2004-11-07 Ben Maurer <bmaurer@ximian.com>
[mono-project.git] / mono / metadata / reflection.c
bloba740d73b50d101b1e027f2739fa75a2c7d7176fa
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
9 */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "image.h"
29 #include "cil-coff.h"
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
32 #include "private.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
41 typedef struct {
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
46 MonoArray *pinfo;
47 MonoArray *opt_types;
48 guint32 attrs;
49 guint32 iattrs;
50 guint32 call_conv;
51 guint32 *table_idx; /* note: it's a pointer */
52 MonoArray *code;
53 MonoObject *type;
54 MonoString *name;
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
61 MonoMethod *mhandle;
62 guint32 nrefs;
63 gpointer *refs;
64 /* for PInvoke */
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
69 typedef struct {
70 guint32 owner;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
75 MONO_MODULE_SIZE,
76 MONO_TYPEREF_SIZE,
77 MONO_TYPEDEF_SIZE,
79 MONO_FIELD_SIZE,
81 MONO_METHOD_SIZE,
83 MONO_PARAM_SIZE,
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
86 MONO_CONSTANT_SIZE,
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
93 MONO_EVENT_MAP_SIZE,
95 MONO_EVENT_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
98 MONO_PROPERTY_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
102 MONO_TYPESPEC_SIZE,
103 MONO_IMPLMAP_SIZE,
104 MONO_FIELD_RVA_SIZE,
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
113 MONO_FILE_SIZE,
114 MONO_EXP_TYPE_SIZE,
115 MONO_MANIFEST_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
122 0 /* 0x2D */
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
128 * than g_malloc.
130 #ifdef HAVE_BOEHM_GC
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
134 #else
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
138 #endif
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
159 static void
160 alloc_table (MonoDynamicTable *table, guint nrows)
162 table->rows = nrows;
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows) {
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
168 else
169 table->alloc_rows *= 2;
172 if (table->values)
173 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
174 else
175 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
179 static void
180 make_room_in_stream (MonoDynamicStream *stream, int size)
182 while (stream->alloc_size <= size) {
183 if (stream->alloc_size < 4096)
184 stream->alloc_size = 4096;
185 else
186 stream->alloc_size *= 2;
188 if (stream->data)
189 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
190 else
191 stream->data = ALLOC_ATOMIC (stream->alloc_size);
194 static guint32
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
197 guint32 idx;
198 guint32 len;
199 gpointer oldkey, oldval;
201 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202 return GPOINTER_TO_UINT (oldval);
204 len = strlen (str) + 1;
205 idx = sh->index;
206 if (idx + len > sh->alloc_size)
207 make_room_in_stream (sh, idx + len);
210 * We strdup the string even if we already copy them in sh->data
211 * so that the string pointers in the hash remain valid even if
212 * we need to realloc sh->data. We may want to avoid that later.
214 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215 memcpy (sh->data + idx, str, len);
216 sh->index += len;
217 return idx;
220 static void
221 string_heap_init (MonoDynamicStream *sh)
223 sh->index = 0;
224 sh->alloc_size = 4096;
225 sh->data = ALLOC_ATOMIC (4096);
226 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227 string_heap_insert (sh, "");
230 #if 0 /* never used */
231 static void
232 string_heap_free (MonoDynamicStream *sh)
234 FREE_ATOMIC (sh->data);
235 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236 g_hash_table_destroy (sh->hash);
238 #endif
240 static guint32
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
243 guint32 idx;
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memcpy (stream->data + stream->index, data, len);
247 idx = stream->index;
248 stream->index += len;
250 * align index? Not without adding an additional param that controls it since
251 * we may store a blob value in pieces.
253 return idx;
256 static guint32
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
259 guint32 idx;
260 if (stream->alloc_size < stream->index + len)
261 make_room_in_stream (stream, stream->index + len);
262 memset (stream->data + stream->index, 0, len);
263 idx = stream->index;
264 stream->index += len;
265 return idx;
268 static void
269 stream_data_align (MonoDynamicStream *stream)
271 char buf [4] = {0};
272 guint32 count = stream->index % 4;
274 /* we assume the stream data will be aligned */
275 if (count)
276 mono_image_add_stream_data (stream, buf, 4 - count);
279 static int
280 mono_blob_entry_hash (const char* str)
282 guint len, h;
283 const char *end;
284 len = mono_metadata_decode_blob_size (str, &str);
285 if (len > 0) {
286 end = str + len;
287 h = *str;
288 for (str += 1; str < end; str++)
289 h = (h << 5) - h + *str;
290 return h;
291 } else {
292 return 0;
296 static gboolean
297 mono_blob_entry_equal (const char *str1, const char *str2) {
298 int len, len2;
299 const char *end1;
300 const char *end2;
301 len = mono_metadata_decode_blob_size (str1, &end1);
302 len2 = mono_metadata_decode_blob_size (str2, &end2);
303 if (len != len2)
304 return 0;
305 return memcmp (end1, end2, len) == 0;
308 static guint32
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
311 guint32 idx;
312 char *copy;
313 gpointer oldkey, oldval;
315 copy = ALLOC_ATOMIC (s1+s2);
316 memcpy (copy, b1, s1);
317 memcpy (copy + s1, b2, s2);
318 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
319 FREE_ATOMIC (copy);
320 idx = GPOINTER_TO_UINT (oldval);
321 } else {
322 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323 mono_image_add_stream_data (&assembly->blob, b2, s2);
324 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
326 return idx;
330 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331 * dest may be misaligned.
333 static void
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
336 int elem;
338 for (elem = 0; elem < nelem; ++elem) {
339 switch (len) {
340 case 1:
341 *dest = *val;
342 break;
343 case 2:
344 dest [0] = val [1];
345 dest [1] = val [0];
346 break;
347 case 4:
348 dest [0] = val [3];
349 dest [1] = val [2];
350 dest [2] = val [1];
351 dest [3] = val [0];
352 break;
353 case 8:
354 dest [0] = val [7];
355 dest [1] = val [6];
356 dest [2] = val [5];
357 dest [3] = val [4];
358 dest [4] = val [3];
359 dest [5] = val [2];
360 dest [6] = val [1];
361 dest [7] = val [0];
362 break;
363 default:
364 g_assert_not_reached ();
366 dest += len;
367 val += len;
369 #else
370 memcpy (dest, val, len * nelem);
371 #endif
374 static guint32
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
377 char blob_size [64];
378 char *b = blob_size;
379 guint32 idx = 0, len;
381 len = str->length * 2;
382 mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
385 char *swapped = g_malloc (2 * mono_string_length (str));
386 const char *p = (const char*)mono_string_chars (str);
388 swap_with_size (swapped, p, 2, mono_string_length (str));
389 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
390 g_free (swapped);
392 #else
393 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
394 #endif
395 return idx;
398 /* modified version needed to handle building corlib */
399 static MonoClass*
400 my_mono_class_from_mono_type (MonoType *type) {
401 switch (type->type) {
402 case MONO_TYPE_ARRAY:
403 case MONO_TYPE_PTR:
404 case MONO_TYPE_SZARRAY:
405 case MONO_TYPE_GENERICINST:
406 return mono_class_from_mono_type (type);
407 case MONO_TYPE_VAR:
408 case MONO_TYPE_MVAR:
409 g_assert (type->data.generic_param->pklass);
410 return type->data.generic_param->pklass;
411 default:
412 /* should be always valid when we reach this case... */
413 return type->data.klass;
417 static MonoClass *
418 default_class_from_mono_type (MonoType *type)
420 switch (type->type) {
421 case MONO_TYPE_OBJECT:
422 return mono_defaults.object_class;
423 case MONO_TYPE_VOID:
424 return mono_defaults.void_class;
425 case MONO_TYPE_BOOLEAN:
426 return mono_defaults.boolean_class;
427 case MONO_TYPE_CHAR:
428 return mono_defaults.char_class;
429 case MONO_TYPE_I1:
430 return mono_defaults.sbyte_class;
431 case MONO_TYPE_U1:
432 return mono_defaults.byte_class;
433 case MONO_TYPE_I2:
434 return mono_defaults.int16_class;
435 case MONO_TYPE_U2:
436 return mono_defaults.uint16_class;
437 case MONO_TYPE_I4:
438 return mono_defaults.int32_class;
439 case MONO_TYPE_U4:
440 return mono_defaults.uint32_class;
441 case MONO_TYPE_I:
442 return mono_defaults.int_class;
443 case MONO_TYPE_U:
444 return mono_defaults.uint_class;
445 case MONO_TYPE_I8:
446 return mono_defaults.int64_class;
447 case MONO_TYPE_U8:
448 return mono_defaults.uint64_class;
449 case MONO_TYPE_R4:
450 return mono_defaults.single_class;
451 case MONO_TYPE_R8:
452 return mono_defaults.double_class;
453 case MONO_TYPE_STRING:
454 return mono_defaults.string_class;
455 default:
456 g_warning ("implement me 0x%02x\n", type->type);
457 g_assert_not_reached ();
460 return NULL;
463 static void
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
466 int i;
468 if (!ginst) {
469 g_assert_not_reached ();
470 return;
473 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474 encode_type (assembly, ginst->generic_type, p, &p);
475 mono_metadata_encode_value (ginst->type_argc, p, &p);
476 for (i = 0; i < ginst->type_argc; ++i)
477 encode_type (assembly, ginst->type_argv [i], p, &p);
479 *endbuf = p;
482 static void
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
485 if (!type) {
486 g_assert_not_reached ();
487 return;
490 if (type->byref)
491 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
493 switch (type->type){
494 case MONO_TYPE_VOID:
495 case MONO_TYPE_BOOLEAN:
496 case MONO_TYPE_CHAR:
497 case MONO_TYPE_I1:
498 case MONO_TYPE_U1:
499 case MONO_TYPE_I2:
500 case MONO_TYPE_U2:
501 case MONO_TYPE_I4:
502 case MONO_TYPE_U4:
503 case MONO_TYPE_I8:
504 case MONO_TYPE_U8:
505 case MONO_TYPE_R4:
506 case MONO_TYPE_R8:
507 case MONO_TYPE_I:
508 case MONO_TYPE_U:
509 case MONO_TYPE_STRING:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_TYPEDBYREF:
512 mono_metadata_encode_value (type->type, p, &p);
513 break;
514 case MONO_TYPE_PTR:
515 mono_metadata_encode_value (type->type, p, &p);
516 encode_type (assembly, type->data.type, p, &p);
517 break;
518 case MONO_TYPE_SZARRAY:
519 mono_metadata_encode_value (type->type, p, &p);
520 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
521 break;
522 case MONO_TYPE_VALUETYPE:
523 case MONO_TYPE_CLASS: {
524 MonoClass *k = mono_class_from_mono_type (type);
525 mono_metadata_encode_value (type->type, p, &p);
527 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528 * otherwise two typerefs could point to the same type, leading to
529 * verification errors.
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
532 break;
534 case MONO_TYPE_ARRAY:
535 mono_metadata_encode_value (type->type, p, &p);
536 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537 mono_metadata_encode_value (type->data.array->rank, p, &p);
538 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539 mono_metadata_encode_value (0, p, &p);
540 break;
541 case MONO_TYPE_GENERICINST:
542 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
543 break;
544 case MONO_TYPE_VAR:
545 case MONO_TYPE_MVAR:
546 mono_metadata_encode_value (type->type, p, &p);
547 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
548 break;
549 default:
550 g_error ("need to encode type %x", type->type);
552 *endbuf = p;
555 static void
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
558 if (!type) {
559 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
560 return;
562 if (type->type) {
563 encode_type (assembly, type->type, p, endbuf);
564 return;
567 g_assert_not_reached ();
571 static void
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
574 int i;
576 if (modreq) {
577 for (i = 0; i < mono_array_length (modreq); ++i) {
578 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_REQD;
580 p++;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
584 if (modopt) {
585 for (i = 0; i < mono_array_length (modopt); ++i) {
586 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587 *p = MONO_TYPE_CMOD_OPT;
588 p++;
589 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
592 *endbuf = p;
595 static guint32
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
598 guint32 size = 0;
599 int i;
601 if (!ginst) {
602 g_assert_not_reached ();
605 size += 1 + type_get_signature_size (ginst->generic_type);
606 size += 4;
607 for (i = 0; i < ginst->type_argc; ++i)
608 size += type_get_signature_size (ginst->type_argv [i]);
610 return size;
613 static guint32
614 type_get_signature_size (MonoType *type)
616 guint32 size = 0;
618 if (!type) {
619 g_assert_not_reached ();
622 if (type->byref)
623 size++;
625 switch (type->type){
626 case MONO_TYPE_VOID:
627 case MONO_TYPE_BOOLEAN:
628 case MONO_TYPE_CHAR:
629 case MONO_TYPE_I1:
630 case MONO_TYPE_U1:
631 case MONO_TYPE_I2:
632 case MONO_TYPE_U2:
633 case MONO_TYPE_I4:
634 case MONO_TYPE_U4:
635 case MONO_TYPE_I8:
636 case MONO_TYPE_U8:
637 case MONO_TYPE_R4:
638 case MONO_TYPE_R8:
639 case MONO_TYPE_I:
640 case MONO_TYPE_U:
641 case MONO_TYPE_STRING:
642 case MONO_TYPE_OBJECT:
643 case MONO_TYPE_TYPEDBYREF:
644 return size + 1;
645 case MONO_TYPE_PTR:
646 return size + 1 + type_get_signature_size (type->data.type);
647 case MONO_TYPE_SZARRAY:
648 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS:
651 return size + 5;
652 case MONO_TYPE_ARRAY:
653 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654 case MONO_TYPE_GENERICINST:
655 return size + generic_inst_get_signature_size (type->data.generic_inst);
656 case MONO_TYPE_VAR:
657 case MONO_TYPE_MVAR:
658 return size + 5;
659 default:
660 g_error ("need to encode type %x", type->type);
661 return size;
665 static guint32
666 method_get_signature_size (MonoMethodSignature *sig)
668 guint32 size;
669 int i;
671 size = type_get_signature_size (sig->ret);
672 for (i = 0; i < sig->param_count; i++)
673 size += type_get_signature_size (sig->params [i]);
675 if (sig->generic_param_count)
676 size += 4;
677 if (sig->sentinelpos >= 0)
678 size++;
680 return size;
683 static guint32
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
686 char *buf;
687 char *p;
688 int i;
689 guint32 nparams = sig->param_count;
690 guint32 size = 11 + method_get_signature_size (sig);
691 guint32 idx;
692 char blob_size [6];
693 char *b = blob_size;
695 if (!assembly->save)
696 return 0;
698 p = buf = g_malloc (size);
700 * FIXME: vararg, explicit_this, differenc call_conv values...
702 *p = sig->call_convention;
703 if (sig->hasthis)
704 *p |= 0x20; /* hasthis */
705 if (sig->generic_param_count)
706 *p |= 0x10; /* generic */
707 p++;
708 if (sig->generic_param_count)
709 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710 mono_metadata_encode_value (nparams, p, &p);
711 encode_type (assembly, sig->ret, p, &p);
712 for (i = 0; i < nparams; ++i) {
713 if (i == sig->sentinelpos)
714 *p++ = MONO_TYPE_SENTINEL;
715 encode_type (assembly, sig->params [i], p, &p);
717 /* store length */
718 g_assert (p - buf < size);
719 mono_metadata_encode_value (p-buf, b, &b);
720 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
721 g_free (buf);
722 return idx;
725 static guint32
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
729 * FIXME: reuse code from method_encode_signature().
731 char *buf;
732 char *p;
733 int i;
734 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
735 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737 guint32 size = 21 + nparams * 20 + notypes * 20;
738 guint32 idx;
739 char blob_size [6];
740 char *b = blob_size;
742 p = buf = g_malloc (size);
743 /* LAMESPEC: all the call conv spec is foobared */
744 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745 if (mb->call_conv & 2)
746 *p |= 0x5; /* vararg */
747 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748 *p |= 0x20; /* hasthis */
749 if (ngparams)
750 *p |= 0x10; /* generic */
751 p++;
752 if (ngparams)
753 mono_metadata_encode_value (ngparams, p, &p);
754 mono_metadata_encode_value (nparams + notypes, p, &p);
755 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756 encode_reflection_type (assembly, mb->rtype, p, &p);
757 for (i = 0; i < nparams; ++i) {
758 MonoArray *modreq = NULL;
759 MonoArray *modopt = NULL;
760 MonoReflectionType *pt;
762 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
770 if (notypes)
771 *p++ = MONO_TYPE_SENTINEL;
772 for (i = 0; i < notypes; ++i) {
773 MonoReflectionType *pt;
775 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776 encode_reflection_type (assembly, pt, p, &p);
779 /* store length */
780 g_assert (p - buf < size);
781 mono_metadata_encode_value (p-buf, b, &b);
782 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
783 g_free (buf);
784 return idx;
787 static guint32
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
790 MonoDynamicTable *table;
791 guint32 *values;
792 char *p;
793 guint32 idx, sig_idx, size;
794 guint nl = mono_array_length (ilgen->locals);
795 char *buf;
796 char blob_size [6];
797 char *b = blob_size;
798 int i;
800 size = 10 + nl * 10;
801 p = buf = g_malloc (size);
802 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803 idx = table->next_idx ++;
804 table->rows ++;
805 alloc_table (table, table->rows);
806 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
808 mono_metadata_encode_value (0x07, p, &p);
809 mono_metadata_encode_value (nl, p, &p);
810 for (i = 0; i < nl; ++i) {
811 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
813 if (lb->is_pinned)
814 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
816 encode_reflection_type (assembly, lb->type, p, &p);
818 g_assert (p - buf < size);
819 mono_metadata_encode_value (p-buf, b, &b);
820 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
821 g_free (buf);
823 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
825 return idx;
828 static guint32
829 method_count_clauses (MonoReflectionILGen *ilgen)
831 guint32 num_clauses = 0;
832 int i;
834 MonoILExceptionInfo *ex_info;
835 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 if (ex_info->handlers)
838 num_clauses += mono_array_length (ex_info->handlers);
839 else
840 num_clauses++;
843 return num_clauses;
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
849 MonoExceptionClause *clauses;
850 MonoExceptionClause *clause;
851 MonoILExceptionInfo *ex_info;
852 MonoILExceptionBlock *ex_block;
853 guint32 finally_start;
854 int i, j, clause_index;;
856 clauses = g_new0 (MonoExceptionClause, num_clauses);
858 clause_index = 0;
859 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861 finally_start = ex_info->start + ex_info->len;
862 g_assert (ex_info->handlers);
863 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865 clause = &(clauses [clause_index]);
867 clause->flags = ex_block->type;
868 clause->try_offset = ex_info->start;
870 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871 clause->try_len = finally_start - ex_info->start;
872 else
873 clause->try_len = ex_info->len;
874 clause->handler_offset = ex_block->start;
875 clause->handler_len = ex_block->len;
876 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878 if (ex_block->extype) {
879 mono_g_hash_table_insert (assembly->tokens,
880 GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
882 finally_start = ex_block->start + ex_block->len;
884 clause_index ++;
888 return clauses;
891 static guint32
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
894 char flags = 0;
895 guint32 idx;
896 guint32 code_size;
897 gint32 max_stack, i;
898 gint32 num_locals = 0;
899 gint32 num_exception = 0;
900 gint maybe_small;
901 guint32 fat_flags;
902 char fat_header [12];
903 guint32 *intp;
904 guint16 *shortp;
905 guint32 local_sig = 0;
906 guint32 header_size = 12;
907 MonoArray *code;
909 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
911 return 0;
913 /*if (mb->name)
914 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
915 if (mb->ilgen) {
916 code = mb->ilgen->code;
917 code_size = mb->ilgen->code_len;
918 max_stack = mb->ilgen->max_stack;
919 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920 if (mb->ilgen->ex_handlers)
921 num_exception = method_count_clauses (mb->ilgen);
922 } else {
923 code = mb->code;
924 if (code == NULL){
925 char *name = mono_string_to_utf8 (mb->name);
926 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
928 g_free (str);
929 g_free (name);
930 mono_raise_exception (exception);
933 code_size = mono_array_length (code);
934 max_stack = 8; /* we probably need to run a verifier on the code... */
937 stream_data_align (&assembly->code);
939 /* check for exceptions, maxstack, locals */
940 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
941 if (maybe_small) {
942 if (code_size < 64 && !(code_size & 1)) {
943 flags = (code_size << 2) | 0x2;
944 } else if (code_size < 32 && (code_size & 1)) {
945 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
946 } else {
947 goto fat_header;
949 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
953 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
954 return assembly->text_rva + idx;
956 fat_header:
957 if (num_locals)
958 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
960 * FIXME: need to set also the header size in fat_flags.
961 * (and more sects and init locals flags)
963 fat_flags = 0x03;
964 if (num_exception)
965 fat_flags |= METHOD_HEADER_MORE_SECTS;
966 if (mb->init_locals)
967 fat_flags |= METHOD_HEADER_INIT_LOCALS;
968 fat_header [0] = fat_flags;
969 fat_header [1] = (header_size / 4 ) << 4;
970 shortp = (guint16*)(fat_header + 2);
971 *shortp = GUINT16_TO_LE (max_stack);
972 intp = (guint32*)(fat_header + 4);
973 *intp = GUINT32_TO_LE (code_size);
974 intp = (guint32*)(fat_header + 8);
975 *intp = GUINT32_TO_LE (local_sig);
976 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
977 /* add to the fixup todo list */
978 if (mb->ilgen && mb->ilgen->num_token_fixups)
979 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
982 if (num_exception) {
983 unsigned char sheader [4];
984 MonoExceptionClause clause;
985 MonoILExceptionInfo * ex_info;
986 MonoILExceptionBlock * ex_block;
987 int j;
989 stream_data_align (&assembly->code);
990 /* always use fat format for now */
991 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
992 num_exception *= sizeof (MonoExceptionClause);
993 num_exception += 4; /* include the size of the header */
994 sheader [1] = num_exception & 0xff;
995 sheader [2] = (num_exception >> 8) & 0xff;
996 sheader [3] = (num_exception >> 16) & 0xff;
997 mono_image_add_stream_data (&assembly->code, sheader, 4);
998 /* fat header, so we are already aligned */
999 /* reverse order */
1000 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1001 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1002 if (ex_info->handlers) {
1003 int finally_start = ex_info->start + ex_info->len;
1004 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1005 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1006 clause.flags = GUINT32_TO_LE (ex_block->type);
1007 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1008 /* need fault, too, probably */
1009 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1010 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1011 else
1012 clause.try_len = GUINT32_TO_LE (ex_info->len);
1013 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1014 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1015 finally_start = ex_block->start + ex_block->len;
1016 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1017 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1018 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1019 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1020 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1021 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1023 } else {
1024 g_error ("No clauses for ex info block %d", i);
1028 return assembly->text_rva + idx;
1031 static guint32
1032 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1034 int i;
1035 MonoDynamicTable *table;
1036 guint32 *values;
1038 table = &assembly->tables [table_idx];
1040 g_assert (col < table->columns);
1042 values = table->values + table->columns;
1043 for (i = 1; i <= table->rows; ++i) {
1044 if (values [col] == token)
1045 return i;
1046 values += table->columns;
1048 return 0;
1051 static GHashTable *dynamic_custom_attrs = NULL;
1053 static MonoCustomAttrInfo*
1054 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1056 int i, count;
1057 MonoCustomAttrInfo *ainfo;
1058 MonoReflectionCustomAttr *cattr;
1060 if (!cattrs)
1061 return NULL;
1062 /* FIXME: check in assembly the Run flag is set */
1064 count = mono_array_length (cattrs);
1066 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1068 ainfo->image = image;
1069 ainfo->num_attrs = count;
1070 for (i = 0; i < count; ++i) {
1071 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1072 ainfo->attrs [i].ctor = cattr->ctor->method;
1073 /* FIXME: might want to memdup the data here */
1074 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1075 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1078 return ainfo;
1081 static void
1082 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1084 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1086 if (!ainfo)
1087 return;
1089 if (!dynamic_custom_attrs)
1090 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1092 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1093 ainfo->cached = TRUE;
1096 void
1097 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1099 /* they are cached, so we don't free them */
1100 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1101 return;
1102 g_free (ainfo);
1106 * idx is the table index of the object
1107 * type is one of MONO_CUSTOM_ATTR_*
1109 static void
1110 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1112 MonoDynamicTable *table;
1113 MonoReflectionCustomAttr *cattr;
1114 guint32 *values;
1115 guint32 count, i, token;
1116 char blob_size [6];
1117 char *p = blob_size;
1119 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1120 if (!cattrs)
1121 return;
1122 count = mono_array_length (cattrs);
1123 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1124 table->rows += count;
1125 alloc_table (table, table->rows);
1126 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1127 idx <<= MONO_CUSTOM_ATTR_BITS;
1128 idx |= type;
1129 for (i = 0; i < count; ++i) {
1130 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1131 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1132 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1133 type = mono_metadata_token_index (token);
1134 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1135 switch (mono_metadata_token_table (token)) {
1136 case MONO_TABLE_METHOD:
1137 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1138 break;
1139 case MONO_TABLE_MEMBERREF:
1140 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1141 break;
1142 default:
1143 g_warning ("got wrong token in custom attr");
1144 continue;
1146 values [MONO_CUSTOM_ATTR_TYPE] = type;
1147 p = blob_size;
1148 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1149 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1150 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1151 values += MONO_CUSTOM_ATTR_SIZE;
1152 ++table->next_idx;
1156 static void
1157 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1159 MonoDynamicTable *table;
1160 guint32 *values;
1161 guint32 count, i, idx;
1162 MonoReflectionPermissionSet *perm;
1164 if (!permissions)
1165 return;
1167 count = mono_array_length (permissions);
1168 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1169 table->rows += count;
1170 alloc_table (table, table->rows);
1172 for (i = 0; i < mono_array_length (permissions); ++i) {
1173 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1175 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1177 idx = mono_metadata_token_index (parent_token);
1178 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1179 switch (mono_metadata_token_table (parent_token)) {
1180 case MONO_TABLE_TYPEDEF:
1181 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1182 break;
1183 case MONO_TABLE_METHOD:
1184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1185 break;
1186 case MONO_TABLE_ASSEMBLY:
1187 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1188 break;
1189 default:
1190 g_assert_not_reached ();
1193 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1194 values [MONO_DECL_SECURITY_PARENT] = idx;
1195 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1197 ++table->next_idx;
1202 * Fill in the MethodDef and ParamDef tables for a method.
1203 * This is used for both normal methods and constructors.
1205 static void
1206 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1208 MonoDynamicTable *table;
1209 guint32 *values;
1210 char *name;
1211 guint i, count;
1213 /* room in this table is already allocated */
1214 table = &assembly->tables [MONO_TABLE_METHOD];
1215 *mb->table_idx = table->next_idx ++;
1216 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1217 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1218 name = mono_string_to_utf8 (mb->name);
1219 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1220 g_free (name);
1221 values [MONO_METHOD_FLAGS] = mb->attrs;
1222 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1223 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1224 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1226 table = &assembly->tables [MONO_TABLE_PARAM];
1227 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1229 mono_image_add_decl_security (assembly,
1230 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1232 if (mb->pinfo) {
1233 MonoDynamicTable *mtable;
1234 guint32 *mvalues;
1236 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1237 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1239 count = 0;
1240 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1241 if (mono_array_get (mb->pinfo, gpointer, i))
1242 count++;
1244 table->rows += count;
1245 alloc_table (table, table->rows);
1246 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1247 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1248 MonoReflectionParamBuilder *pb;
1249 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1250 values [MONO_PARAM_FLAGS] = pb->attrs;
1251 values [MONO_PARAM_SEQUENCE] = i;
1252 if (pb->name != NULL) {
1253 name = mono_string_to_utf8 (pb->name);
1254 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1255 g_free (name);
1256 } else {
1257 values [MONO_PARAM_NAME] = 0;
1259 values += MONO_PARAM_SIZE;
1260 if (pb->marshal_info) {
1261 mtable->rows++;
1262 alloc_table (mtable, mtable->rows);
1263 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1264 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1265 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1267 pb->table_idx = table->next_idx++;
1268 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1269 guint32 field_type = 0;
1270 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1271 mtable->rows ++;
1272 alloc_table (mtable, mtable->rows);
1273 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1274 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1275 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1276 mvalues [MONO_CONSTANT_TYPE] = field_type;
1277 mvalues [MONO_CONSTANT_PADDING] = 0;
1284 static void
1285 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mb->rtype;
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = mb->generic_params;
1291 rmb->opt_types = NULL;
1292 rmb->pinfo = mb->pinfo;
1293 rmb->attrs = mb->attrs;
1294 rmb->iattrs = mb->iattrs;
1295 rmb->call_conv = mb->call_conv;
1296 rmb->code = mb->code;
1297 rmb->type = mb->type;
1298 rmb->name = mb->name;
1299 rmb->table_idx = &mb->table_idx;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = mb->return_modreq;
1302 rmb->return_modopt = mb->return_modopt;
1303 rmb->param_modreq = mb->param_modreq;
1304 rmb->param_modopt = mb->param_modopt;
1305 rmb->permissions = mb->permissions;
1306 rmb->mhandle = mb->mhandle;
1307 rmb->nrefs = 0;
1308 rmb->refs = NULL;
1310 if (mb->dll) {
1311 rmb->charset = rmb->charset & 0xf;
1312 rmb->lasterr = rmb->charset & 0x40;
1313 rmb->native_cc = rmb->native_cc;
1314 rmb->dllentry = mb->dllentry;
1315 rmb->dll = mb->dll;
1319 static void
1320 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1322 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1324 rmb->ilgen = mb->ilgen;
1325 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1326 rmb->parameters = mb->parameters;
1327 rmb->generic_params = NULL;
1328 rmb->opt_types = NULL;
1329 rmb->pinfo = mb->pinfo;
1330 rmb->attrs = mb->attrs;
1331 rmb->iattrs = mb->iattrs;
1332 rmb->call_conv = mb->call_conv;
1333 rmb->code = NULL;
1334 rmb->type = mb->type;
1335 rmb->name = mono_string_new (mono_domain_get (), name);
1336 rmb->table_idx = &mb->table_idx;
1337 rmb->init_locals = mb->init_locals;
1338 rmb->return_modreq = NULL;
1339 rmb->return_modopt = NULL;
1340 rmb->param_modreq = mb->param_modreq;
1341 rmb->param_modopt = mb->param_modopt;
1342 rmb->permissions = mb->permissions;
1343 rmb->mhandle = mb->mhandle;
1344 rmb->nrefs = 0;
1345 rmb->refs = NULL;
1348 static void
1349 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = NULL;
1355 rmb->opt_types = NULL;
1356 rmb->pinfo = NULL;
1357 rmb->attrs = mb->attrs;
1358 rmb->iattrs = 0;
1359 rmb->call_conv = mb->call_conv;
1360 rmb->code = NULL;
1361 rmb->type = NULL;
1362 rmb->name = mb->name;
1363 rmb->table_idx = NULL;
1364 rmb->init_locals = mb->init_locals;
1365 rmb->return_modreq = NULL;
1366 rmb->return_modopt = NULL;
1367 rmb->param_modreq = NULL;
1368 rmb->param_modopt = NULL;
1369 rmb->permissions = NULL;
1370 rmb->mhandle = mb->mhandle;
1371 rmb->nrefs = 0;
1372 rmb->refs = NULL;
1375 static void
1376 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1378 MonoDynamicTable *table;
1379 guint32 *values;
1380 char *name;
1381 ReflectionMethodBuilder rmb;
1382 int i;
1384 reflection_methodbuilder_from_method_builder (&rmb, mb);
1386 mono_image_basic_method (&rmb, assembly);
1388 if (mb->dll) { /* It's a P/Invoke method */
1389 guint32 moduleref;
1390 int charset = mb->charset & 0xf;
1391 int lasterr = mb->charset & 0x40;
1392 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1393 table->rows ++;
1394 alloc_table (table, table->rows);
1395 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1396 /* map CharSet values to on-disk values */
1398 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1399 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1400 name = mono_string_to_utf8 (mb->dllentry);
1401 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1402 g_free (name);
1403 name = mono_string_to_utf8 (mb->dll);
1404 moduleref = string_heap_insert (&assembly->sheap, name);
1405 g_free (name);
1406 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1407 table = &assembly->tables [MONO_TABLE_MODULEREF];
1408 table->rows ++;
1409 alloc_table (table, table->rows);
1410 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1411 values [MONO_IMPLMAP_SCOPE] = table->rows;
1415 if (mb->override_method) {
1416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1417 guint32 tok;
1418 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1419 table->rows ++;
1420 alloc_table (table, table->rows);
1421 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1422 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1423 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1425 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1426 switch (mono_metadata_token_table (tok)) {
1427 case MONO_TABLE_MEMBERREF:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1429 break;
1430 case MONO_TABLE_METHOD:
1431 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1432 break;
1433 default:
1434 g_assert_not_reached ();
1436 values [MONO_METHODIMPL_DECLARATION] = tok;
1439 if (mb->generic_params) {
1440 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1441 table->rows += mono_array_length (mb->generic_params);
1442 alloc_table (table, table->rows);
1443 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1444 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1446 mono_image_get_generic_param_info (
1447 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1453 static void
1454 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1456 ReflectionMethodBuilder rmb;
1458 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1460 mono_image_basic_method (&rmb, assembly);
1463 static char*
1464 type_get_fully_qualified_name (MonoType *type) {
1465 char *name, *result;
1466 MonoClass *klass;
1467 MonoAssembly *ta;
1469 name = mono_type_get_name (type);
1470 klass = my_mono_class_from_mono_type (type);
1471 ta = klass->image->assembly;
1473 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1474 name, ta->aname.name,
1475 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1476 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1477 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1478 g_free (name);
1479 return result;
1482 static char*
1483 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1484 MonoClass *klass;
1485 MonoAssembly *ta;
1487 klass = my_mono_class_from_mono_type (type);
1488 if (!klass)
1489 return mono_type_get_name (type);
1490 ta = klass->image->assembly;
1491 if (ta == ass || klass->image == mono_defaults.corlib)
1492 return mono_type_get_name (type);
1494 return type_get_fully_qualified_name (type);
1497 static guint32
1498 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1500 char blob_size [64];
1501 char *b = blob_size;
1502 char *p;
1503 char* buf;
1504 guint32 idx;
1506 if (!assembly->save)
1507 return 0;
1509 p = buf = g_malloc (64);
1511 mono_metadata_encode_value (0x06, p, &p);
1512 /* encode custom attributes before the type */
1513 encode_type (assembly, type, p, &p);
1514 g_assert (p-buf < 64);
1515 mono_metadata_encode_value (p-buf, b, &b);
1516 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1517 g_free (buf);
1518 return idx;
1521 static guint32
1522 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1524 char blob_size [64];
1525 char *b = blob_size;
1526 char *p;
1527 char* buf;
1528 guint32 idx;
1530 p = buf = g_malloc (64);
1532 mono_metadata_encode_value (0x06, p, &p);
1533 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1534 /* encode custom attributes before the type */
1535 encode_reflection_type (assembly, fb->type, p, &p);
1536 g_assert (p-buf < 64);
1537 mono_metadata_encode_value (p-buf, b, &b);
1538 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1539 g_free (buf);
1540 return idx;
1543 static guint32
1544 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1545 char blob_size [64];
1546 char *b = blob_size;
1547 char *p, *box_val;
1548 char* buf;
1549 guint32 idx = 0, len = 0, dummy = 0;
1551 p = buf = g_malloc (64);
1552 if (!val) {
1553 *ret_type = MONO_TYPE_CLASS;
1554 len = 4;
1555 box_val = (char*)&dummy;
1556 } else {
1557 box_val = ((char*)val) + sizeof (MonoObject);
1558 *ret_type = val->vtable->klass->byval_arg.type;
1560 handle_enum:
1561 switch (*ret_type) {
1562 case MONO_TYPE_BOOLEAN:
1563 case MONO_TYPE_U1:
1564 case MONO_TYPE_I1:
1565 len = 1;
1566 break;
1567 case MONO_TYPE_CHAR:
1568 case MONO_TYPE_U2:
1569 case MONO_TYPE_I2:
1570 len = 2;
1571 break;
1572 case MONO_TYPE_U4:
1573 case MONO_TYPE_I4:
1574 case MONO_TYPE_R4:
1575 len = 4;
1576 break;
1577 case MONO_TYPE_U8:
1578 case MONO_TYPE_I8:
1579 case MONO_TYPE_R8:
1580 len = 8;
1581 break;
1582 case MONO_TYPE_VALUETYPE:
1583 if (val->vtable->klass->enumtype) {
1584 *ret_type = val->vtable->klass->enum_basetype->type;
1585 goto handle_enum;
1586 } else
1587 g_error ("we can't encode valuetypes");
1588 case MONO_TYPE_CLASS:
1589 break;
1590 case MONO_TYPE_STRING: {
1591 MonoString *str = (MonoString*)val;
1592 /* there is no signature */
1593 len = str->length * 2;
1594 mono_metadata_encode_value (len, b, &b);
1595 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1597 char *swapped = g_malloc (2 * mono_string_length (str));
1598 const char *p = (const char*)mono_string_chars (str);
1600 swap_with_size (swapped, p, 2, mono_string_length (str));
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1602 g_free (swapped);
1604 #else
1605 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1606 #endif
1608 g_free (buf);
1609 return idx;
1611 default:
1612 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1615 /* there is no signature */
1616 mono_metadata_encode_value (len, b, &b);
1617 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1618 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1619 swap_with_size (blob_size, box_val, len, 1);
1620 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1621 #else
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1623 #endif
1625 g_free (buf);
1626 return idx;
1629 static guint32
1630 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1631 char blob_size [64];
1632 char *b = blob_size;
1633 char *p, *buf, *str;
1634 guint32 idx, len, bufsize = 256;
1636 p = buf = g_malloc (bufsize);
1638 switch (minfo->type) {
1639 case MONO_NATIVE_BYVALTSTR:
1640 case MONO_NATIVE_BYVALARRAY:
1641 mono_metadata_encode_value (minfo->type, p, &p);
1642 mono_metadata_encode_value (minfo->count, p, &p);
1643 break;
1644 case MONO_NATIVE_LPARRAY:
1645 mono_metadata_encode_value (minfo->type, p, &p);
1646 if (minfo->eltype || (minfo->count > 0)) {
1647 mono_metadata_encode_value (minfo->eltype, p, &p);
1648 if (minfo->count > 0) {
1649 mono_metadata_encode_value (0, p, &p);
1650 mono_metadata_encode_value (minfo->count, p, &p);
1653 break;
1654 case MONO_NATIVE_CUSTOM:
1655 mono_metadata_encode_value (minfo->type, p, &p);
1656 if (minfo->guid) {
1657 str = mono_string_to_utf8 (minfo->guid);
1658 len = strlen (str);
1659 mono_metadata_encode_value (len, p, &p);
1660 memcpy (p, str, len);
1661 p += len;
1662 g_free (str);
1663 } else {
1664 mono_metadata_encode_value (0, p, &p);
1666 if (minfo->marshaltype) {
1667 str = mono_string_to_utf8 (minfo->marshaltype);
1668 len = strlen (str);
1669 mono_metadata_encode_value (len, p, &p);
1670 if (p + len >= buf + bufsize) {
1671 idx = p - buf;
1672 bufsize *= 2;
1673 buf = g_realloc (buf, bufsize);
1674 p = buf + idx;
1676 memcpy (p, str, len);
1677 p += len;
1678 g_free (str);
1679 } else {
1680 mono_metadata_encode_value (0, p, &p);
1682 if (minfo->marshaltyperef) {
1683 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1684 len = strlen (str);
1685 mono_metadata_encode_value (len, p, &p);
1686 if (p + len >= buf + bufsize) {
1687 idx = p - buf;
1688 bufsize *= 2;
1689 buf = g_realloc (buf, bufsize);
1690 p = buf + idx;
1692 memcpy (p, str, len);
1693 p += len;
1694 g_free (str);
1695 } else {
1696 mono_metadata_encode_value (0, p, &p);
1698 if (minfo->mcookie) {
1699 str = mono_string_to_utf8 (minfo->mcookie);
1700 len = strlen (str);
1701 mono_metadata_encode_value (len, p, &p);
1702 if (p + len >= buf + bufsize) {
1703 idx = p - buf;
1704 bufsize *= 2;
1705 buf = g_realloc (buf, bufsize);
1706 p = buf + idx;
1708 memcpy (p, str, len);
1709 p += len;
1710 g_free (str);
1711 } else {
1712 mono_metadata_encode_value (0, p, &p);
1714 break;
1715 default:
1716 mono_metadata_encode_value (minfo->type, p, &p);
1717 break;
1719 len = p-buf;
1720 mono_metadata_encode_value (len, b, &b);
1721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1722 g_free (buf);
1723 return idx;
1726 static void
1727 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1729 MonoDynamicTable *table;
1730 guint32 *values;
1731 char *name;
1733 /* maybe this fixup should be done in the C# code */
1734 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1735 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1736 table = &assembly->tables [MONO_TABLE_FIELD];
1737 fb->table_idx = table->next_idx ++;
1738 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1739 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1740 name = mono_string_to_utf8 (fb->name);
1741 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1742 g_free (name);
1743 values [MONO_FIELD_FLAGS] = fb->attrs;
1744 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1746 if (fb->offset != -1) {
1747 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1748 table->rows ++;
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1751 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1752 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1754 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1755 guint32 field_type = 0;
1756 table = &assembly->tables [MONO_TABLE_CONSTANT];
1757 table->rows ++;
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1760 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1761 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1762 values [MONO_CONSTANT_TYPE] = field_type;
1763 values [MONO_CONSTANT_PADDING] = 0;
1765 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1766 guint32 rva_idx;
1767 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1768 table->rows ++;
1769 alloc_table (table, table->rows);
1770 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1771 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1773 * We store it in the code section because it's simpler for now.
1775 if (fb->rva_data)
1776 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1777 else
1778 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1779 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1781 if (fb->marshal_info) {
1782 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1783 table->rows ++;
1784 alloc_table (table, table->rows);
1785 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1786 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1787 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1791 static guint32
1792 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1794 char *buf, *p;
1795 char blob_size [6];
1796 char *b = blob_size;
1797 guint32 nparams = 0;
1798 MonoReflectionMethodBuilder *mb = fb->get_method;
1799 MonoReflectionMethodBuilder *smb = fb->set_method;
1800 guint32 idx, i, size;
1802 if (mb && mb->parameters)
1803 nparams = mono_array_length (mb->parameters);
1804 if (!mb && smb && smb->parameters)
1805 nparams = mono_array_length (smb->parameters) - 1;
1806 size = 24 + nparams * 10;
1807 buf = p = g_malloc (size);
1808 *p = 0x08;
1809 p++;
1810 mono_metadata_encode_value (nparams, p, &p);
1811 if (mb) {
1812 encode_reflection_type (assembly, mb->rtype, p, &p);
1813 for (i = 0; i < nparams; ++i) {
1814 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1815 encode_reflection_type (assembly, pt, p, &p);
1817 } else {
1818 /* the property type is the last param */
1819 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1820 for (i = 0; i < nparams; ++i) {
1821 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1822 encode_reflection_type (assembly, pt, p, &p);
1825 /* store length */
1826 g_assert (p - buf < size);
1827 mono_metadata_encode_value (p-buf, b, &b);
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1829 g_free (buf);
1830 return idx;
1833 static void
1834 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1836 MonoDynamicTable *table;
1837 guint32 *values;
1838 char *name;
1839 guint num_methods = 0;
1840 guint32 semaidx;
1843 * we need to set things in the following tables:
1844 * PROPERTYMAP (info already filled in _get_type_info ())
1845 * PROPERTY (rows already preallocated in _get_type_info ())
1846 * METHOD (method info already done with the generic method code)
1847 * METHODSEMANTICS
1849 table = &assembly->tables [MONO_TABLE_PROPERTY];
1850 pb->table_idx = table->next_idx ++;
1851 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1852 name = mono_string_to_utf8 (pb->name);
1853 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1854 g_free (name);
1855 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1856 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1858 /* FIXME: we still don't handle 'other' methods */
1859 if (pb->get_method) num_methods ++;
1860 if (pb->set_method) num_methods ++;
1862 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1863 table->rows += num_methods;
1864 alloc_table (table, table->rows);
1866 if (pb->get_method) {
1867 semaidx = table->next_idx ++;
1868 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1869 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1870 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1871 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1873 if (pb->set_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1882 static void
1883 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1885 MonoDynamicTable *table;
1886 guint32 *values;
1887 char *name;
1888 guint num_methods = 0;
1889 guint32 semaidx;
1892 * we need to set things in the following tables:
1893 * EVENTMAP (info already filled in _get_type_info ())
1894 * EVENT (rows already preallocated in _get_type_info ())
1895 * METHOD (method info already done with the generic method code)
1896 * METHODSEMANTICS
1898 table = &assembly->tables [MONO_TABLE_EVENT];
1899 eb->table_idx = table->next_idx ++;
1900 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1901 name = mono_string_to_utf8 (eb->name);
1902 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1903 g_free (name);
1904 values [MONO_EVENT_FLAGS] = eb->attrs;
1905 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1908 * FIXME: we still don't handle 'other' methods
1910 if (eb->add_method) num_methods ++;
1911 if (eb->remove_method) num_methods ++;
1912 if (eb->raise_method) num_methods ++;
1914 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1915 table->rows += num_methods;
1916 alloc_table (table, table->rows);
1918 if (eb->add_method) {
1919 semaidx = table->next_idx ++;
1920 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1921 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1922 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1923 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1925 if (eb->remove_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->raise_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1941 static void
1942 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1944 static MonoClass *NewConstraintAttr;
1945 static MonoMethod *NewConstraintAttr_ctor;
1946 MonoDynamicTable *table;
1947 guint32 *values;
1948 guint32 token, type;
1949 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1950 char *buf, *p;
1952 if (!NewConstraintAttr)
1953 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1954 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1955 g_assert (NewConstraintAttr);
1957 if (!NewConstraintAttr_ctor) {
1958 int i;
1960 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1961 MonoMethod *m = NewConstraintAttr->methods [i];
1963 if (strcmp (m->name, ".ctor"))
1964 continue;
1966 NewConstraintAttr_ctor = m;
1967 break;
1970 g_assert (NewConstraintAttr_ctor);
1973 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1974 table->rows += 1;
1975 alloc_table (table, table->rows);
1977 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1978 owner <<= MONO_CUSTOM_ATTR_BITS;
1979 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1980 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1982 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1984 type = mono_metadata_token_index (token);
1985 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1986 switch (mono_metadata_token_table (token)) {
1987 case MONO_TABLE_METHOD:
1988 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1989 break;
1990 case MONO_TABLE_MEMBERREF:
1991 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1992 break;
1993 default:
1994 g_warning ("got wrong token in custom attr");
1995 return;
1997 values [MONO_CUSTOM_ATTR_TYPE] = type;
1999 buf = p = g_malloc (1);
2000 mono_metadata_encode_value (4, p, &p);
2001 g_assert (p-buf == 1);
2003 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2005 values += MONO_CUSTOM_ATTR_SIZE;
2006 ++table->next_idx;
2009 static void
2010 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2013 guint32 num_constraints, i;
2014 guint32 *values;
2015 guint32 table_idx;
2017 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2018 num_constraints = gparam->iface_constraints ?
2019 mono_array_length (gparam->iface_constraints) : 0;
2020 table->rows += num_constraints;
2021 if (gparam->base_type)
2022 table->rows++;
2023 alloc_table (table, table->rows);
2025 if (gparam->base_type) {
2026 table_idx = table->next_idx ++;
2027 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2029 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2030 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2031 assembly, gparam->base_type->type);
2034 for (i = 0; i < num_constraints; i++) {
2035 MonoReflectionType *constraint = mono_array_get (
2036 gparam->iface_constraints, gpointer, i);
2038 table_idx = table->next_idx ++;
2039 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2041 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2042 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2043 assembly, constraint->type);
2046 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2047 encode_new_constraint (assembly, owner);
2050 static void
2051 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2053 GenericParamTableEntry *entry;
2056 * The GenericParam table must be sorted according to the `owner' field.
2057 * We need to do this sorting prior to writing the GenericParamConstraint
2058 * table, since we have to use the final GenericParam table indices there
2059 * and they must also be sorted.
2062 entry = g_new0 (GenericParamTableEntry, 1);
2063 entry->owner = owner;
2064 entry->gparam = gparam;
2066 g_ptr_array_add (assembly->gen_params, entry);
2069 static void
2070 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2072 MonoDynamicTable *table;
2073 MonoGenericParam *param;
2074 guint32 *values;
2075 guint32 table_idx;
2077 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2078 table_idx = table->next_idx ++;
2079 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2081 param = entry->gparam->type.type->data.generic_param;
2083 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2084 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2085 values [MONO_GENERICPARAM_NUMBER] = param->num;
2086 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2087 values [MONO_GENERICPARAM_KIND] = 0;
2089 encode_constraints (entry->gparam, table_idx, assembly);
2092 static guint32
2093 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2095 MonoDynamicTable *table;
2096 guint32 token;
2097 guint32 *values;
2098 guint32 cols [MONO_ASSEMBLY_SIZE];
2099 const char *pubkey;
2100 guint32 publen;
2102 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2103 return token;
2105 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2106 table = &assembly->tables [MONO_TABLE_MODULEREF];
2107 token = table->next_idx ++;
2108 table->rows ++;
2109 alloc_table (table, table->rows);
2110 values = table->values + token * MONO_MODULEREF_SIZE;
2111 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2113 token <<= MONO_RESOLTION_SCOPE_BITS;
2114 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2115 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2117 return token;
2120 if (image->assembly->dynamic)
2121 /* FIXME: */
2122 memset (cols, 0, sizeof (cols));
2123 else {
2124 /* image->assembly->image is the manifest module */
2125 image = image->assembly->image;
2126 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2129 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2130 token = table->next_idx ++;
2131 table->rows ++;
2132 alloc_table (table, table->rows);
2133 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2134 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2135 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2136 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2137 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2138 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2139 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2140 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2141 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2143 if (strcmp ("", image->assembly->aname.culture)) {
2144 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2145 image->assembly->aname.culture);
2148 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2149 guchar pubtoken [9];
2150 pubtoken [0] = 8;
2151 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2152 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2153 } else {
2154 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2156 token <<= MONO_RESOLTION_SCOPE_BITS;
2157 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2158 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2159 return token;
2162 static guint32
2163 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2165 MonoDynamicTable *table;
2166 guint32 *values;
2167 guint32 token;
2168 char sig [128];
2169 char *p = sig;
2170 char blob_size [6];
2171 char *b = blob_size;
2173 switch (type->type) {
2174 case MONO_TYPE_FNPTR:
2175 case MONO_TYPE_PTR:
2176 case MONO_TYPE_SZARRAY:
2177 case MONO_TYPE_ARRAY:
2178 case MONO_TYPE_VAR:
2179 case MONO_TYPE_MVAR:
2180 case MONO_TYPE_GENERICINST:
2181 encode_type (assembly, type, p, &p);
2182 break;
2183 case MONO_TYPE_CLASS:
2184 case MONO_TYPE_VALUETYPE: {
2185 MonoClass *k = mono_class_from_mono_type (type);
2186 if (!k || !k->generic_inst)
2187 return 0;
2188 encode_generic_inst (assembly, k->generic_inst, p, &p);
2189 break;
2191 default:
2192 return 0;
2195 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2196 if (assembly->save) {
2197 g_assert (p-sig < 128);
2198 mono_metadata_encode_value (p-sig, b, &b);
2199 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2200 alloc_table (table, table->rows + 1);
2201 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2202 values [MONO_TYPESPEC_SIGNATURE] = token;
2205 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2206 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2207 table->next_idx ++;
2208 return token;
2212 * Despite the name, we handle also TypeSpec (with the above helper).
2214 static guint32
2215 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2217 MonoDynamicTable *table;
2218 guint32 *values;
2219 guint32 token, scope, enclosing;
2220 MonoClass *klass;
2222 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2223 if (token)
2224 return token;
2225 token = create_typespec (assembly, type);
2226 if (token)
2227 return token;
2228 klass = my_mono_class_from_mono_type (type);
2229 if (!klass)
2230 klass = mono_class_from_mono_type (type);
2233 * If it's in the same module and not a generic type parameter:
2235 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2236 (type->type != MONO_TYPE_MVAR)) {
2237 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2238 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2239 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2240 return token;
2243 if (klass->nested_in) {
2244 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2245 /* get the typeref idx of the enclosing type */
2246 enclosing >>= MONO_TYPEDEFORREF_BITS;
2247 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2248 } else {
2249 scope = resolution_scope_from_image (assembly, klass->image);
2251 table = &assembly->tables [MONO_TABLE_TYPEREF];
2252 if (assembly->save) {
2253 alloc_table (table, table->rows + 1);
2254 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2255 values [MONO_TYPEREF_SCOPE] = scope;
2256 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2257 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2259 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2260 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2261 table->next_idx ++;
2262 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2263 return token;
2267 * Insert a memberef row into the metadata: the token that point to the memberref
2268 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2269 * mono_image_get_fieldref_token()).
2270 * The sig param is an index to an already built signature.
2272 static guint32
2273 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2275 MonoDynamicTable *table;
2276 guint32 *values;
2277 guint32 token, pclass;
2278 guint32 parent;
2280 parent = mono_image_typedef_or_ref (assembly, type);
2281 switch (parent & MONO_TYPEDEFORREF_MASK) {
2282 case MONO_TYPEDEFORREF_TYPEREF:
2283 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2284 break;
2285 case MONO_TYPEDEFORREF_TYPESPEC:
2286 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2287 break;
2288 case MONO_TYPEDEFORREF_TYPEDEF:
2289 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2290 break;
2291 default:
2292 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2293 return 0;
2295 /* extract the index */
2296 parent >>= MONO_TYPEDEFORREF_BITS;
2298 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2300 if (assembly->save) {
2301 alloc_table (table, table->rows + 1);
2302 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2303 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2304 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2305 values [MONO_MEMBERREF_SIGNATURE] = sig;
2308 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2309 table->next_idx ++;
2311 return token;
2314 static guint32
2315 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2317 guint32 token;
2318 MonoMethodSignature *sig;
2320 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2321 if (token)
2322 return token;
2325 * A methodref signature can't contain an unmanaged calling convention.
2327 sig = mono_metadata_signature_dup (method->signature);
2328 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2329 sig->call_convention = MONO_CALL_DEFAULT;
2330 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2331 method->name, method_encode_signature (assembly, sig));
2332 g_free (sig);
2333 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2334 return token;
2337 static guint32
2338 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2339 const gchar *name, guint32 sig)
2341 MonoDynamicTable *table;
2342 guint32 token;
2343 guint32 *values;
2345 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2347 if (assembly->save) {
2348 alloc_table (table, table->rows + 1);
2349 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2350 values [MONO_MEMBERREF_CLASS] = original;
2351 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2352 values [MONO_MEMBERREF_SIGNATURE] = sig;
2355 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2356 table->next_idx ++;
2358 return token;
2361 static guint32
2362 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2364 guint32 token;
2365 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2368 if (token)
2369 return token;
2371 reflection_methodbuilder_from_method_builder (&rmb, mb);
2373 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2374 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2375 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2376 return token;
2379 static guint32
2380 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2382 guint32 token;
2383 ReflectionMethodBuilder rmb;
2385 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2386 if (token)
2387 return token;
2389 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2391 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2392 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2393 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2394 return token;
2397 static guint32
2398 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2400 MonoType *type;
2401 guint32 token;
2403 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2404 if (token)
2405 return token;
2406 g_assert (f->field->parent);
2407 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2408 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2409 f->field->name, fieldref_encode_signature (assembly, type));
2410 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2411 return token;
2414 static guint32
2415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2417 char *buf;
2418 char *p;
2419 int i;
2420 guint32 nparams = gmethod->mtype_argc;
2421 guint32 size = 10 + nparams * 10;
2422 guint32 idx;
2423 char blob_size [6];
2424 char *b = blob_size;
2426 if (!assembly->save)
2427 return 0;
2429 p = buf = g_malloc (size);
2431 * FIXME: vararg, explicit_this, differenc call_conv values...
2433 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2434 mono_metadata_encode_value (nparams, p, &p);
2436 for (i = 0; i < nparams; i++)
2437 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2439 /* store length */
2440 g_assert (p - buf < size);
2441 mono_metadata_encode_value (p-buf, b, &b);
2442 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2443 g_free (buf);
2444 return idx;
2447 static guint32
2448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2450 MonoDynamicTable *table;
2451 guint32 *values;
2452 guint32 token, mtoken = 0, sig;
2453 MonoMethodInflated *imethod;
2454 MonoMethod *declaring;
2456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2458 g_assert (method->signature->is_inflated);
2459 imethod = (MonoMethodInflated *) method;
2460 declaring = imethod->declaring;
2462 sig = method_encode_signature (assembly, declaring->signature);
2463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2465 if (!declaring->signature->generic_param_count)
2466 return mtoken;
2468 switch (mono_metadata_token_table (mtoken)) {
2469 case MONO_TABLE_MEMBERREF:
2470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2471 break;
2472 case MONO_TABLE_METHOD:
2473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2474 break;
2475 default:
2476 g_assert_not_reached ();
2479 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2481 if (assembly->save) {
2482 alloc_table (table, table->rows + 1);
2483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2484 values [MONO_METHODSPEC_METHOD] = mtoken;
2485 values [MONO_METHODSPEC_SIGNATURE] = sig;
2488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2489 table->next_idx ++;
2491 return token;
2494 static guint32
2495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2497 MonoMethodInflated *imethod;
2498 guint32 token;
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2501 if (token)
2502 return token;
2504 g_assert (m->signature->is_inflated);
2505 imethod = (MonoMethodInflated *) m;
2507 if (imethod->declaring->signature->generic_param_count) {
2508 token = method_encode_methodspec (assembly, m);
2509 } else {
2510 guint32 sig = method_encode_signature (
2511 assembly, imethod->declaring->signature);
2512 token = mono_image_get_memberref_token (
2513 assembly, &m->klass->byval_arg, m->name, sig);
2516 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2517 return token;
2520 static guint32
2521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2524 guint32 sig, token;
2526 sig = method_encode_signature (assembly, imethod->declaring->signature);
2527 token = mono_image_get_memberref_token (
2528 assembly, &m->klass->byval_arg, m->name, sig);
2530 return token;
2533 static guint32
2534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2536 MonoDynamicTable *table;
2537 MonoClass *klass;
2538 guint32 *values;
2539 guint32 token;
2540 char sig [128];
2541 char *p = sig;
2542 char blob_size [6];
2543 char *b = blob_size;
2544 int count, i;
2547 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2548 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2549 * Because of this, we must not insert it into the `typeref' hash table.
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2553 if (token)
2554 return token;
2556 g_assert (tb->generic_params);
2557 klass = mono_class_from_mono_type (tb->type.type);
2559 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2560 encode_type (assembly, &klass->byval_arg, p, &p);
2562 count = mono_array_length (tb->generic_params);
2563 mono_metadata_encode_value (count, p, &p);
2564 for (i = 0; i < count; i++) {
2565 MonoReflectionGenericParam *gparam;
2567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2569 encode_type (assembly, gparam->type.type, p, &p);
2572 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2573 if (assembly->save) {
2574 g_assert (p-sig < 128);
2575 mono_metadata_encode_value (p-sig, b, &b);
2576 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2579 values [MONO_TYPESPEC_SIGNATURE] = token;
2582 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2584 table->next_idx ++;
2585 return token;
2588 static guint32
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2591 MonoDynamicTable *table;
2592 MonoClass *klass;
2593 guint32 *values;
2594 guint32 token, pclass, parent, sig;
2595 gchar *name;
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2598 if (token)
2599 return token;
2601 klass = mono_class_from_mono_type (fb->typeb->type);
2602 name = mono_string_to_utf8 (fb->name);
2604 sig = fieldref_encode_signature (assembly, fb->type->type);
2606 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2609 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610 parent >>= MONO_TYPEDEFORREF_BITS;
2612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2614 if (assembly->save) {
2615 alloc_table (table, table->rows + 1);
2616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619 values [MONO_MEMBERREF_SIGNATURE] = sig;
2622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2623 table->next_idx ++;
2624 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2625 return token;
2628 static guint32
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2631 char *buf;
2632 char *p;
2633 guint32 nargs;
2634 guint32 size;
2635 guint32 i, idx;
2636 char blob_size [6];
2637 char *b = blob_size;
2639 if (!assembly->save)
2640 return 0;
2642 /* FIXME: */
2643 g_assert (helper->type == 2);
2645 if (helper->arguments)
2646 nargs = mono_array_length (helper->arguments);
2647 else
2648 nargs = 0;
2650 size = 10 + (nargs * 10);
2652 p = buf = g_malloc (size);
2654 /* Encode calling convention */
2655 /* Change Any to Standard */
2656 if ((helper->call_conv & 0x03) == 0x03)
2657 helper->call_conv = 0x01;
2658 /* explicit_this implies has_this */
2659 if (helper->call_conv & 0x40)
2660 helper->call_conv &= 0x20;
2662 if (helper->call_conv == 0) { /* Unmanaged */
2663 *p = helper->unmanaged_call_conv - 1;
2664 } else {
2665 /* Managed */
2666 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2667 if (helper->call_conv & 0x02) /* varargs */
2668 *p += 0x05;
2671 p++;
2672 mono_metadata_encode_value (nargs, p, &p);
2673 encode_reflection_type (assembly, helper->return_type, p, &p);
2674 for (i = 0; i < nargs; ++i) {
2675 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2676 encode_reflection_type (assembly, pt, p, &p);
2678 /* store length */
2679 g_assert (p - buf < size);
2680 mono_metadata_encode_value (p-buf, b, &b);
2681 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2682 g_free (buf);
2684 return idx;
2687 static guint32
2688 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2690 guint32 idx;
2691 MonoDynamicTable *table;
2692 guint32 *values;
2694 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2695 idx = table->next_idx ++;
2696 table->rows ++;
2697 alloc_table (table, table->rows);
2698 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2700 values [MONO_STAND_ALONE_SIGNATURE] =
2701 mono_reflection_encode_sighelper (assembly, helper);
2703 return idx;
2706 static int
2707 reflection_cc_to_file (int call_conv) {
2708 switch (call_conv & 0x3) {
2709 case 0:
2710 case 1: return MONO_CALL_DEFAULT;
2711 case 2: return MONO_CALL_VARARG;
2712 default:
2713 g_assert_not_reached ();
2715 return 0;
2718 typedef struct {
2719 MonoType *parent;
2720 MonoMethodSignature *sig;
2721 char *name;
2722 guint32 token;
2723 } ArrayMethod;
2725 static guint32
2726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2728 guint32 nparams, i;
2729 GList *tmp;
2730 char *name;
2731 MonoMethodSignature *sig;
2732 ArrayMethod *am;
2734 name = mono_string_to_utf8 (m->name);
2735 nparams = mono_array_length (m->parameters);
2736 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2737 sig->hasthis = 1;
2738 sig->sentinelpos = -1;
2739 sig->call_convention = reflection_cc_to_file (m->call_conv);
2740 sig->param_count = nparams;
2741 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2742 for (i = 0; i < nparams; ++i) {
2743 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2744 sig->params [i] = t->type;
2747 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2748 am = tmp->data;
2749 if (strcmp (name, am->name) == 0 &&
2750 mono_metadata_type_equal (am->parent, m->parent->type) &&
2751 mono_metadata_signature_equal (am->sig, sig)) {
2752 g_free (name);
2753 g_free (sig);
2754 m->table_idx = am->token & 0xffffff;
2755 return am->token;
2758 am = g_new0 (ArrayMethod, 1);
2759 am->name = name;
2760 am->sig = sig;
2761 am->parent = m->parent->type;
2762 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2763 method_encode_signature (assembly, sig));
2764 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2765 m->table_idx = am->token & 0xffffff;
2766 return am->token;
2770 * Insert into the metadata tables all the info about the TypeBuilder tb.
2771 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2773 static void
2774 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2776 MonoDynamicTable *table;
2777 guint *values;
2778 int i, is_object = 0, is_system = 0;
2779 char *n;
2781 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2782 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2783 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2784 n = mono_string_to_utf8 (tb->name);
2785 if (strcmp (n, "Object") == 0)
2786 is_object++;
2787 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2788 g_free (n);
2789 n = mono_string_to_utf8 (tb->nspace);
2790 if (strcmp (n, "System") == 0)
2791 is_system++;
2792 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2793 g_free (n);
2794 if (tb->parent && !(is_system && is_object) &&
2795 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2796 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2797 } else {
2798 values [MONO_TYPEDEF_EXTENDS] = 0;
2800 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2801 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2804 * if we have explicitlayout or sequentiallayouts, output data in the
2805 * ClassLayout table.
2807 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2808 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2809 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2810 table->rows++;
2811 alloc_table (table, table->rows);
2812 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2813 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2814 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2815 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2818 /* handle interfaces */
2819 if (tb->interfaces) {
2820 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2821 i = table->rows;
2822 table->rows += mono_array_length (tb->interfaces);
2823 alloc_table (table, table->rows);
2824 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2825 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2826 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2827 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2828 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2829 values += MONO_INTERFACEIMPL_SIZE;
2833 /* handle fields */
2834 if (tb->fields) {
2835 table = &assembly->tables [MONO_TABLE_FIELD];
2836 table->rows += tb->num_fields;
2837 alloc_table (table, table->rows);
2838 for (i = 0; i < tb->num_fields; ++i)
2839 mono_image_get_field_info (
2840 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2843 /* handle constructors */
2844 if (tb->ctors) {
2845 table = &assembly->tables [MONO_TABLE_METHOD];
2846 table->rows += mono_array_length (tb->ctors);
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2849 mono_image_get_ctor_info (domain,
2850 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2853 /* handle methods */
2854 if (tb->methods) {
2855 table = &assembly->tables [MONO_TABLE_METHOD];
2856 table->rows += tb->num_methods;
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < tb->num_methods; ++i)
2859 mono_image_get_method_info (
2860 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2863 /* Do the same with properties etc.. */
2864 if (tb->events && mono_array_length (tb->events)) {
2865 table = &assembly->tables [MONO_TABLE_EVENT];
2866 table->rows += mono_array_length (tb->events);
2867 alloc_table (table, table->rows);
2868 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2869 table->rows ++;
2870 alloc_table (table, table->rows);
2871 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2872 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2873 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2874 for (i = 0; i < mono_array_length (tb->events); ++i)
2875 mono_image_get_event_info (
2876 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2878 if (tb->properties && mono_array_length (tb->properties)) {
2879 table = &assembly->tables [MONO_TABLE_PROPERTY];
2880 table->rows += mono_array_length (tb->properties);
2881 alloc_table (table, table->rows);
2882 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2883 table->rows ++;
2884 alloc_table (table, table->rows);
2885 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2886 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2887 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2888 for (i = 0; i < mono_array_length (tb->properties); ++i)
2889 mono_image_get_property_info (
2890 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2893 /* handle generic parameters */
2894 if (tb->generic_params) {
2895 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2896 table->rows += mono_array_length (tb->generic_params);
2897 alloc_table (table, table->rows);
2898 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2899 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2901 mono_image_get_generic_param_info (
2902 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2906 mono_image_add_decl_security (assembly,
2907 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2909 if (tb->subtypes) {
2910 MonoDynamicTable *ntable;
2912 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2913 ntable->rows += mono_array_length (tb->subtypes);
2914 alloc_table (ntable, ntable->rows);
2915 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2917 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2918 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2920 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2921 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2922 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2923 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2924 mono_string_to_utf8 (tb->name), tb->table_idx,
2925 ntable->next_idx, ntable->rows);*/
2926 values += MONO_NESTED_CLASS_SIZE;
2927 ntable->next_idx++;
2932 static void
2933 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2935 int i;
2937 g_ptr_array_add (types, type);
2939 if (!type->subtypes)
2940 return;
2942 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2943 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2944 collect_types (types, subtype);
2948 static gint
2949 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2951 if ((*type1)->table_idx < (*type2)->table_idx)
2952 return -1;
2953 else
2954 if ((*type1)->table_idx > (*type2)->table_idx)
2955 return 1;
2956 else
2957 return 0;
2960 static void
2961 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2962 int i;
2964 if (!pinfo)
2965 return;
2966 for (i = 0; i < mono_array_length (pinfo); ++i) {
2967 MonoReflectionParamBuilder *pb;
2968 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2969 if (!pb)
2970 continue;
2971 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2975 static void
2976 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2977 int i;
2979 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2980 if (tb->fields) {
2981 for (i = 0; i < tb->num_fields; ++i) {
2982 MonoReflectionFieldBuilder* fb;
2983 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2984 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2987 if (tb->events) {
2988 for (i = 0; i < mono_array_length (tb->events); ++i) {
2989 MonoReflectionEventBuilder* eb;
2990 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2991 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2994 if (tb->properties) {
2995 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2996 MonoReflectionPropertyBuilder* pb;
2997 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2998 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3001 if (tb->ctors) {
3002 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3003 MonoReflectionCtorBuilder* cb;
3004 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3005 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3006 params_add_cattrs (assembly, cb->pinfo);
3010 if (tb->methods) {
3011 for (i = 0; i < tb->num_methods; ++i) {
3012 MonoReflectionMethodBuilder* mb;
3013 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3014 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3015 params_add_cattrs (assembly, mb->pinfo);
3019 if (tb->subtypes) {
3020 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3021 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3025 static void
3026 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3027 int i;
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3031 /* no types in the module */
3032 if (!mb->types)
3033 return;
3035 for (i = 0; i < mb->num_types; ++i)
3036 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3039 static void
3040 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3042 MonoDynamicTable *table;
3043 guint32 *values;
3044 char blob_size [6];
3045 guchar hash [20];
3046 char *b = blob_size;
3047 char *dir, *path;
3049 table = &assembly->tables [MONO_TABLE_FILE];
3050 table->rows++;
3051 alloc_table (table, table->rows);
3052 values = table->values + table->next_idx * MONO_FILE_SIZE;
3053 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3054 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3055 if (module->image->dynamic) {
3056 /* This depends on the fact that the main module is emitted last */
3057 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3058 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3059 } else {
3060 dir = NULL;
3061 path = g_strdup (module->image->name);
3063 mono_sha1_get_digest_from_file (path, hash);
3064 g_free (dir);
3065 g_free (path);
3066 mono_metadata_encode_value (20, b, &b);
3067 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3068 mono_image_add_stream_data (&assembly->blob, hash, 20);
3069 table->next_idx ++;
3072 static void
3073 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3076 int i;
3077 char *name;
3079 table = &assembly->tables [MONO_TABLE_MODULE];
3080 mb->table_idx = table->next_idx ++;
3081 name = mono_string_to_utf8 (mb->module.name);
3082 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3083 g_free (name);
3084 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3085 i /= 16;
3086 ++i;
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3088 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3092 static guint32
3093 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3094 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3096 MonoDynamicTable *table;
3097 guint32 *values;
3098 guint32 visib, res;
3100 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3101 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3102 return 0;
3104 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3105 table->rows++;
3106 alloc_table (table, table->rows);
3107 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3109 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3110 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3111 if (klass->nested_in)
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3113 else
3114 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3115 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3116 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3118 res = table->next_idx;
3120 table->next_idx ++;
3122 /* Emit nested types */
3123 if (klass->nested_classes) {
3124 GList *tmp;
3126 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3127 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3130 return res;
3133 static void
3134 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3135 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3137 MonoClass *klass;
3138 guint32 idx, i;
3140 klass = mono_class_from_mono_type (tb->type.type);
3142 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3144 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3145 parent_index, assembly);
3148 * Emit nested types
3149 * We need to do this ourselves since klass->nested_classes is not set up.
3151 if (tb->subtypes) {
3152 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3153 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3157 static void
3158 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3159 guint32 module_index, MonoDynamicImage *assembly)
3161 MonoImage *image = module->image;
3162 MonoTableInfo *t;
3163 guint32 i;
3165 t = &image->tables [MONO_TABLE_TYPEDEF];
3167 for (i = 0; i < t->rows; ++i) {
3168 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3170 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3171 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3175 #define align_pointer(base,p)\
3176 do {\
3177 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3178 if (__diff & 3)\
3179 (p) += 4 - (__diff & 3);\
3180 } while (0)
3182 static int
3183 compare_semantics (const void *a, const void *b)
3185 const guint32 *a_values = a;
3186 const guint32 *b_values = b;
3187 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3188 if (assoc)
3189 return assoc;
3190 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3193 static int
3194 compare_custom_attrs (const void *a, const void *b)
3196 const guint32 *a_values = a;
3197 const guint32 *b_values = b;
3199 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3202 static int
3203 compare_field_marshal (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3208 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3211 static int
3212 compare_nested (const void *a, const void *b)
3214 const guint32 *a_values = a;
3215 const guint32 *b_values = b;
3217 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3220 static int
3221 compare_genericparam (const void *a, const void *b)
3223 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3224 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3226 return (*a_entry)->owner - (*b_entry)->owner;
3229 static int
3230 compare_declsecurity_attrs (const void *a, const void *b)
3232 const guint32 *a_values = a;
3233 const guint32 *b_values = b;
3235 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3238 static void
3239 pad_heap (MonoDynamicStream *sh)
3241 if (sh->index & 3) {
3242 int sz = 4 - (sh->index & 3);
3243 memset (sh->data + sh->index, 0, sz);
3244 sh->index += sz;
3248 struct StreamDesc {
3249 const char *name;
3250 MonoDynamicStream *stream;
3254 * build_compressed_metadata() fills in the blob of data that represents the
3255 * raw metadata as it will be saved in the PE file. The five streams are output
3256 * and the metadata tables are comnpressed from the guint32 array representation,
3257 * to the compressed on-disk format.
3259 static void
3260 build_compressed_metadata (MonoDynamicImage *assembly)
3262 MonoDynamicTable *table;
3263 int i;
3264 guint64 valid_mask = 0;
3265 guint64 sorted_mask;
3266 guint32 heapt_size = 0;
3267 guint32 meta_size = 256; /* allow for header and other stuff */
3268 guint32 table_offset;
3269 guint32 ntables = 0;
3270 guint64 *int64val;
3271 guint32 *int32val;
3272 guint16 *int16val;
3273 MonoImage *meta;
3274 unsigned char *p;
3275 struct StreamDesc stream_desc [5];
3277 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3278 for (i = 0; i < assembly->gen_params->len; i++){
3279 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3280 write_generic_param_entry (assembly, entry);
3283 stream_desc [0].name = "#~";
3284 stream_desc [0].stream = &assembly->tstream;
3285 stream_desc [1].name = "#Strings";
3286 stream_desc [1].stream = &assembly->sheap;
3287 stream_desc [2].name = "#US";
3288 stream_desc [2].stream = &assembly->us;
3289 stream_desc [3].name = "#Blob";
3290 stream_desc [3].stream = &assembly->blob;
3291 stream_desc [4].name = "#GUID";
3292 stream_desc [4].stream = &assembly->guid;
3294 /* tables that are sorted */
3295 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3296 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3297 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3298 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3299 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3300 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3302 /* Compute table sizes */
3303 /* the MonoImage has already been created in mono_image_basic_init() */
3304 meta = &assembly->image;
3306 /* sizes should be multiple of 4 */
3307 pad_heap (&assembly->blob);
3308 pad_heap (&assembly->guid);
3309 pad_heap (&assembly->sheap);
3310 pad_heap (&assembly->us);
3312 /* Setup the info used by compute_sizes () */
3313 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3314 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3315 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3317 meta_size += assembly->blob.index;
3318 meta_size += assembly->guid.index;
3319 meta_size += assembly->sheap.index;
3320 meta_size += assembly->us.index;
3322 for (i=0; i < 64; ++i)
3323 meta->tables [i].rows = assembly->tables [i].rows;
3325 for (i = 0; i < 64; i++){
3326 if (meta->tables [i].rows == 0)
3327 continue;
3328 valid_mask |= (guint64)1 << i;
3329 ntables ++;
3330 meta->tables [i].row_size = mono_metadata_compute_size (
3331 meta, i, &meta->tables [i].size_bitfield);
3332 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3334 heapt_size += 24; /* #~ header size */
3335 heapt_size += ntables * 4;
3336 /* make multiple of 4 */
3337 heapt_size += 3;
3338 heapt_size &= ~3;
3339 meta_size += heapt_size;
3340 meta->raw_metadata = g_malloc0 (meta_size);
3341 p = meta->raw_metadata;
3342 /* the metadata signature */
3343 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3344 /* version numbers and 4 bytes reserved */
3345 int16val = (guint16*)p;
3346 *int16val++ = GUINT16_TO_LE (1);
3347 *int16val = GUINT16_TO_LE (1);
3348 p += 8;
3349 /* version string */
3350 int32val = (guint32*)p;
3351 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3352 p += 4;
3353 memcpy (p, meta->version, strlen (meta->version));
3354 p += GUINT32_FROM_LE (*int32val);
3355 align_pointer (meta->raw_metadata, p);
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3358 *int16val = GUINT16_TO_LE (5); /* number of streams */
3359 p += 4;
3362 * write the stream info.
3364 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3365 table_offset += 3; table_offset &= ~3;
3367 assembly->tstream.index = heapt_size;
3368 for (i = 0; i < 5; ++i) {
3369 int32val = (guint32*)p;
3370 stream_desc [i].stream->offset = table_offset;
3371 *int32val++ = GUINT32_TO_LE (table_offset);
3372 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3373 table_offset += GUINT32_FROM_LE (*int32val);
3374 table_offset += 3; table_offset &= ~3;
3375 p += 8;
3376 strcpy (p, stream_desc [i].name);
3377 p += strlen (stream_desc [i].name) + 1;
3378 align_pointer (meta->raw_metadata, p);
3381 * now copy the data, the table stream header and contents goes first.
3383 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3384 p = meta->raw_metadata + assembly->tstream.offset;
3385 int32val = (guint32*)p;
3386 *int32val = GUINT32_TO_LE (0); /* reserved */
3387 p += 4;
3389 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3390 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3391 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3392 *p++ = 1; /* version */
3393 *p++ = 1;
3394 } else {
3395 *p++ = 1; /* version */
3396 *p++ = 0;
3399 if (meta->idx_string_wide)
3400 *p |= 0x01;
3401 if (meta->idx_guid_wide)
3402 *p |= 0x02;
3403 if (meta->idx_blob_wide)
3404 *p |= 0x04;
3405 ++p;
3406 *p++ = 1; /* reserved */
3407 int64val = (guint64*)p;
3408 *int64val++ = GUINT64_TO_LE (valid_mask);
3409 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3410 p += 16;
3411 int32val = (guint32*)p;
3412 for (i = 0; i < 64; i++){
3413 if (meta->tables [i].rows == 0)
3414 continue;
3415 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3417 p = (unsigned char*)int32val;
3419 /* sort the tables that still need sorting */
3420 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3421 if (table->rows)
3422 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3423 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3424 if (table->rows)
3425 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3426 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3427 if (table->rows)
3428 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3429 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3430 if (table->rows)
3431 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3432 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3433 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3434 if (table->rows)
3435 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3437 /* compress the tables */
3438 for (i = 0; i < 64; i++){
3439 int row, col;
3440 guint32 *values;
3441 guint32 bitfield = meta->tables [i].size_bitfield;
3442 if (!meta->tables [i].rows)
3443 continue;
3444 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3445 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3446 meta->tables [i].base = p;
3447 for (row = 1; row <= meta->tables [i].rows; ++row) {
3448 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3449 for (col = 0; col < assembly->tables [i].columns; ++col) {
3450 switch (mono_metadata_table_size (bitfield, col)) {
3451 case 1:
3452 *p++ = values [col];
3453 break;
3454 case 2:
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3457 break;
3458 case 4:
3459 *p++ = values [col] & 0xff;
3460 *p++ = (values [col] >> 8) & 0xff;
3461 *p++ = (values [col] >> 16) & 0xff;
3462 *p++ = (values [col] >> 24) & 0xff;
3463 break;
3464 default:
3465 g_assert_not_reached ();
3469 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3472 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3473 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3474 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3475 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3476 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3478 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 * Some tables in metadata need to be sorted according to some criteria, but
3483 * when methods and fields are first created with reflection, they may be assigned a token
3484 * that doesn't correspond to the final token they will get assigned after the sorting.
3485 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3486 * with the reflection objects that represent them. Once all the tables are set up, the
3487 * reflection objects will contains the correct table index. fixup_method() will fixup the
3488 * tokens for the method with ILGenerator @ilgen.
3490 static void
3491 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3492 guint32 code_idx = GPOINTER_TO_UINT (value);
3493 MonoReflectionILTokenInfo *iltoken;
3494 MonoReflectionFieldBuilder *field;
3495 MonoReflectionCtorBuilder *ctor;
3496 MonoReflectionMethodBuilder *method;
3497 MonoReflectionTypeBuilder *tb;
3498 MonoReflectionArrayMethod *am;
3499 guint32 i, idx = 0;
3500 unsigned char *target;
3502 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3503 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3504 target = assembly->code.data + code_idx + iltoken->code_pos;
3505 switch (target [3]) {
3506 case MONO_TABLE_FIELD:
3507 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3508 field = (MonoReflectionFieldBuilder *)iltoken->member;
3509 idx = field->table_idx;
3510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3511 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3512 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3513 } else {
3514 g_assert_not_reached ();
3516 break;
3517 case MONO_TABLE_METHOD:
3518 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3519 method = (MonoReflectionMethodBuilder *)iltoken->member;
3520 idx = method->table_idx;
3521 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3522 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3523 idx = ctor->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3525 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3526 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3527 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3528 } else {
3529 g_assert_not_reached ();
3531 break;
3532 case MONO_TABLE_TYPEDEF:
3533 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3534 g_assert_not_reached ();
3535 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3536 idx = tb->table_idx;
3537 break;
3538 case MONO_TABLE_MEMBERREF:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3540 am = (MonoReflectionArrayMethod*)iltoken->member;
3541 idx = am->table_idx;
3542 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3543 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3544 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3545 g_assert (m->klass->generic_inst);
3546 continue;
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3548 continue;
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3550 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3551 g_assert (f->generic_info);
3552 continue;
3553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3554 continue;
3555 } else {
3556 g_assert_not_reached ();
3558 break;
3559 case MONO_TABLE_METHODSPEC:
3560 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3561 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3562 g_assert (m->signature->generic_param_count);
3563 continue;
3564 } else {
3565 g_assert_not_reached ();
3567 break;
3568 default:
3569 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3571 target [0] = idx & 0xff;
3572 target [1] = (idx >> 8) & 0xff;
3573 target [2] = (idx >> 16) & 0xff;
3578 * fixup_cattrs:
3580 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3581 * value is not known when the table is emitted.
3583 static void
3584 fixup_cattrs (MonoDynamicImage *assembly)
3586 MonoDynamicTable *table;
3587 guint32 *values;
3588 guint32 type, i, idx, token;
3589 MonoObject *ctor;
3591 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3593 for (i = 0; i < table->rows; ++i) {
3594 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3596 type = values [MONO_CUSTOM_ATTR_TYPE];
3597 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3598 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3599 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3600 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3601 g_assert (ctor);
3603 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3604 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3605 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3606 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3612 static void
3613 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3615 MonoDynamicTable *table;
3616 guint32 *values;
3617 char *name;
3619 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3620 table->rows++;
3621 alloc_table (table, table->rows);
3622 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3623 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3624 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3625 name = mono_string_to_utf8 (rsrc->name);
3626 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3627 g_free (name);
3628 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3629 table->next_idx++;
3632 static void
3633 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3635 MonoDynamicTable *table;
3636 guint32 *values;
3637 char blob_size [6];
3638 guchar hash [20];
3639 char *b = blob_size;
3640 char *name, *sname;
3641 guint32 idx, offset;
3643 if (rsrc->filename) {
3644 name = mono_string_to_utf8 (rsrc->filename);
3645 sname = g_path_get_basename (name);
3647 table = &assembly->tables [MONO_TABLE_FILE];
3648 table->rows++;
3649 alloc_table (table, table->rows);
3650 values = table->values + table->next_idx * MONO_FILE_SIZE;
3651 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3652 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3653 g_free (sname);
3655 mono_sha1_get_digest_from_file (name, hash);
3656 mono_metadata_encode_value (20, b, &b);
3657 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3658 mono_image_add_stream_data (&assembly->blob, hash, 20);
3659 g_free (name);
3660 idx = table->next_idx++;
3661 rsrc->offset = 0;
3662 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3663 } else {
3664 char sizebuf [4];
3665 offset = mono_array_length (rsrc->data);
3666 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3667 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3668 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3669 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3671 if (!mb->is_main)
3673 * The entry should be emitted into the MANIFESTRESOURCE table of
3674 * the main module, but that needs to reference the FILE table
3675 * which isn't emitted yet.
3677 return;
3678 else
3679 idx = 0;
3682 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3685 static void
3686 set_version_from_string (MonoString *version, guint32 *values)
3688 gchar *ver, *p, *str;
3689 guint32 i;
3691 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3692 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3693 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3694 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3695 if (!version)
3696 return;
3697 ver = str = mono_string_to_utf8 (version);
3698 for (i = 0; i < 4; ++i) {
3699 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3700 switch (*p) {
3701 case '.':
3702 p++;
3703 break;
3704 case '*':
3705 /* handle Revision and Build */
3706 p++;
3707 break;
3709 ver = p;
3711 g_free (str);
3714 static guint32
3715 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3716 gsize len;
3717 guint32 token = 0;
3718 char blob_size [6];
3719 char *b = blob_size;
3721 if (!pkey)
3722 return token;
3724 len = mono_array_length (pkey);
3725 mono_metadata_encode_value (len, b, &b);
3726 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3727 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3729 /* need to get the actual value from the key type... */
3730 assembly->strong_name_size = 128;
3731 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3733 return token;
3736 static void
3737 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3739 MonoDynamicTable *table;
3740 MonoDynamicImage *assembly;
3741 MonoReflectionAssemblyBuilder *assemblyb;
3742 MonoDomain *domain;
3743 guint32 *values;
3744 char *name;
3745 int i;
3746 guint32 module_index;
3748 assemblyb = moduleb->assemblyb;
3749 assembly = moduleb->dynamic_image;
3750 domain = mono_object_domain (assemblyb);
3752 /* Emit ASSEMBLY table */
3753 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3754 alloc_table (table, 1);
3755 values = table->values + MONO_ASSEMBLY_SIZE;
3756 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3757 name = mono_string_to_utf8 (assemblyb->name);
3758 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3759 g_free (name);
3760 if (assemblyb->culture) {
3761 name = mono_string_to_utf8 (assemblyb->culture);
3762 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3763 g_free (name);
3764 } else {
3765 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3767 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3768 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3769 set_version_from_string (assemblyb->version, values);
3771 /* Emit FILE + EXPORTED_TYPE table */
3772 module_index = 0;
3773 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3774 int j;
3775 MonoReflectionModuleBuilder *file_module =
3776 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3777 if (file_module != moduleb) {
3778 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3779 module_index ++;
3780 if (file_module->types) {
3781 for (j = 0; j < file_module->num_types; ++j) {
3782 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3783 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3788 if (assemblyb->loaded_modules) {
3789 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3790 MonoReflectionModule *file_module =
3791 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3792 mono_image_fill_file_table (domain, file_module, assembly);
3793 module_index ++;
3794 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3798 /* Emit MANIFESTRESOURCE table */
3799 module_index = 0;
3800 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3801 int j;
3802 MonoReflectionModuleBuilder *file_module =
3803 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3804 /* The table for the main module is emitted later */
3805 if (file_module != moduleb) {
3806 module_index ++;
3807 if (file_module->resources) {
3808 int len = mono_array_length (file_module->resources);
3809 for (j = 0; j < len; ++j) {
3810 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3811 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3819 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3820 * for the modulebuilder @moduleb.
3821 * At the end of the process, method and field tokens are fixed up and the
3822 * on-disk compressed metadata representation is created.
3824 void
3825 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3827 MonoDynamicTable *table;
3828 MonoDynamicImage *assembly;
3829 MonoReflectionAssemblyBuilder *assemblyb;
3830 MonoDomain *domain;
3831 guint32 *values;
3832 int i;
3834 assemblyb = moduleb->assemblyb;
3835 assembly = moduleb->dynamic_image;
3836 domain = mono_object_domain (assemblyb);
3838 if (assembly->text_rva)
3839 return;
3841 assembly->text_rva = START_TEXT_RVA;
3843 if (moduleb->is_main) {
3844 mono_image_emit_manifest (moduleb);
3847 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3848 table->rows = 1; /* .<Module> */
3849 table->next_idx++;
3850 alloc_table (table, table->rows);
3852 * Set the first entry.
3854 values = table->values + table->columns;
3855 values [MONO_TYPEDEF_FLAGS] = 0;
3856 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3857 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3858 values [MONO_TYPEDEF_EXTENDS] = 0;
3859 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3860 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3863 * handle global methods
3864 * FIXME: test what to do when global methods are defined in multiple modules.
3866 if (moduleb->global_methods) {
3867 table = &assembly->tables [MONO_TABLE_METHOD];
3868 table->rows += mono_array_length (moduleb->global_methods);
3869 alloc_table (table, table->rows);
3870 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3871 mono_image_get_method_info (
3872 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3874 if (moduleb->global_fields) {
3875 table = &assembly->tables [MONO_TABLE_FIELD];
3876 table->rows += mono_array_length (moduleb->global_fields);
3877 alloc_table (table, table->rows);
3878 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3879 mono_image_get_field_info (
3880 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3883 table = &assembly->tables [MONO_TABLE_MODULE];
3884 alloc_table (table, 1);
3885 mono_image_fill_module_table (domain, moduleb, assembly);
3887 /* Emit types */
3889 /* Collect all types into a list sorted by their table_idx */
3890 GPtrArray *types = g_ptr_array_new ();
3892 if (moduleb->types)
3893 for (i = 0; i < moduleb->num_types; ++i) {
3894 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3895 collect_types (types, type);
3898 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows += types->len;
3901 alloc_table (table, table->rows);
3903 for (i = 0; i < types->len; ++i) {
3904 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3905 mono_image_get_type_info (domain, type, assembly);
3907 g_ptr_array_free (types, TRUE);
3911 * table->rows is already set above and in mono_image_fill_module_table.
3913 /* add all the custom attributes at the end, once all the indexes are stable */
3914 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3916 /* CAS assembly permissions */
3917 if (assemblyb->permissions_minimum)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3919 if (assemblyb->permissions_optional)
3920 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3921 if (assemblyb->permissions_refused)
3922 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3924 module_add_cattrs (assembly, moduleb);
3926 /* fixup tokens */
3927 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3928 fixup_cattrs (assembly);
3932 * mono_image_insert_string:
3933 * @module: module builder object
3934 * @str: a string
3936 * Insert @str into the user string stream of @module.
3938 guint32
3939 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3941 MonoDynamicImage *assembly;
3942 guint32 idx;
3943 char buf [16];
3944 char *b = buf;
3946 MONO_ARCH_SAVE_REGS;
3948 if (!module->dynamic_image)
3949 mono_image_module_basic_init (module);
3951 assembly = module->dynamic_image;
3953 if (assembly->save) {
3954 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3955 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3956 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3958 char *swapped = g_malloc (2 * mono_string_length (str));
3959 const char *p = (const char*)mono_string_chars (str);
3961 swap_with_size (swapped, p, 2, mono_string_length (str));
3962 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3963 g_free (swapped);
3965 #else
3966 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3967 #endif
3968 mono_image_add_stream_data (&assembly->us, "", 1);
3969 } else {
3970 idx = assembly->us.index ++;
3973 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3975 return MONO_TOKEN_STRING | idx;
3978 guint32
3979 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3981 MonoClass *klass;
3982 guint32 token = 0;
3984 klass = obj->vtable->klass;
3985 if (strcmp (klass->name, "MonoMethod") == 0) {
3986 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3987 MonoMethodSignature *sig, *old;
3988 guint32 sig_token, parent;
3989 int nargs, i;
3991 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3993 nargs = mono_array_length (opt_param_types);
3994 old = method->signature;
3995 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3997 sig->hasthis = old->hasthis;
3998 sig->explicit_this = old->explicit_this;
3999 sig->call_convention = old->call_convention;
4000 sig->generic_param_count = old->generic_param_count;
4001 sig->param_count = old->param_count + nargs;
4002 sig->sentinelpos = old->param_count;
4003 sig->ret = old->ret;
4005 for (i = 0; i < old->param_count; i++)
4006 sig->params [i] = old->params [i];
4008 for (i = 0; i < nargs; i++) {
4009 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4010 sig->params [old->param_count + i] = rt->type;
4013 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4014 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4015 parent >>= MONO_TYPEDEFORREF_BITS;
4017 parent <<= MONO_MEMBERREF_PARENT_BITS;
4018 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4020 sig_token = method_encode_signature (assembly, sig);
4021 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4022 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4024 ReflectionMethodBuilder rmb;
4025 guint32 parent, sig;
4027 reflection_methodbuilder_from_method_builder (&rmb, mb);
4028 rmb.opt_types = opt_param_types;
4030 sig = method_builder_encode_signature (assembly, &rmb);
4032 parent = mono_image_create_token (assembly, obj, TRUE);
4033 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4035 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4036 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4038 token = mono_image_get_varargs_method_token (
4039 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4040 } else {
4041 g_error ("requested method token for %s\n", klass->name);
4044 return token;
4048 * mono_image_create_token:
4049 * @assembly: a dynamic assembly
4050 * @obj:
4052 * Get a token to insert in the IL code stream for the given MemberInfo.
4053 * @obj can be one of:
4054 * ConstructorBuilder
4055 * MethodBuilder
4056 * FieldBuilder
4057 * MonoCMethod
4058 * MonoMethod
4059 * MonoField
4060 * MonoType
4061 * TypeBuilder
4063 guint32
4064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4066 MonoClass *klass;
4067 guint32 token = 0;
4069 klass = obj->vtable->klass;
4070 if (strcmp (klass->name, "MethodBuilder") == 0) {
4071 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4073 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4074 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4075 else
4076 token = mono_image_get_methodbuilder_token (assembly, mb);
4077 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4078 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4079 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4081 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4082 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4083 else
4084 token = mono_image_get_ctorbuilder_token (assembly, mb);
4085 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4086 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4087 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4088 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4089 if (tb->generic_params) {
4090 token = mono_image_get_generic_field_token (assembly, fb);
4091 } else {
4092 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4094 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4095 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4096 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4097 } else if (strcmp (klass->name, "MonoType") == 0 ||
4098 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4099 MonoReflectionType *tb = (MonoReflectionType *)obj;
4100 token = mono_metadata_token_from_dor (
4101 mono_image_typedef_or_ref (assembly, tb->type));
4102 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4103 MonoReflectionType *tb = (MonoReflectionType *)obj;
4104 token = mono_metadata_token_from_dor (
4105 mono_image_typedef_or_ref (assembly, tb->type));
4106 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4107 strcmp (klass->name, "MonoMethod") == 0) {
4108 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4109 if (m->method->signature->is_inflated) {
4110 if (create_methodspec)
4111 token = mono_image_get_methodspec_token (assembly, m->method);
4112 else
4113 token = mono_image_get_inflated_method_token (assembly, m->method);
4114 } else if (m->method->signature->generic_param_count) {
4115 g_assert_not_reached ();
4116 } else if ((m->method->klass->image == &assembly->image) &&
4117 !m->method->klass->generic_inst) {
4118 static guint32 method_table_idx = 0xffffff;
4119 if (m->method->klass->wastypebuilder) {
4120 /* we use the same token as the one that was assigned
4121 * to the Methodbuilder.
4122 * FIXME: do the equivalent for Fields.
4124 token = m->method->token;
4125 } else {
4127 * Each token should have a unique index, but the indexes are
4128 * assigned by managed code, so we don't know about them. An
4129 * easy solution is to count backwards...
4131 method_table_idx --;
4132 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4134 } else {
4135 token = mono_image_get_methodref_token (assembly, m->method);
4137 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4138 } else if (strcmp (klass->name, "MonoField") == 0) {
4139 MonoReflectionField *f = (MonoReflectionField *)obj;
4140 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4141 static guint32 field_table_idx = 0xffffff;
4142 field_table_idx --;
4143 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4144 } else {
4145 token = mono_image_get_fieldref_token (assembly, f);
4147 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4148 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4149 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4150 token = mono_image_get_array_token (assembly, m);
4151 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4152 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4153 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4154 } else {
4155 g_error ("requested token for %s\n", klass->name);
4158 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4160 return token;
4163 typedef struct {
4164 guint32 import_lookup_table;
4165 guint32 timestamp;
4166 guint32 forwarder;
4167 guint32 name_rva;
4168 guint32 import_address_table_rva;
4169 } MonoIDT;
4171 typedef struct {
4172 guint32 name_rva;
4173 guint32 flags;
4174 } MonoILT;
4176 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4178 static MonoDynamicImage*
4179 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4181 static const guchar entrycode [16] = {0xff, 0x25, 0};
4182 MonoDynamicImage *image;
4183 int i;
4185 const char *version = mono_get_runtime_version ();
4187 #if HAVE_BOEHM_GC
4188 image = GC_MALLOC (sizeof (MonoDynamicImage));
4189 #else
4190 image = g_new0 (MonoDynamicImage, 1);
4191 #endif
4193 /* keep in sync with image.c */
4194 image->image.name = assembly_name;
4195 image->image.assembly_name = image->image.name; /* they may be different */
4196 image->image.module_name = module_name;
4197 image->image.version = g_strdup (version);
4198 image->image.dynamic = TRUE;
4200 image->image.references = g_new0 (MonoAssembly*, 1);
4201 image->image.references [0] = NULL;
4203 mono_image_init (&image->image);
4205 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4206 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4207 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4208 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4209 image->handleref = g_hash_table_new (NULL, NULL);
4210 image->tokens = mono_g_hash_table_new (NULL, NULL);
4211 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4212 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4213 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4214 image->gen_params = g_ptr_array_new ();
4216 string_heap_init (&image->sheap);
4217 mono_image_add_stream_data (&image->us, "", 1);
4218 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4219 /* import tables... */
4220 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4221 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4222 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4223 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4225 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4226 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4227 stream_data_align (&image->code);
4229 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4231 for (i=0; i < 64; ++i) {
4232 image->tables [i].next_idx = 1;
4233 image->tables [i].columns = table_sizes [i];
4236 image->image.assembly = (MonoAssembly*)assembly;
4237 image->run = assembly->run;
4238 image->save = assembly->save;
4239 image->pe_kind = 0x1; /* ILOnly */
4240 image->machine = 0x14c; /* I386 */
4242 return image;
4246 * mono_image_basic_init:
4247 * @assembly: an assembly builder object
4249 * Create the MonoImage that represents the assembly builder and setup some
4250 * of the helper hash table and the basic metadata streams.
4252 void
4253 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4255 MonoDynamicAssembly *assembly;
4256 MonoDynamicImage *image;
4258 MONO_ARCH_SAVE_REGS;
4260 if (assemblyb->dynamic_assembly)
4261 return;
4263 #if HAVE_BOEHM_GC
4264 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4265 #else
4266 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4267 #endif
4269 assembly->assembly.dynamic = TRUE;
4270 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4271 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4272 if (assemblyb->culture)
4273 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4274 else
4275 assembly->assembly.aname.culture = g_strdup ("");
4277 assembly->run = assemblyb->access != 2;
4278 assembly->save = assemblyb->access != 1;
4280 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4281 image->initial_image = TRUE;
4282 assembly->assembly.aname.name = image->image.name;
4283 assembly->assembly.image = &image->image;
4285 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4286 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4289 static int
4290 calc_section_size (MonoDynamicImage *assembly)
4292 int nsections = 0;
4294 /* alignment constraints */
4295 assembly->code.index += 3;
4296 assembly->code.index &= ~3;
4297 assembly->meta_size += 3;
4298 assembly->meta_size &= ~3;
4299 assembly->resources.index += 3;
4300 assembly->resources.index &= ~3;
4302 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4303 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4304 nsections++;
4306 if (assembly->win32_res) {
4307 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4309 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4310 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4311 nsections++;
4314 assembly->sections [MONO_SECTION_RELOC].size = 12;
4315 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4316 nsections++;
4318 return nsections;
4321 typedef struct {
4322 guint32 id;
4323 guint32 offset;
4324 GSList *children;
4325 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4326 } ResTreeNode;
4328 static int
4329 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4331 ResTreeNode *t1 = (ResTreeNode*)a;
4332 ResTreeNode *t2 = (ResTreeNode*)b;
4334 return t1->id - t2->id;
4338 * resource_tree_create:
4340 * Organize the resources into a resource tree.
4342 static ResTreeNode *
4343 resource_tree_create (MonoArray *win32_resources)
4345 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4346 GSList *l;
4347 int i;
4349 tree = g_new0 (ResTreeNode, 1);
4351 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4352 MonoReflectionWin32Resource *win32_res =
4353 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4355 /* Create node */
4357 lang_node = g_new0 (ResTreeNode, 1);
4358 lang_node->id = win32_res->lang_id;
4359 lang_node->win32_res = win32_res;
4361 /* Create type node if neccesary */
4362 type_node = NULL;
4363 for (l = tree->children; l; l = l->next)
4364 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4365 type_node = (ResTreeNode*)l->data;
4366 break;
4369 if (!type_node) {
4370 type_node = g_new0 (ResTreeNode, 1);
4371 type_node->id = win32_res->res_type;
4374 * The resource types have to be sorted otherwise
4375 * Windows Explorer can't display the version information.
4377 tree->children = g_slist_insert_sorted (tree->children,
4378 type_node, resource_tree_compare_by_id);
4381 /* Create res node if neccesary */
4382 res_node = NULL;
4383 for (l = type_node->children; l; l = l->next)
4384 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4385 res_node = (ResTreeNode*)l->data;
4386 break;
4389 if (!res_node) {
4390 res_node = g_new0 (ResTreeNode, 1);
4391 res_node->id = win32_res->res_id;
4392 type_node->children = g_slist_append (type_node->children, res_node);
4395 res_node->children = g_slist_append (res_node->children, lang_node);
4398 return tree;
4402 * resource_tree_encode:
4404 * Encode the resource tree into the format used in the PE file.
4406 static void
4407 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4409 char *entries;
4410 MonoPEResourceDir dir;
4411 MonoPEResourceDirEntry dir_entry;
4412 MonoPEResourceDataEntry data_entry;
4413 GSList *l;
4416 * For the format of the resource directory, see the article
4417 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4418 * Matt Pietrek
4421 memset (&dir, 0, sizeof (dir));
4422 memset (&dir_entry, 0, sizeof (dir_entry));
4423 memset (&data_entry, 0, sizeof (data_entry));
4425 g_assert (sizeof (dir) == 16);
4426 g_assert (sizeof (dir_entry) == 8);
4427 g_assert (sizeof (data_entry) == 16);
4429 node->offset = p - begin;
4431 /* IMAGE_RESOURCE_DIRECTORY */
4432 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4434 memcpy (p, &dir, sizeof (dir));
4435 p += sizeof (dir);
4437 /* Reserve space for entries */
4438 entries = p;
4439 p += sizeof (dir_entry) * dir.res_id_entries;
4441 /* Write children */
4442 for (l = node->children; l; l = l->next) {
4443 ResTreeNode *child = (ResTreeNode*)l->data;
4445 if (child->win32_res) {
4447 child->offset = p - begin;
4449 /* IMAGE_RESOURCE_DATA_ENTRY */
4450 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4451 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4453 memcpy (p, &data_entry, sizeof (data_entry));
4454 p += sizeof (data_entry);
4456 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4457 p += data_entry.rde_size;
4458 } else {
4459 resource_tree_encode (child, begin, p, &p);
4463 /* IMAGE_RESOURCE_ENTRY */
4464 for (l = node->children; l; l = l->next) {
4465 ResTreeNode *child = (ResTreeNode*)l->data;
4466 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4468 dir_entry.is_dir = child->win32_res ? 0 : 1;
4469 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4471 memcpy (entries, &dir_entry, sizeof (dir_entry));
4472 entries += sizeof (dir_entry);
4475 *endbuf = p;
4478 static void
4479 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4481 char *buf;
4482 char *p;
4483 guint32 size, i;
4484 MonoReflectionWin32Resource *win32_res;
4485 ResTreeNode *tree;
4487 if (!assemblyb->win32_resources)
4488 return;
4491 * Resources are stored in a three level tree inside the PE file.
4492 * - level one contains a node for each type of resource
4493 * - level two contains a node for each resource
4494 * - level three contains a node for each instance of a resource for a
4495 * specific language.
4498 tree = resource_tree_create (assemblyb->win32_resources);
4500 /* Estimate the size of the encoded tree */
4501 size = 0;
4502 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4503 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4504 size += mono_array_length (win32_res->res_data);
4506 /* Directory structure */
4507 size += mono_array_length (assemblyb->win32_resources) * 256;
4508 p = buf = g_malloc (size);
4510 resource_tree_encode (tree, p, p, &p);
4512 g_assert (p - buf < size);
4514 assembly->win32_res = g_malloc (p - buf);
4515 assembly->win32_res_size = p - buf;
4516 memcpy (assembly->win32_res, buf, p - buf);
4518 g_free (buf);
4521 static void
4522 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4524 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4525 int i;
4527 p += sizeof (MonoPEResourceDir);
4528 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4529 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4530 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4531 if (dir_entry->is_dir) {
4532 fixup_resource_directory (res_section, child, rva);
4533 } else {
4534 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4535 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4538 p += sizeof (MonoPEResourceDirEntry);
4543 * mono_image_create_pefile:
4544 * @mb: a module builder object
4546 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4547 * assembly->pefile where it can be easily retrieved later in chunks.
4549 void
4550 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4551 MonoMSDOSHeader *msdos;
4552 MonoDotNetHeader *header;
4553 MonoSectionTable *section;
4554 MonoCLIHeader *cli_header;
4555 guint32 size, image_size, virtual_base, text_offset;
4556 guint32 header_start, section_start, file_offset, virtual_offset;
4557 MonoDynamicImage *assembly;
4558 MonoReflectionAssemblyBuilder *assemblyb;
4559 MonoDynamicStream *pefile;
4560 int i, nsections;
4561 guint32 *rva, value;
4562 guint16 *data16;
4563 guchar *p;
4564 static const unsigned char msheader[] = {
4565 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4566 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4569 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4570 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4571 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4572 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4575 assemblyb = mb->assemblyb;
4577 mono_image_basic_init (assemblyb);
4578 assembly = mb->dynamic_image;
4580 assembly->pe_kind = assemblyb->pe_kind;
4581 assembly->machine = assemblyb->machine;
4582 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4583 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4585 /* already created */
4586 if (assembly->pefile.index)
4587 return;
4589 mono_image_build_metadata (mb);
4591 if (mb->is_main && assemblyb->resources) {
4592 int len = mono_array_length (assemblyb->resources);
4593 for (i = 0; i < len; ++i)
4594 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4597 if (mb->resources) {
4598 int len = mono_array_length (mb->resources);
4599 for (i = 0; i < len; ++i)
4600 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4603 build_compressed_metadata (assembly);
4605 if (mb->is_main)
4606 assembly_add_win32_resources (assembly, assemblyb);
4608 nsections = calc_section_size (assembly);
4610 pefile = &assembly->pefile;
4612 /* The DOS header and stub */
4613 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4614 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4616 /* the dotnet header */
4617 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4619 /* the section tables */
4620 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4622 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4623 virtual_offset = VIRT_ALIGN;
4624 image_size = 0;
4626 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4627 if (!assembly->sections [i].size)
4628 continue;
4629 /* align offsets */
4630 file_offset += FILE_ALIGN - 1;
4631 file_offset &= ~(FILE_ALIGN - 1);
4632 virtual_offset += VIRT_ALIGN - 1;
4633 virtual_offset &= ~(VIRT_ALIGN - 1);
4635 assembly->sections [i].offset = file_offset;
4636 assembly->sections [i].rva = virtual_offset;
4638 file_offset += assembly->sections [i].size;
4639 virtual_offset += assembly->sections [i].size;
4640 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4643 file_offset += FILE_ALIGN - 1;
4644 file_offset &= ~(FILE_ALIGN - 1);
4645 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4647 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4649 /* back-patch info */
4650 msdos = (MonoMSDOSHeader*)pefile->data;
4651 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4652 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4653 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4655 header = (MonoDotNetHeader*)(pefile->data + header_start);
4656 header->pesig [0] = 'P';
4657 header->pesig [1] = 'E';
4659 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4660 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4661 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4662 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4663 if (assemblyb->pekind == 1) {
4664 /* it's a dll */
4665 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4666 } else {
4667 /* it's an exe */
4668 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4671 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4673 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4674 header->pe.pe_major = 6;
4675 header->pe.pe_minor = 0;
4676 size = assembly->sections [MONO_SECTION_TEXT].size;
4677 size += FILE_ALIGN - 1;
4678 size &= ~(FILE_ALIGN - 1);
4679 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4680 size = assembly->sections [MONO_SECTION_RSRC].size;
4681 size += FILE_ALIGN - 1;
4682 size &= ~(FILE_ALIGN - 1);
4683 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4684 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4685 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4686 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4687 /* pe_rva_entry_point always at the beginning of the text section */
4688 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4690 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4691 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4692 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4693 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4694 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4695 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4696 size = section_start;
4697 size += FILE_ALIGN - 1;
4698 size &= ~(FILE_ALIGN - 1);
4699 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4700 size = image_size;
4701 size += VIRT_ALIGN - 1;
4702 size &= ~(VIRT_ALIGN - 1);
4703 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4706 // Translate the PEFileKind value to the value expected by the Windows loader
4709 short kind;
4712 // PEFileKinds.Dll == 1
4713 // PEFileKinds.ConsoleApplication == 2
4714 // PEFileKinds.WindowApplication == 3
4716 // need to get:
4717 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4718 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4720 if (assemblyb->pekind == 3)
4721 kind = 2;
4722 else
4723 kind = 3;
4725 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4727 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4728 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4729 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4730 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4731 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4732 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4734 /* fill data directory entries */
4736 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4737 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4739 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4740 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4742 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4743 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4744 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4745 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4746 /* patch entrypoint name */
4747 if (assemblyb->pekind == 1)
4748 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4749 else
4750 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4751 /* patch imported function RVA name */
4752 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4753 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4755 /* the import table */
4756 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4757 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4758 /* patch imported dll RVA name and other entries in the dir */
4759 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4760 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4761 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4762 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4763 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4766 p = (assembly->code.data + assembly->ilt_offset);
4767 value = (assembly->text_rva + assembly->imp_names_offset);
4768 *p++ = (value) & 0xff;
4769 *p++ = (value >> 8) & (0xff);
4770 *p++ = (value >> 16) & (0xff);
4771 *p++ = (value >> 24) & (0xff);
4773 /* the CLI header info */
4774 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4775 cli_header->ch_size = GUINT32_FROM_LE (72);
4776 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4777 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4778 if (assemblyb->entry_point) {
4779 guint32 table_idx = 0;
4780 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4781 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4782 table_idx = methodb->table_idx;
4783 } else {
4784 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4786 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4787 } else {
4788 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4790 /* The embedded managed resources */
4791 text_offset = assembly->text_rva + assembly->code.index;
4792 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4793 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4794 text_offset += assembly->resources.index;
4795 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4796 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4797 text_offset += assembly->meta_size;
4798 if (assembly->strong_name_size) {
4799 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4800 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4801 text_offset += assembly->strong_name_size;
4804 /* write the section tables and section content */
4805 section = (MonoSectionTable*)(pefile->data + section_start);
4806 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4807 static const char *section_names [] = {
4808 ".text", ".rsrc", ".reloc"
4810 if (!assembly->sections [i].size)
4811 continue;
4812 strcpy (section->st_name, section_names [i]);
4813 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4814 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4815 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4816 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4817 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4818 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4819 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4820 switch (i) {
4821 case MONO_SECTION_TEXT:
4822 /* patch entry point */
4823 p = (assembly->code.data + 2);
4824 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4825 *p++ = (value) & 0xff;
4826 *p++ = (value >> 8) & 0xff;
4827 *p++ = (value >> 16) & 0xff;
4828 *p++ = (value >> 24) & 0xff;
4830 text_offset = assembly->sections [i].offset;
4831 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4832 text_offset += assembly->code.index;
4833 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4834 text_offset += assembly->resources.index;
4835 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4836 text_offset += assembly->meta_size;
4837 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4839 g_free (assembly->image.raw_metadata);
4840 break;
4841 case MONO_SECTION_RELOC:
4842 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4843 *rva = GUINT32_FROM_LE (assembly->text_rva);
4844 ++rva;
4845 *rva = GUINT32_FROM_LE (12);
4846 ++rva;
4847 data16 = (guint16*)rva;
4849 * the entrypoint is always at the start of the text section
4850 * 3 is IMAGE_REL_BASED_HIGHLOW
4851 * 2 is patch_size_rva - text_rva
4853 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4854 data16++;
4855 *data16 = 0; /* terminate */
4856 break;
4857 case MONO_SECTION_RSRC:
4858 if (assembly->win32_res) {
4859 text_offset = assembly->sections [i].offset;
4861 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4862 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4864 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4866 break;
4867 default:
4868 g_assert_not_reached ();
4870 section++;
4873 /* check that the file is properly padded */
4874 #if 0
4876 FILE *f = fopen ("mypetest.exe", "w");
4877 fwrite (pefile->data, pefile->index, 1, f);
4878 fclose (f);
4880 #endif
4883 MonoReflectionModule *
4884 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4886 char *name;
4887 MonoImage *image;
4888 MonoImageOpenStatus status;
4889 MonoDynamicAssembly *assembly;
4890 guint32 module_count;
4891 MonoImage **new_modules;
4893 name = mono_string_to_utf8 (fileName);
4895 image = mono_image_open (name, &status);
4896 if (status) {
4897 MonoException *exc;
4898 if (status == MONO_IMAGE_ERROR_ERRNO)
4899 exc = mono_get_exception_file_not_found (fileName);
4900 else
4901 exc = mono_get_exception_bad_image_format (name);
4902 g_free (name);
4903 mono_raise_exception (exc);
4906 g_free (name);
4908 assembly = ab->dynamic_assembly;
4909 image->assembly = (MonoAssembly*)assembly;
4911 module_count = image->assembly->image->module_count;
4912 new_modules = g_new0 (MonoImage *, module_count + 1);
4914 if (image->assembly->image->modules)
4915 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4916 new_modules [module_count] = image;
4918 g_free (image->assembly->image->modules);
4919 image->assembly->image->modules = new_modules;
4920 image->assembly->image->module_count ++;
4922 mono_assembly_load_references (image, &status);
4923 if (status) {
4924 mono_image_close (image);
4925 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4928 return mono_module_get_object (mono_domain_get (), image);
4932 * We need to return always the same object for MethodInfo, FieldInfo etc..
4933 * but we need to consider the reflected type.
4934 * type uses a different hash, since it uses custom hash/equal functions.
4937 typedef struct {
4938 gpointer item;
4939 MonoClass *refclass;
4940 } ReflectedEntry;
4942 static gboolean
4943 reflected_equal (gconstpointer a, gconstpointer b) {
4944 const ReflectedEntry *ea = a;
4945 const ReflectedEntry *eb = b;
4947 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4950 static guint
4951 reflected_hash (gconstpointer a) {
4952 const ReflectedEntry *ea = a;
4953 return GPOINTER_TO_UINT (ea->item);
4956 #define CHECK_OBJECT(t,p,k) \
4957 do { \
4958 t _obj; \
4959 ReflectedEntry e; \
4960 e.item = (p); \
4961 e.refclass = (k); \
4962 mono_domain_lock (domain); \
4963 if (!domain->refobject_hash) \
4964 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4965 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4966 mono_domain_unlock (domain); \
4967 return _obj; \
4969 } while (0)
4971 #if HAVE_BOEHM_GC
4972 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4973 #else
4974 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4975 #endif
4977 #define CACHE_OBJECT(p,o,k) \
4978 do { \
4979 ReflectedEntry *e = ALLOC_REFENTRY; \
4980 e->item = (p); \
4981 e->refclass = (k); \
4982 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4983 mono_domain_unlock (domain); \
4984 } while (0)
4986 static void
4987 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4989 /* this is done only once */
4990 mono_domain_lock (domain);
4991 CACHE_OBJECT (assembly, res, NULL);
4994 static void
4995 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4997 /* this is done only once */
4998 mono_domain_lock (domain);
4999 CACHE_OBJECT (module, res, NULL);
5002 void
5003 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5005 MonoDynamicImage *image = moduleb->dynamic_image;
5006 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5007 if (!image) {
5009 * FIXME: we already created an image in mono_image_basic_init (), but
5010 * we don't know which module it belongs to, since that is only
5011 * determined at assembly save time.
5013 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5014 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5016 moduleb->module.image = &image->image;
5017 moduleb->dynamic_image = image;
5018 register_module (mono_object_domain (moduleb), moduleb, image);
5023 * mono_assembly_get_object:
5024 * @domain: an app domain
5025 * @assembly: an assembly
5027 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5029 MonoReflectionAssembly*
5030 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5032 static MonoClass *System_Reflection_Assembly;
5033 MonoReflectionAssembly *res;
5035 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5036 if (!System_Reflection_Assembly)
5037 System_Reflection_Assembly = mono_class_from_name (
5038 mono_defaults.corlib, "System.Reflection", "Assembly");
5039 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5040 res->assembly = assembly;
5041 CACHE_OBJECT (assembly, res, NULL);
5042 return res;
5047 MonoReflectionModule*
5048 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5050 static MonoClass *System_Reflection_Module;
5051 MonoReflectionModule *res;
5052 char* basename;
5054 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5055 if (!System_Reflection_Module)
5056 System_Reflection_Module = mono_class_from_name (
5057 mono_defaults.corlib, "System.Reflection", "Module");
5058 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5060 res->image = image;
5061 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5063 res->fqname = mono_string_new (domain, image->name);
5064 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5065 res->scopename = mono_string_new (domain, image->module_name);
5067 g_free (basename);
5069 if (image->assembly->image == image) {
5070 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5071 } else {
5072 int i;
5073 g_assert (image->assembly->image->modules);
5074 res->token = 0;
5075 for (i = 0; i < image->assembly->image->module_count; i++) {
5076 if (image->assembly->image->modules [i] == image)
5077 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5079 g_assert (res->token);
5082 mono_image_addref (image);
5084 CACHE_OBJECT (image, res, NULL);
5085 return res;
5088 MonoReflectionModule*
5089 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5091 static MonoClass *System_Reflection_Module;
5092 MonoReflectionModule *res;
5093 MonoTableInfo *table;
5094 guint32 cols [MONO_FILE_SIZE];
5095 const char *name;
5096 guint32 i, name_idx;
5097 const char *val;
5099 if (!System_Reflection_Module)
5100 System_Reflection_Module = mono_class_from_name (
5101 mono_defaults.corlib, "System.Reflection", "Module");
5102 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5104 table = &image->tables [MONO_TABLE_FILE];
5105 g_assert (table_index < table->rows);
5106 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5108 res->image = 0;
5109 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5110 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5112 /* Check whenever the row has a corresponding row in the moduleref table */
5113 table = &image->tables [MONO_TABLE_MODULEREF];
5114 for (i = 0; i < table->rows; ++i) {
5115 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5116 val = mono_metadata_string_heap (image, name_idx);
5117 if (strcmp (val, name) == 0)
5118 res->image = image->modules [i];
5121 res->fqname = mono_string_new (domain, name);
5122 res->name = mono_string_new (domain, name);
5123 res->scopename = mono_string_new (domain, name);
5124 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5125 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5127 return res;
5130 static gboolean
5131 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5133 if ((t1->type != t2->type) ||
5134 (t1->byref != t2->byref))
5135 return FALSE;
5137 switch (t1->type) {
5138 case MONO_TYPE_VOID:
5139 case MONO_TYPE_BOOLEAN:
5140 case MONO_TYPE_CHAR:
5141 case MONO_TYPE_I1:
5142 case MONO_TYPE_U1:
5143 case MONO_TYPE_I2:
5144 case MONO_TYPE_U2:
5145 case MONO_TYPE_I4:
5146 case MONO_TYPE_U4:
5147 case MONO_TYPE_I8:
5148 case MONO_TYPE_U8:
5149 case MONO_TYPE_R4:
5150 case MONO_TYPE_R8:
5151 case MONO_TYPE_STRING:
5152 case MONO_TYPE_I:
5153 case MONO_TYPE_U:
5154 case MONO_TYPE_OBJECT:
5155 case MONO_TYPE_TYPEDBYREF:
5156 return TRUE;
5157 case MONO_TYPE_VALUETYPE:
5158 case MONO_TYPE_CLASS:
5159 case MONO_TYPE_SZARRAY:
5160 return t1->data.klass == t2->data.klass;
5161 case MONO_TYPE_PTR:
5162 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5163 case MONO_TYPE_ARRAY:
5164 if (t1->data.array->rank != t2->data.array->rank)
5165 return FALSE;
5166 return t1->data.array->eklass == t2->data.array->eklass;
5167 case MONO_TYPE_GENERICINST: {
5168 int i;
5169 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5170 return FALSE;
5171 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5172 return FALSE;
5173 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5174 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5175 return FALSE;
5177 return TRUE;
5179 case MONO_TYPE_VAR:
5180 case MONO_TYPE_MVAR:
5181 return t1->data.generic_param == t2->data.generic_param;
5182 default:
5183 g_error ("implement type compare for %0x!", t1->type);
5184 return FALSE;
5187 return FALSE;
5190 static guint
5191 mymono_metadata_type_hash (MonoType *t1)
5193 guint hash;
5195 hash = t1->type;
5197 hash |= t1->byref << 6; /* do not collide with t1->type values */
5198 switch (t1->type) {
5199 case MONO_TYPE_VALUETYPE:
5200 case MONO_TYPE_CLASS:
5201 case MONO_TYPE_SZARRAY:
5202 /* check if the distribution is good enough */
5203 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5204 case MONO_TYPE_PTR:
5205 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5207 return hash;
5210 static MonoReflectionGenericInst*
5211 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5213 static MonoClass *System_Reflection_MonoGenericInst;
5214 MonoReflectionGenericInst *res;
5215 MonoGenericInst *ginst;
5216 MonoClass *gklass;
5218 if (!System_Reflection_MonoGenericInst) {
5219 System_Reflection_MonoGenericInst = mono_class_from_name (
5220 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5221 g_assert (System_Reflection_MonoGenericInst);
5224 ginst = geninst->data.generic_inst;
5225 gklass = mono_class_from_mono_type (ginst->generic_type);
5227 mono_class_init (ginst->klass);
5229 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5231 res->type.type = geninst;
5232 if (gklass->wastypebuilder && gklass->reflection_info)
5233 res->generic_type = gklass->reflection_info;
5234 else
5235 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5237 return res;
5241 * mono_type_get_object:
5242 * @domain: an app domain
5243 * @type: a type
5245 * Return an System.MonoType object representing the type @type.
5247 MonoReflectionType*
5248 mono_type_get_object (MonoDomain *domain, MonoType *type)
5250 MonoReflectionType *res;
5251 MonoClass *klass = mono_class_from_mono_type (type);
5253 mono_domain_lock (domain);
5254 if (!domain->type_hash)
5255 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5256 (GCompareFunc)mymono_metadata_type_equal);
5257 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5258 mono_domain_unlock (domain);
5259 return res;
5261 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5262 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5263 mono_g_hash_table_insert (domain->type_hash, type, res);
5264 mono_domain_unlock (domain);
5265 return res;
5267 if (klass->reflection_info && !klass->wastypebuilder) {
5268 /* g_assert_not_reached (); */
5269 /* should this be considered an error condition? */
5270 if (!type->byref) {
5271 mono_domain_unlock (domain);
5272 return klass->reflection_info;
5275 mono_class_init (klass);
5276 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5277 res->type = type;
5278 mono_g_hash_table_insert (domain->type_hash, type, res);
5279 mono_domain_unlock (domain);
5280 return res;
5284 * mono_method_get_object:
5285 * @domain: an app domain
5286 * @method: a method
5287 * @refclass: the reflected type (can be NULL)
5289 * Return an System.Reflection.MonoMethod object representing the method @method.
5291 MonoReflectionMethod*
5292 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5295 * We use the same C representation for methods and constructors, but the type
5296 * name in C# is different.
5298 const char *cname;
5299 MonoClass *klass;
5300 MonoReflectionMethod *ret;
5302 if (!refclass)
5303 refclass = method->klass;
5305 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5306 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5307 cname = "MonoCMethod";
5308 else
5309 cname = "MonoMethod";
5310 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5312 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5313 ret->method = method;
5314 ret->name = mono_string_new (domain, method->name);
5315 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5316 CACHE_OBJECT (method, ret, refclass);
5317 return ret;
5321 * mono_field_get_object:
5322 * @domain: an app domain
5323 * @klass: a type
5324 * @field: a field
5326 * Return an System.Reflection.MonoField object representing the field @field
5327 * in class @klass.
5329 MonoReflectionField*
5330 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5332 MonoReflectionField *res;
5333 MonoClass *oklass;
5335 CHECK_OBJECT (MonoReflectionField *, field, klass);
5336 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5337 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5338 res->klass = klass;
5339 res->field = field;
5340 res->name = mono_string_new (domain, field->name);
5341 if (field->generic_info)
5342 res->attrs = field->generic_info->generic_type->attrs;
5343 else
5344 res->attrs = field->type->attrs;
5345 res->type = mono_type_get_object (domain, field->type);
5346 CACHE_OBJECT (field, res, klass);
5347 return res;
5351 * mono_property_get_object:
5352 * @domain: an app domain
5353 * @klass: a type
5354 * @property: a property
5356 * Return an System.Reflection.MonoProperty object representing the property @property
5357 * in class @klass.
5359 MonoReflectionProperty*
5360 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5362 MonoReflectionProperty *res;
5363 MonoClass *oklass;
5365 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5366 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5367 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5368 res->klass = klass;
5369 res->property = property;
5370 CACHE_OBJECT (property, res, klass);
5371 return res;
5375 * mono_event_get_object:
5376 * @domain: an app domain
5377 * @klass: a type
5378 * @event: a event
5380 * Return an System.Reflection.MonoEvent object representing the event @event
5381 * in class @klass.
5383 MonoReflectionEvent*
5384 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5386 MonoReflectionEvent *res;
5387 MonoClass *oklass;
5389 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5390 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5391 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5392 res->klass = klass;
5393 res->event = event;
5394 CACHE_OBJECT (event, res, klass);
5395 return res;
5399 * mono_param_get_objects:
5400 * @domain: an app domain
5401 * @method: a method
5403 * Return an System.Reflection.ParameterInfo array object representing the parameters
5404 * in the method @method.
5406 MonoArray*
5407 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5409 static MonoClass *System_Reflection_ParameterInfo;
5410 MonoArray *res = NULL;
5411 MonoReflectionMethod *member = NULL;
5412 MonoReflectionParameter *param = NULL;
5413 char **names, **blobs = NULL;
5414 MonoObject *dbnull = mono_get_dbnull_object (domain);
5415 MonoMarshalSpec **mspecs;
5416 int i;
5418 if (!System_Reflection_ParameterInfo)
5419 System_Reflection_ParameterInfo = mono_class_from_name (
5420 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5422 if (!method->signature->param_count)
5423 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5425 /* Note: the cache is based on the address of the signature into the method
5426 * since we already cache MethodInfos with the method as keys.
5428 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5430 member = mono_method_get_object (domain, method, NULL);
5431 names = g_new (char *, method->signature->param_count);
5432 mono_method_get_param_names (method, (const char **) names);
5434 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5435 mono_method_get_marshal_info (method, mspecs);
5437 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5438 for (i = 0; i < method->signature->param_count; ++i) {
5439 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5440 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5441 param->MemberImpl = (MonoObject*)member;
5442 param->NameImpl = mono_string_new (domain, names [i]);
5443 param->PositionImpl = i;
5444 param->AttrsImpl = method->signature->params [i]->attrs;
5446 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5447 param->DefaultValueImpl = dbnull;
5448 } else {
5449 MonoType *type = param->ClassImpl->type;
5451 if (!blobs) {
5452 blobs = g_new0 (char *, method->signature->param_count);
5453 get_default_param_value_blobs (method, blobs);
5456 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5458 if (!param->DefaultValueImpl) {
5459 param->DefaultValueImpl = dbnull;
5463 if (mspecs [i + 1])
5464 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5466 mono_array_set (res, gpointer, i, param);
5468 g_free (names);
5469 g_free (blobs);
5471 for (i = method->signature->param_count; i >= 0; i--)
5472 if (mspecs [i])
5473 mono_metadata_free_marshal_spec (mspecs [i]);
5474 g_free (mspecs);
5476 CACHE_OBJECT (&(method->signature), res, NULL);
5477 return res;
5481 * mono_method_body_get_object:
5482 * @domain: an app domain
5483 * @method: a method
5485 * Return an System.Reflection.MethodBody object representing the method @method.
5487 MonoReflectionMethodBody*
5488 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5490 static MonoClass *System_Reflection_MethodBody = NULL;
5491 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5492 MonoReflectionMethodBody *ret;
5493 MonoMethodNormal *mn;
5494 MonoMethodHeader *header;
5495 int i;
5497 if (!System_Reflection_MethodBody)
5498 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5499 if (!System_Reflection_LocalVariableInfo)
5500 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5502 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5504 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5505 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5506 return NULL;
5507 mn = (MonoMethodNormal *)method;
5508 header = mn->header;
5510 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5511 /* FIXME: Other fields */
5512 ret->init_locals = header->init_locals;
5513 ret->max_stack = header->max_stack;
5514 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5515 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5516 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5517 for (i = 0; i < header->num_locals; ++i) {
5518 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5519 info->local_type = mono_type_get_object (domain, header->locals [i]);
5520 info->is_pinned = header->locals [i]->pinned;
5521 info->local_index = 0;
5524 CACHE_OBJECT (method, ret, NULL);
5525 return ret;
5528 MonoObject *
5529 mono_get_dbnull_object (MonoDomain *domain)
5531 MonoObject *obj;
5532 MonoClass *klass;
5533 static MonoClassField *dbnull_value_field = NULL;
5535 if (!dbnull_value_field) {
5536 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5537 mono_class_init (klass);
5538 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5539 g_assert (dbnull_value_field);
5541 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5542 g_assert (obj);
5543 return obj;
5547 static void
5548 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5550 guint32 param_index, i, lastp, crow = 0;
5551 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5552 gint32 idx = -1;
5554 MonoClass *klass = method->klass;
5555 MonoImage *image = klass->image;
5556 MonoMethodSignature *methodsig = method->signature;
5558 MonoTableInfo *constt;
5559 MonoTableInfo *methodt;
5560 MonoTableInfo *paramt;
5562 if (!methodsig->param_count)
5563 return;
5565 if (klass->generic_inst) {
5566 return; /* FIXME - ??? */
5569 mono_class_init (klass);
5571 if (klass->image->dynamic) {
5572 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5573 if (aux && aux->param_defaults)
5574 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5575 return;
5578 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5579 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5580 constt = &image->tables [MONO_TABLE_CONSTANT];
5582 for (i = 0; i < klass->method.count; ++i) {
5583 if (method == klass->methods [i]) {
5584 idx = klass->method.first + i;
5585 break;
5589 g_assert (idx != -1);
5591 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5592 if (idx + 1 < methodt->rows)
5593 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5594 else
5595 lastp = paramt->rows + 1;
5597 for (i = param_index; i < lastp; ++i) {
5598 guint32 paramseq;
5600 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5601 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5603 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5604 continue;
5606 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5607 if (!crow) {
5608 continue;
5611 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5612 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5615 return;
5618 static MonoObject *
5619 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5621 void *retval;
5622 MonoClass *klass;
5623 MonoObject *object;
5625 if (!blob)
5626 return NULL;
5628 klass = mono_class_from_mono_type (type);
5629 if (klass->valuetype) {
5630 object = mono_object_new (domain, klass);
5631 retval = ((gchar *) object + sizeof (MonoObject));
5632 } else {
5633 retval = &object;
5636 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5637 return object;
5638 else
5639 return NULL;
5642 static int
5643 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5644 int found_sep;
5645 char *s;
5647 memset (assembly, 0, sizeof (MonoAssemblyName));
5648 assembly->name = p;
5649 assembly->culture = "";
5650 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5652 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5653 p++;
5654 found_sep = 0;
5655 while (*p == ' ' || *p == ',') {
5656 *p++ = 0;
5657 found_sep = 1;
5658 continue;
5660 /* failed */
5661 if (!found_sep)
5662 return 1;
5663 while (*p) {
5664 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5665 p += 8;
5666 assembly->major = strtoul (p, &s, 10);
5667 if (s == p || *s != '.')
5668 return 1;
5669 p = ++s;
5670 assembly->minor = strtoul (p, &s, 10);
5671 if (s == p || *s != '.')
5672 return 1;
5673 p = ++s;
5674 assembly->build = strtoul (p, &s, 10);
5675 if (s == p || *s != '.')
5676 return 1;
5677 p = ++s;
5678 assembly->revision = strtoul (p, &s, 10);
5679 if (s == p)
5680 return 1;
5681 p = s;
5682 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5683 p += 8;
5684 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5685 assembly->culture = "";
5686 p += 7;
5687 } else {
5688 assembly->culture = p;
5689 while (*p && *p != ',') {
5690 p++;
5693 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5694 p += 15;
5695 if (strncmp (p, "null", 4) == 0) {
5696 p += 4;
5697 } else {
5698 int len;
5699 gchar *start = p;
5700 while (*p && *p != ',') {
5701 p++;
5703 len = (p - start + 1);
5704 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5705 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5706 g_strlcpy (assembly->public_key_token, start, len);
5708 } else {
5709 while (*p && *p != ',')
5710 p++;
5712 found_sep = 0;
5713 while (*p == ' ' || *p == ',') {
5714 *p++ = 0;
5715 found_sep = 1;
5716 continue;
5718 /* failed */
5719 if (!found_sep)
5720 return 1;
5723 return 0;
5727 * mono_reflection_parse_type:
5728 * @name: type name
5730 * Parse a type name as accepted by the GetType () method and output the info
5731 * extracted in the info structure.
5732 * the name param will be mangled, so, make a copy before passing it to this function.
5733 * The fields in info will be valid until the memory pointed to by name is valid.
5734 * Returns 0 on parse error.
5735 * See also mono_type_get_name () below.
5738 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5740 char *start, *p, *w, *last_point, *startn;
5741 int in_modifiers = 0;
5742 int isbyref = 0, rank;
5744 start = p = w = name;
5746 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5747 info->name = info->name_space = NULL;
5748 info->nested = NULL;
5749 info->modifiers = NULL;
5751 /* last_point separates the namespace from the name */
5752 last_point = NULL;
5754 while (*p) {
5755 switch (*p) {
5756 case '+':
5757 *p = 0; /* NULL terminate the name */
5758 startn = p + 1;
5759 info->nested = g_list_append (info->nested, startn);
5760 /* we have parsed the nesting namespace + name */
5761 if (info->name)
5762 break;
5763 if (last_point) {
5764 info->name_space = start;
5765 *last_point = 0;
5766 info->name = last_point + 1;
5767 } else {
5768 info->name_space = (char *)"";
5769 info->name = start;
5771 break;
5772 case '.':
5773 last_point = w;
5774 break;
5775 case '\\':
5776 ++p;
5777 break;
5778 case '&':
5779 case '*':
5780 case '[':
5781 case ',':
5782 in_modifiers = 1;
5783 break;
5784 default:
5785 break;
5787 if (in_modifiers)
5788 break;
5789 *w++ = *p++;
5792 if (!info->name) {
5793 if (last_point) {
5794 info->name_space = start;
5795 *last_point = 0;
5796 info->name = last_point + 1;
5797 } else {
5798 info->name_space = (char *)"";
5799 info->name = start;
5802 while (*p) {
5803 switch (*p) {
5804 case '&':
5805 if (isbyref) /* only one level allowed by the spec */
5806 return 0;
5807 isbyref = 1;
5808 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5809 *p++ = 0;
5810 break;
5811 case '*':
5812 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5813 *p++ = 0;
5814 break;
5815 case '[':
5816 rank = 1;
5817 *p++ = 0;
5818 while (*p) {
5819 if (*p == ']')
5820 break;
5821 if (*p == ',')
5822 rank++;
5823 else if (*p != '*') /* '*' means unknown lower bound */
5824 return 0;
5825 ++p;
5827 if (*p++ != ']')
5828 return 0;
5829 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5830 break;
5831 case ',':
5832 *p++ = 0;
5833 while (*p) {
5834 if (*p == ' ') {
5835 ++p;
5836 continue;
5838 break;
5840 if (!*p)
5841 return 0; /* missing assembly name */
5842 if (!assembly_name_to_aname (&info->assembly, p))
5843 return 0;
5844 break;
5845 default:
5846 return 0;
5847 break;
5849 if (info->assembly.name)
5850 break;
5852 *w = 0; /* terminate class name */
5853 if (!info->name || !*info->name)
5854 return 0;
5855 /* add other consistency checks */
5856 return 1;
5859 static MonoType*
5860 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5862 MonoClass *klass;
5863 GList *mod;
5864 int modval;
5866 if (!image)
5867 image = mono_defaults.corlib;
5869 if (ignorecase)
5870 klass = mono_class_from_name_case (image, info->name_space, info->name);
5871 else
5872 klass = mono_class_from_name (image, info->name_space, info->name);
5873 if (!klass)
5874 return NULL;
5875 for (mod = info->nested; mod; mod = mod->next) {
5876 GList *nested;
5878 mono_class_init (klass);
5879 nested = klass->nested_classes;
5880 klass = NULL;
5881 while (nested) {
5882 klass = nested->data;
5883 if (ignorecase) {
5884 if (g_strcasecmp (klass->name, mod->data) == 0)
5885 break;
5886 } else {
5887 if (strcmp (klass->name, mod->data) == 0)
5888 break;
5890 klass = NULL;
5891 nested = nested->next;
5893 if (!klass)
5894 break;
5896 if (!klass)
5897 return NULL;
5898 mono_class_init (klass);
5899 for (mod = info->modifiers; mod; mod = mod->next) {
5900 modval = GPOINTER_TO_UINT (mod->data);
5901 if (!modval) { /* byref: must be last modifier */
5902 return &klass->this_arg;
5903 } else if (modval == -1) {
5904 klass = mono_ptr_class_get (&klass->byval_arg);
5905 } else { /* array rank */
5906 klass = mono_array_class_get (klass, modval);
5908 mono_class_init (klass);
5911 return &klass->byval_arg;
5915 * mono_reflection_get_type:
5916 * @image: a metadata context
5917 * @info: type description structure
5918 * @ignorecase: flag for case-insensitive string compares
5919 * @type_resolve: whenever type resolve was already tried
5921 * Build a MonoType from the type description in @info.
5925 MonoType*
5926 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5928 MonoType *type;
5929 MonoReflectionAssembly *assembly;
5930 GString *fullName;
5931 GList *mod;
5933 type = mono_reflection_get_type_internal (image, info, ignorecase);
5934 if (type)
5935 return type;
5936 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5937 return NULL;
5939 if (type_resolve) {
5940 if (*type_resolve)
5941 return NULL;
5942 else
5943 *type_resolve = TRUE;
5946 /* Reconstruct the type name */
5947 fullName = g_string_new ("");
5948 if (info->name_space && (info->name_space [0] != '\0'))
5949 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5950 else
5951 g_string_printf (fullName, info->name);
5952 for (mod = info->nested; mod; mod = mod->next)
5953 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5955 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5956 if (assembly) {
5957 if (assembly->assembly->dynamic) {
5958 /* Enumerate all modules */
5959 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5960 int i;
5962 type = NULL;
5963 if (abuilder->modules) {
5964 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5965 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5966 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5967 if (type)
5968 break;
5972 if (!type && abuilder->loaded_modules) {
5973 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5974 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5975 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5976 if (type)
5977 break;
5981 else
5982 type = mono_reflection_get_type_internal (assembly->assembly->image,
5983 info, ignorecase);
5985 g_string_free (fullName, TRUE);
5986 return type;
5990 * mono_reflection_type_from_name:
5991 * @name: type name.
5992 * @image: a metadata context (can be NULL).
5994 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5995 * it defaults to get the type from @image or, if @image is NULL or loading
5996 * from it fails, uses corlib.
5999 MonoType*
6000 mono_reflection_type_from_name (char *name, MonoImage *image)
6002 MonoType *type;
6003 MonoTypeNameParse info;
6004 MonoAssembly *assembly;
6005 char *tmp;
6006 gboolean type_resolve = FALSE;
6008 /* Make a copy since parse_type modifies its argument */
6009 tmp = g_strdup (name);
6011 /*g_print ("requested type %s\n", str);*/
6012 if (!mono_reflection_parse_type (tmp, &info)) {
6013 g_free (tmp);
6014 g_list_free (info.modifiers);
6015 g_list_free (info.nested);
6016 return NULL;
6019 if (info.assembly.name) {
6020 assembly = mono_assembly_loaded (&info.assembly);
6021 if (!assembly) {
6022 /* then we must load the assembly ourselve - see #60439 */
6023 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6024 if (!assembly) {
6025 g_free (tmp);
6026 g_list_free (info.modifiers);
6027 g_list_free (info.nested);
6028 return NULL;
6031 image = assembly->image;
6032 } else if (image == NULL) {
6033 image = mono_defaults.corlib;
6036 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6037 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6038 image = mono_defaults.corlib;
6039 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6042 g_free (tmp);
6043 g_list_free (info.modifiers);
6044 g_list_free (info.nested);
6045 return type;
6049 * mono_reflection_get_token:
6051 * Return the metadata token of OBJ which should be an object
6052 * representing a metadata element.
6054 guint32
6055 mono_reflection_get_token (MonoObject *obj)
6057 MonoClass *klass;
6058 guint32 token = 0;
6060 klass = obj->vtable->klass;
6062 if (strcmp (klass->name, "MethodBuilder") == 0) {
6063 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6065 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6066 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6067 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6069 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6070 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6071 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6072 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6073 if (tb->generic_params) {
6074 g_assert_not_reached ();
6075 } else {
6076 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6078 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6079 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6080 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6081 } else if (strcmp (klass->name, "MonoType") == 0) {
6082 MonoReflectionType *tb = (MonoReflectionType *)obj;
6083 token = mono_class_from_mono_type (tb->type)->type_token;
6084 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6085 strcmp (klass->name, "MonoMethod") == 0) {
6086 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6087 if (m->method->signature->is_inflated) {
6088 g_assert_not_reached ();
6089 } else if (m->method->signature->generic_param_count) {
6090 g_assert_not_reached ();
6091 } else if (m->method->klass->generic_inst) {
6092 g_assert_not_reached ();
6093 } else {
6094 token = m->method->token;
6096 } else if (strcmp (klass->name, "MonoField") == 0) {
6097 MonoReflectionField *f = (MonoReflectionField*)obj;
6099 token = mono_class_get_field_token (f->field);
6100 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6101 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6103 token = mono_class_get_property_token (p->property);
6104 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6105 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6107 token = mono_class_get_event_token (p->event);
6108 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6109 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6111 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6112 } else if (strcmp (klass->name, "Module") == 0) {
6113 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6115 token = m->token;
6116 } else if (strcmp (klass->name, "Assembly") == 0) {
6117 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6118 } else {
6119 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6120 MonoException *ex = mono_get_exception_not_implemented (msg);
6121 g_free (msg);
6122 mono_raise_exception (ex);
6125 return token;
6128 static void*
6129 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6131 int slen, type = t->type;
6132 handle_enum:
6133 switch (type) {
6134 case MONO_TYPE_U1:
6135 case MONO_TYPE_I1:
6136 case MONO_TYPE_BOOLEAN: {
6137 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6138 *bval = *p;
6139 *end = p + 1;
6140 return bval;
6142 case MONO_TYPE_CHAR:
6143 case MONO_TYPE_U2:
6144 case MONO_TYPE_I2: {
6145 guint16 *val = g_malloc (sizeof (guint16));
6146 *val = read16 (p);
6147 *end = p + 2;
6148 return val;
6150 #if SIZEOF_VOID_P == 4
6151 case MONO_TYPE_U:
6152 case MONO_TYPE_I:
6153 #endif
6154 case MONO_TYPE_R4:
6155 case MONO_TYPE_U4:
6156 case MONO_TYPE_I4: {
6157 guint32 *val = g_malloc (sizeof (guint32));
6158 *val = read32 (p);
6159 *end = p + 4;
6160 return val;
6162 #if SIZEOF_VOID_P == 8
6163 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6164 case MONO_TYPE_I:
6165 #endif
6166 case MONO_TYPE_R8:
6167 case MONO_TYPE_U8:
6168 case MONO_TYPE_I8: {
6169 guint64 *val = g_malloc (sizeof (guint64));
6170 *val = read64 (p);
6171 *end = p + 8;
6172 return val;
6174 case MONO_TYPE_VALUETYPE:
6175 if (t->data.klass->enumtype) {
6176 type = t->data.klass->enum_basetype->type;
6177 goto handle_enum;
6178 } else {
6179 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6181 break;
6182 case MONO_TYPE_STRING:
6183 if (*p == (char)0xFF) {
6184 *end = p + 1;
6185 return NULL;
6187 slen = mono_metadata_decode_value (p, &p);
6188 *end = p + slen;
6189 return mono_string_new_len (mono_domain_get (), p, slen);
6190 case MONO_TYPE_CLASS: {
6191 char *n;
6192 MonoType *t;
6193 if (*p == (char)0xFF) {
6194 *end = p + 1;
6195 return NULL;
6197 handle_type:
6198 slen = mono_metadata_decode_value (p, &p);
6199 n = g_memdup (p, slen + 1);
6200 n [slen] = 0;
6201 t = mono_reflection_type_from_name (n, image);
6202 if (!t)
6203 g_warning ("Cannot load type '%s'", n);
6204 g_free (n);
6205 *end = p + slen;
6206 if (t)
6207 return mono_type_get_object (mono_domain_get (), t);
6208 else
6209 return NULL;
6211 case MONO_TYPE_OBJECT: {
6212 char subt = *p++;
6213 MonoObject *obj;
6214 MonoClass *subc = NULL;
6215 void *val;
6217 if (subt == 0x50) {
6218 goto handle_type;
6219 } else if (subt == 0x0E) {
6220 type = MONO_TYPE_STRING;
6221 goto handle_enum;
6222 } else if (subt == 0x55) {
6223 char *n;
6224 MonoType *t;
6225 slen = mono_metadata_decode_value (p, &p);
6226 n = g_memdup (p, slen + 1);
6227 n [slen] = 0;
6228 t = mono_reflection_type_from_name (n, image);
6229 if (!t)
6230 g_warning ("Cannot load type '%s'", n);
6231 g_free (n);
6232 p += slen;
6233 subc = mono_class_from_mono_type (t);
6234 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6235 MonoType simple_type = {{0}};
6236 simple_type.type = subt;
6237 subc = mono_class_from_mono_type (&simple_type);
6238 } else {
6239 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6241 val = load_cattr_value (image, &subc->byval_arg, p, end);
6242 obj = mono_object_new (mono_domain_get (), subc);
6243 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6244 g_free (val);
6245 return obj;
6247 case MONO_TYPE_SZARRAY: {
6248 MonoArray *arr;
6249 guint32 i, alen, basetype;
6250 alen = read32 (p);
6251 p += 4;
6252 if (alen == 0xffffffff) {
6253 *end = p;
6254 return NULL;
6256 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6257 basetype = t->data.klass->byval_arg.type;
6258 switch (basetype)
6260 case MONO_TYPE_U1:
6261 case MONO_TYPE_I1:
6262 case MONO_TYPE_BOOLEAN:
6263 for (i = 0; i < alen; i++) {
6264 MonoBoolean val = *p++;
6265 mono_array_set (arr, MonoBoolean, i, val);
6267 break;
6268 case MONO_TYPE_CHAR:
6269 case MONO_TYPE_U2:
6270 case MONO_TYPE_I2:
6271 for (i = 0; i < alen; i++) {
6272 guint16 val = read16 (p);
6273 mono_array_set (arr, guint16, i, val);
6274 p += 2;
6276 break;
6277 case MONO_TYPE_R4:
6278 case MONO_TYPE_U4:
6279 case MONO_TYPE_I4:
6280 for (i = 0; i < alen; i++) {
6281 guint32 val = read32 (p);
6282 mono_array_set (arr, guint32, i, val);
6283 p += 4;
6285 break;
6286 case MONO_TYPE_R8:
6287 case MONO_TYPE_U8:
6288 case MONO_TYPE_I8:
6289 for (i = 0; i < alen; i++) {
6290 guint64 val = read64 (p);
6291 mono_array_set (arr, guint64, i, val);
6292 p += 8;
6294 break;
6295 case MONO_TYPE_CLASS:
6296 case MONO_TYPE_OBJECT:
6297 case MONO_TYPE_STRING:
6298 for (i = 0; i < alen; i++) {
6299 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6300 mono_array_set (arr, gpointer, i, item);
6302 break;
6303 default:
6304 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6306 *end=p;
6307 return arr;
6309 default:
6310 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6312 return NULL;
6315 static gboolean
6316 type_is_reference (MonoType *type)
6318 switch (type->type) {
6319 case MONO_TYPE_BOOLEAN:
6320 case MONO_TYPE_CHAR:
6321 case MONO_TYPE_U:
6322 case MONO_TYPE_I:
6323 case MONO_TYPE_U1:
6324 case MONO_TYPE_I1:
6325 case MONO_TYPE_U2:
6326 case MONO_TYPE_I2:
6327 case MONO_TYPE_U4:
6328 case MONO_TYPE_I4:
6329 case MONO_TYPE_U8:
6330 case MONO_TYPE_I8:
6331 case MONO_TYPE_R8:
6332 case MONO_TYPE_R4:
6333 case MONO_TYPE_VALUETYPE:
6334 return FALSE;
6335 default:
6336 return TRUE;
6340 static void
6341 free_param_data (MonoMethodSignature *sig, void **params) {
6342 int i;
6343 for (i = 0; i < sig->param_count; ++i) {
6344 if (!type_is_reference (sig->params [i]))
6345 g_free (params [i]);
6350 * Find the method index in the metadata methodDef table.
6351 * Later put these three helper methods in metadata and export them.
6353 static guint32
6354 find_method_index (MonoMethod *method) {
6355 MonoClass *klass = method->klass;
6356 int i;
6358 for (i = 0; i < klass->method.count; ++i) {
6359 if (method == klass->methods [i])
6360 return klass->method.first + 1 + i;
6362 return 0;
6366 * Find the field index in the metadata FieldDef table.
6368 static guint32
6369 find_field_index (MonoClass *klass, MonoClassField *field) {
6370 int i;
6372 for (i = 0; i < klass->field.count; ++i) {
6373 if (field == &klass->fields [i])
6374 return klass->field.first + 1 + i;
6376 return 0;
6380 * Find the property index in the metadata Property table.
6382 static guint32
6383 find_property_index (MonoClass *klass, MonoProperty *property) {
6384 int i;
6386 for (i = 0; i < klass->property.count; ++i) {
6387 if (property == &klass->properties [i])
6388 return klass->property.first + 1 + i;
6390 return 0;
6394 * Find the event index in the metadata Event table.
6396 static guint32
6397 find_event_index (MonoClass *klass, MonoEvent *event) {
6398 int i;
6400 for (i = 0; i < klass->event.count; ++i) {
6401 if (event == &klass->events [i])
6402 return klass->event.first + 1 + i;
6404 return 0;
6407 static MonoObject*
6408 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6410 const char *p = data;
6411 const char *named;
6412 guint32 i, j, num_named;
6413 MonoObject *attr;
6414 void **params;
6416 mono_class_init (method->klass);
6418 if (len == 0) {
6419 attr = mono_object_new (mono_domain_get (), method->klass);
6420 mono_runtime_invoke (method, attr, NULL, NULL);
6421 return attr;
6424 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6425 return NULL;
6427 /*g_print ("got attr %s\n", method->klass->name);*/
6429 params = g_new (void*, method->signature->param_count);
6431 /* skip prolog */
6432 p += 2;
6433 for (i = 0; i < method->signature->param_count; ++i) {
6434 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6437 named = p;
6438 attr = mono_object_new (mono_domain_get (), method->klass);
6439 mono_runtime_invoke (method, attr, params, NULL);
6440 free_param_data (method->signature, params);
6441 g_free (params);
6442 num_named = read16 (named);
6443 named += 2;
6444 for (j = 0; j < num_named; j++) {
6445 gint name_len;
6446 char *name, named_type, data_type;
6447 named_type = *named++;
6448 data_type = *named++; /* type of data */
6449 if (data_type == 0x55) {
6450 gint type_len;
6451 char *type_name;
6452 type_len = mono_metadata_decode_blob_size (named, &named);
6453 type_name = g_malloc (type_len + 1);
6454 memcpy (type_name, named, type_len);
6455 type_name [type_len] = 0;
6456 named += type_len;
6457 /* FIXME: lookup the type and check type consistency */
6458 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6459 /* this seems to be the type of the element of the array */
6460 /* g_print ("skipping 0x%02x after prop\n", *named); */
6461 named++;
6463 name_len = mono_metadata_decode_blob_size (named, &named);
6464 name = g_malloc (name_len + 1);
6465 memcpy (name, named, name_len);
6466 name [name_len] = 0;
6467 named += name_len;
6468 if (named_type == 0x53) {
6469 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6470 void *val = load_cattr_value (image, field->type, named, &named);
6471 mono_field_set_value (attr, field, val);
6472 if (!type_is_reference (field->type))
6473 g_free (val);
6474 } else if (named_type == 0x54) {
6475 MonoProperty *prop;
6476 void *pparams [1];
6477 MonoType *prop_type;
6479 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6480 /* can we have more that 1 arg in a custom attr named property? */
6481 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6482 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6483 mono_property_set_value (prop, attr, pparams, NULL);
6484 if (!type_is_reference (prop_type))
6485 g_free (pparams [0]);
6487 g_free (name);
6490 return attr;
6493 MonoArray*
6494 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6496 MonoArray *result;
6497 MonoClass *klass;
6498 MonoObject *attr;
6499 int i;
6501 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6502 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6503 for (i = 0; i < cinfo->num_attrs; ++i) {
6504 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6505 mono_array_set (result, gpointer, i, attr);
6507 return result;
6510 MonoCustomAttrInfo*
6511 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6513 guint32 mtoken, i, len;
6514 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6515 MonoTableInfo *ca;
6516 MonoCustomAttrInfo *ainfo;
6517 GList *tmp, *list = NULL;
6518 const char *data;
6520 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6522 i = mono_metadata_custom_attrs_from_index (image, idx);
6523 if (!i)
6524 return NULL;
6525 i --;
6526 while (i < ca->rows) {
6527 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6528 break;
6529 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6530 ++i;
6532 len = g_list_length (list);
6533 if (!len)
6534 return NULL;
6535 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6536 ainfo->num_attrs = len;
6537 ainfo->image = image;
6538 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6539 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6540 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6541 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6542 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6543 mtoken |= MONO_TOKEN_METHOD_DEF;
6544 break;
6545 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6546 mtoken |= MONO_TOKEN_MEMBER_REF;
6547 break;
6548 default:
6549 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6550 break;
6552 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6553 if (!ainfo->attrs [i].ctor)
6554 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6555 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6556 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6557 ainfo->attrs [i].data = data;
6559 g_list_free (list);
6561 return ainfo;
6564 MonoCustomAttrInfo*
6565 mono_custom_attrs_from_method (MonoMethod *method)
6567 MonoCustomAttrInfo *cinfo;
6568 guint32 idx;
6570 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6571 return cinfo;
6572 idx = find_method_index (method);
6573 idx <<= MONO_CUSTOM_ATTR_BITS;
6574 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6575 return mono_custom_attrs_from_index (method->klass->image, idx);
6578 MonoCustomAttrInfo*
6579 mono_custom_attrs_from_class (MonoClass *klass)
6581 MonoCustomAttrInfo *cinfo;
6582 guint32 idx;
6584 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6585 return cinfo;
6586 idx = mono_metadata_token_index (klass->type_token);
6587 idx <<= MONO_CUSTOM_ATTR_BITS;
6588 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6589 return mono_custom_attrs_from_index (klass->image, idx);
6592 MonoCustomAttrInfo*
6593 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6595 MonoCustomAttrInfo *cinfo;
6596 guint32 idx;
6598 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6599 return cinfo;
6600 idx = 1; /* there is only one assembly */
6601 idx <<= MONO_CUSTOM_ATTR_BITS;
6602 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6603 return mono_custom_attrs_from_index (assembly->image, idx);
6606 static MonoCustomAttrInfo*
6607 mono_custom_attrs_from_module (MonoImage *image)
6609 MonoCustomAttrInfo *cinfo;
6610 guint32 idx;
6612 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6613 return cinfo;
6614 idx = 1; /* there is only one module */
6615 idx <<= MONO_CUSTOM_ATTR_BITS;
6616 idx |= MONO_CUSTOM_ATTR_MODULE;
6617 return mono_custom_attrs_from_index (image, idx);
6620 MonoCustomAttrInfo*
6621 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6623 MonoCustomAttrInfo *cinfo;
6624 guint32 idx;
6626 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6627 return cinfo;
6628 idx = find_property_index (klass, property);
6629 idx <<= MONO_CUSTOM_ATTR_BITS;
6630 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6631 return mono_custom_attrs_from_index (klass->image, idx);
6634 MonoCustomAttrInfo*
6635 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6637 MonoCustomAttrInfo *cinfo;
6638 guint32 idx;
6640 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6641 return cinfo;
6642 idx = find_event_index (klass, event);
6643 idx <<= MONO_CUSTOM_ATTR_BITS;
6644 idx |= MONO_CUSTOM_ATTR_EVENT;
6645 return mono_custom_attrs_from_index (klass->image, idx);
6648 MonoCustomAttrInfo*
6649 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6651 MonoCustomAttrInfo *cinfo;
6652 guint32 idx;
6654 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6655 return cinfo;
6656 idx = find_field_index (klass, field);
6657 idx <<= MONO_CUSTOM_ATTR_BITS;
6658 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6659 return mono_custom_attrs_from_index (klass->image, idx);
6662 MonoCustomAttrInfo*
6663 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6665 MonoTableInfo *ca;
6666 guint32 i, idx, method_index;
6667 guint32 param_list, param_last, param_pos, found;
6668 MonoImage *image;
6669 MonoReflectionMethodAux *aux;
6671 if (method->klass->image->dynamic) {
6672 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6673 if (!aux || !aux->param_cattr)
6674 return NULL;
6675 return aux->param_cattr [param];
6678 image = method->klass->image;
6679 method_index = find_method_index (method);
6680 ca = &image->tables [MONO_TABLE_METHOD];
6682 if (method->klass->generic_inst || method->klass->generic_container ||
6683 method->signature->generic_param_count) {
6684 /* FIXME FIXME FIXME */
6685 return NULL;
6688 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6689 if (method_index == ca->rows) {
6690 ca = &image->tables [MONO_TABLE_PARAM];
6691 param_last = ca->rows + 1;
6692 } else {
6693 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6694 ca = &image->tables [MONO_TABLE_PARAM];
6696 found = FALSE;
6697 for (i = param_list; i < param_last; ++i) {
6698 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6699 if (param_pos == param) {
6700 found = TRUE;
6701 break;
6704 if (!found)
6705 return NULL;
6706 idx = i;
6707 idx <<= MONO_CUSTOM_ATTR_BITS;
6708 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6709 return mono_custom_attrs_from_index (image, idx);
6713 * mono_reflection_get_custom_attrs:
6714 * @obj: a reflection object handle
6716 * Return an array with all the custom attributes defined of the
6717 * reflection handle @obj. The objects are fully build.
6719 MonoArray*
6720 mono_reflection_get_custom_attrs (MonoObject *obj)
6722 MonoClass *klass;
6723 MonoArray *result;
6724 MonoCustomAttrInfo *cinfo = NULL;
6726 MONO_ARCH_SAVE_REGS;
6728 klass = obj->vtable->klass;
6729 if (klass == mono_defaults.monotype_class) {
6730 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6731 klass = mono_class_from_mono_type (rtype->type);
6732 cinfo = mono_custom_attrs_from_class (klass);
6733 } else if (strcmp ("Assembly", klass->name) == 0) {
6734 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6735 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6736 } else if (strcmp ("Module", klass->name) == 0) {
6737 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6738 cinfo = mono_custom_attrs_from_module (module->image);
6739 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6740 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6741 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6742 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6743 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6744 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6745 } else if (strcmp ("MonoField", klass->name) == 0) {
6746 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6747 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6748 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6749 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6750 cinfo = mono_custom_attrs_from_method (rmethod->method);
6751 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6752 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6753 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6754 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6755 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6756 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6757 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6758 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6759 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6760 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6761 } else { /* handle other types here... */
6762 g_error ("get custom attrs not yet supported for %s", klass->name);
6765 if (cinfo) {
6766 result = mono_custom_attrs_construct (cinfo);
6767 if (!cinfo->cached)
6768 mono_custom_attrs_free (cinfo);
6769 } else {
6770 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6771 result = mono_array_new (mono_domain_get (), klass, 0);
6774 return result;
6777 static MonoMethodSignature*
6778 parameters_to_signature (MonoArray *parameters) {
6779 MonoMethodSignature *sig;
6780 int count, i;
6782 count = parameters? mono_array_length (parameters): 0;
6784 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6785 sig->param_count = count;
6786 sig->sentinelpos = -1; /* FIXME */
6787 for (i = 0; i < count; ++i) {
6788 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6789 sig->params [i] = pt->type;
6791 return sig;
6794 static MonoMethodSignature*
6795 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6796 MonoMethodSignature *sig;
6798 sig = parameters_to_signature (ctor->parameters);
6799 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6800 sig->ret = &mono_defaults.void_class->byval_arg;
6801 return sig;
6804 static MonoMethodSignature*
6805 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6806 MonoMethodSignature *sig;
6808 sig = parameters_to_signature (method->parameters);
6809 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6810 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6811 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6812 return sig;
6815 static MonoMethodSignature*
6816 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6817 MonoMethodSignature *sig;
6819 sig = parameters_to_signature (method->parameters);
6820 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6821 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6822 sig->generic_param_count = 0;
6823 return sig;
6826 static void
6827 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6829 MonoClass *klass = mono_object_class (prop);
6830 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6831 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6832 *name = mono_string_to_utf8 (pb->name);
6833 *type = pb->type->type;
6834 } else {
6835 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6836 *name = g_strdup (p->property->name);
6837 if (p->property->get)
6838 *type = p->property->get->signature->ret;
6839 else
6840 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6844 static void
6845 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6847 MonoClass *klass = mono_object_class (field);
6848 if (strcmp (klass->name, "FieldBuilder") == 0) {
6849 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6850 *name = mono_string_to_utf8 (fb->name);
6851 *type = fb->type->type;
6852 } else {
6853 MonoReflectionField *f = (MonoReflectionField *)field;
6854 *name = g_strdup (f->field->name);
6855 *type = f->field->type;
6860 * Encode a value in a custom attribute stream of bytes.
6861 * The value to encode is either supplied as an object in argument val
6862 * (valuetypes are boxed), or as a pointer to the data in the
6863 * argument argval.
6864 * @type represents the type of the value
6865 * @buffer is the start of the buffer
6866 * @p the current position in the buffer
6867 * @buflen contains the size of the buffer and is used to return the new buffer size
6868 * if this needs to be realloced.
6869 * @retbuffer and @retp return the start and the position of the buffer
6871 static void
6872 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6874 MonoTypeEnum simple_type;
6876 if ((p-buffer) + 10 >= *buflen) {
6877 char *newbuf;
6878 *buflen *= 2;
6879 newbuf = g_realloc (buffer, *buflen);
6880 p = newbuf + (p-buffer);
6881 buffer = newbuf;
6883 if (!argval)
6884 argval = ((char*)arg + sizeof (MonoObject));
6885 simple_type = type->type;
6886 handle_enum:
6887 switch (simple_type) {
6888 case MONO_TYPE_BOOLEAN:
6889 case MONO_TYPE_U1:
6890 case MONO_TYPE_I1:
6891 *p++ = *argval;
6892 break;
6893 case MONO_TYPE_CHAR:
6894 case MONO_TYPE_U2:
6895 case MONO_TYPE_I2:
6896 swap_with_size (p, argval, 2, 1);
6897 p += 2;
6898 break;
6899 case MONO_TYPE_U4:
6900 case MONO_TYPE_I4:
6901 case MONO_TYPE_R4:
6902 swap_with_size (p, argval, 4, 1);
6903 p += 4;
6904 break;
6905 case MONO_TYPE_U8:
6906 case MONO_TYPE_I8:
6907 case MONO_TYPE_R8:
6908 swap_with_size (p, argval, 8, 1);
6909 p += 8;
6910 break;
6911 case MONO_TYPE_VALUETYPE:
6912 if (type->data.klass->enumtype) {
6913 simple_type = type->data.klass->enum_basetype->type;
6914 goto handle_enum;
6915 } else {
6916 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6918 break;
6919 case MONO_TYPE_STRING: {
6920 char *str;
6921 guint32 slen;
6922 if (!arg) {
6923 *p++ = 0xFF;
6924 break;
6926 str = mono_string_to_utf8 ((MonoString*)arg);
6927 slen = strlen (str);
6928 if ((p-buffer) + 10 + slen >= *buflen) {
6929 char *newbuf;
6930 *buflen *= 2;
6931 *buflen += slen;
6932 newbuf = g_realloc (buffer, *buflen);
6933 p = newbuf + (p-buffer);
6934 buffer = newbuf;
6936 mono_metadata_encode_value (slen, p, &p);
6937 memcpy (p, str, slen);
6938 p += slen;
6939 g_free (str);
6940 break;
6942 case MONO_TYPE_CLASS: {
6943 char *str;
6944 guint32 slen;
6945 MonoClass *k;
6946 if (!arg) {
6947 *p++ = 0xFF;
6948 break;
6950 k = mono_object_class (arg);
6951 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6952 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6953 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6954 handle_type:
6955 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6956 slen = strlen (str);
6957 if ((p-buffer) + 10 + slen >= *buflen) {
6958 char *newbuf;
6959 *buflen *= 2;
6960 *buflen += slen;
6961 newbuf = g_realloc (buffer, *buflen);
6962 p = newbuf + (p-buffer);
6963 buffer = newbuf;
6965 mono_metadata_encode_value (slen, p, &p);
6966 memcpy (p, str, slen);
6967 p += slen;
6968 g_free (str);
6969 break;
6971 case MONO_TYPE_SZARRAY: {
6972 int len, i;
6973 MonoClass *eclass, *arg_eclass;
6975 if (!arg) {
6976 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6977 break;
6979 len = mono_array_length ((MonoArray*)arg);
6980 *p++ = len & 0xff;
6981 *p++ = (len >> 8) & 0xff;
6982 *p++ = (len >> 16) & 0xff;
6983 *p++ = (len >> 24) & 0xff;
6984 *retp = p;
6985 *retbuffer = buffer;
6986 eclass = type->data.klass;
6987 arg_eclass = mono_object_class (arg)->element_class;
6988 if (eclass->valuetype && arg_eclass->valuetype) {
6989 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6990 int elsize = mono_class_array_element_size (eclass);
6991 for (i = 0; i < len; ++i) {
6992 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6993 elptr += elsize;
6995 } else {
6996 for (i = 0; i < len; ++i) {
6997 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7000 break;
7002 /* it may be a boxed value or a Type */
7003 case MONO_TYPE_OBJECT: {
7004 MonoClass *klass = mono_object_class (arg);
7005 char *str;
7006 guint32 slen;
7008 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7009 *p++ = 0x50;
7010 goto handle_type;
7011 } else if (klass->enumtype) {
7012 *p++ = 0x55;
7013 } else if (klass == mono_defaults.string_class) {
7014 simple_type = MONO_TYPE_STRING;
7015 *p++ = 0x0E;
7016 goto handle_enum;
7017 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7018 *p++ = simple_type = klass->byval_arg.type;
7019 goto handle_enum;
7020 } else {
7021 g_error ("unhandled type in custom attr");
7023 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7024 slen = strlen (str);
7025 if ((p-buffer) + 10 + slen >= *buflen) {
7026 char *newbuf;
7027 *buflen *= 2;
7028 *buflen += slen;
7029 newbuf = g_realloc (buffer, *buflen);
7030 p = newbuf + (p-buffer);
7031 buffer = newbuf;
7033 mono_metadata_encode_value (slen, p, &p);
7034 memcpy (p, str, slen);
7035 p += slen;
7036 g_free (str);
7037 simple_type = klass->enum_basetype->type;
7038 goto handle_enum;
7040 default:
7041 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7043 *retp = p;
7044 *retbuffer = buffer;
7048 * mono_reflection_get_custom_attrs_blob:
7049 * @ctor: custom attribute constructor
7050 * @ctorArgs: arguments o the constructor
7051 * @properties:
7052 * @propValues:
7053 * @fields:
7054 * @fieldValues:
7056 * Creates the blob of data that needs to be saved in the metadata and that represents
7057 * the custom attributed described by @ctor, @ctorArgs etc.
7058 * Returns: a Byte array representing the blob of data.
7060 MonoArray*
7061 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7063 MonoArray *result;
7064 MonoMethodSignature *sig;
7065 MonoObject *arg;
7066 char *buffer, *p;
7067 guint32 buflen, i;
7069 MONO_ARCH_SAVE_REGS;
7071 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7072 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7073 } else {
7074 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7076 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7077 buflen = 256;
7078 p = buffer = g_malloc (buflen);
7079 /* write the prolog */
7080 *p++ = 1;
7081 *p++ = 0;
7082 for (i = 0; i < sig->param_count; ++i) {
7083 arg = mono_array_get (ctorArgs, MonoObject*, i);
7084 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7086 i = 0;
7087 if (properties)
7088 i += mono_array_length (properties);
7089 if (fields)
7090 i += mono_array_length (fields);
7091 *p++ = i & 0xff;
7092 *p++ = (i >> 8) & 0xff;
7093 if (properties) {
7094 MonoObject *prop;
7095 for (i = 0; i < mono_array_length (properties); ++i) {
7096 MonoType *ptype;
7097 char *pname;
7098 int len;
7100 prop = mono_array_get (properties, gpointer, i);
7101 get_prop_name_and_type (prop, &pname, &ptype);
7102 *p++ = 0x54; /* PROPERTY signature */
7104 /* Preallocate a large enough buffer */
7105 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7106 char *str = type_get_qualified_name (ptype, NULL);
7107 len = strlen (str);
7108 g_free (str);
7110 else
7111 len = 0;
7112 len += strlen (pname);
7114 if ((p-buffer) + 20 + len >= buflen) {
7115 char *newbuf;
7116 buflen *= 2;
7117 buflen += len;
7118 newbuf = g_realloc (buffer, buflen);
7119 p = newbuf + (p-buffer);
7120 buffer = newbuf;
7123 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7124 char *str = type_get_qualified_name (ptype, NULL);
7125 int slen = strlen (str);
7127 *p++ = 0x55;
7129 * This seems to be optional...
7130 * *p++ = 0x80;
7132 mono_metadata_encode_value (slen, p, &p);
7133 memcpy (p, str, slen);
7134 p += slen;
7135 g_free (str);
7136 } else {
7137 mono_metadata_encode_value (ptype->type, p, &p);
7138 if (ptype->type == MONO_TYPE_SZARRAY)
7139 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7141 len = strlen (pname);
7142 mono_metadata_encode_value (len, p, &p);
7143 memcpy (p, pname, len);
7144 p += len;
7145 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7146 g_free (pname);
7150 if (fields) {
7151 MonoObject *field;
7152 for (i = 0; i < mono_array_length (fields); ++i) {
7153 MonoType *ftype;
7154 char *fname;
7155 int len;
7157 field = mono_array_get (fields, gpointer, i);
7158 get_field_name_and_type (field, &fname, &ftype);
7159 *p++ = 0x53; /* FIELD signature */
7160 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7161 char *str = type_get_qualified_name (ftype, NULL);
7162 int slen = strlen (str);
7163 if ((p-buffer) + 10 + slen >= buflen) {
7164 char *newbuf;
7165 buflen *= 2;
7166 buflen += slen;
7167 newbuf = g_realloc (buffer, buflen);
7168 p = newbuf + (p-buffer);
7169 buffer = newbuf;
7171 *p++ = 0x55;
7173 * This seems to be optional...
7174 * *p++ = 0x80;
7176 mono_metadata_encode_value (slen, p, &p);
7177 memcpy (p, str, slen);
7178 p += slen;
7179 g_free (str);
7180 } else {
7181 mono_metadata_encode_value (ftype->type, p, &p);
7182 if (ftype->type == MONO_TYPE_SZARRAY)
7183 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7185 len = strlen (fname);
7186 mono_metadata_encode_value (len, p, &p);
7187 memcpy (p, fname, len);
7188 p += len;
7189 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7190 g_free (fname);
7194 g_assert (p - buffer <= buflen);
7195 buflen = p - buffer;
7196 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7197 p = mono_array_addr (result, char, 0);
7198 memcpy (p, buffer, buflen);
7199 g_free (buffer);
7200 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7201 g_free (sig);
7202 return result;
7206 * mono_reflection_setup_internal_class:
7207 * @tb: a TypeBuilder object
7209 * Creates a MonoClass that represents the TypeBuilder.
7210 * This is a trick that lets us simplify a lot of reflection code
7211 * (and will allow us to support Build and Run assemblies easier).
7213 void
7214 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7216 MonoClass *klass, *parent;
7218 MONO_ARCH_SAVE_REGS;
7220 if (tb->parent) {
7221 /* check so we can compile corlib correctly */
7222 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7223 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7224 parent = tb->parent->type->data.klass;
7225 } else {
7226 parent = my_mono_class_from_mono_type (tb->parent->type);
7228 } else {
7229 parent = NULL;
7232 /* the type has already being created: it means we just have to change the parent */
7233 if (tb->type.type) {
7234 klass = mono_class_from_mono_type (tb->type.type);
7235 klass->parent = NULL;
7236 /* fool mono_class_setup_parent */
7237 g_free (klass->supertypes);
7238 klass->supertypes = NULL;
7239 mono_class_setup_parent (klass, parent);
7240 mono_class_setup_mono_type (klass);
7241 return;
7244 klass = g_new0 (MonoClass, 1);
7246 klass->image = &tb->module->dynamic_image->image;
7248 klass->inited = 1; /* we lie to the runtime */
7249 klass->name = mono_string_to_utf8 (tb->name);
7250 klass->name_space = mono_string_to_utf8 (tb->nspace);
7251 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7252 klass->flags = tb->attrs;
7254 klass->element_class = klass;
7255 klass->reflection_info = tb; /* need to pin. */
7257 /* Put into cache so mono_class_get () will find it */
7258 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7260 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7261 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7263 if (parent != NULL) {
7264 mono_class_setup_parent (klass, parent);
7265 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7266 const char *old_n = klass->name;
7267 /* trick to get relative numbering right when compiling corlib */
7268 klass->name = "BuildingObject";
7269 mono_class_setup_parent (klass, mono_defaults.object_class);
7270 klass->name = old_n;
7273 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7274 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7275 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7276 klass->instance_size = sizeof (MonoObject);
7277 klass->size_inited = 1;
7278 mono_class_setup_vtable (klass, NULL, 0);
7281 mono_class_setup_mono_type (klass);
7283 mono_class_setup_supertypes (klass);
7286 * FIXME: handle interfaces.
7289 tb->type.type = &klass->byval_arg;
7291 if (tb->nesting_type) {
7292 g_assert (tb->nesting_type->type);
7293 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7296 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7300 * mono_reflection_setup_generic_class:
7301 * @tb: a TypeBuilder object
7303 * Setup the generic class before adding the first generic parameter.
7305 void
7306 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7308 MonoClass *klass;
7310 MONO_ARCH_SAVE_REGS;
7312 klass = my_mono_class_from_mono_type (tb->type.type);
7313 if (tb->generic_container)
7314 return;
7316 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7317 tb->generic_container->klass = klass;
7321 * mono_reflection_create_generic_class:
7322 * @tb: a TypeBuilder object
7324 * Creates the generic class after all generic parameters have been added.
7326 void
7327 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7329 MonoClass *klass;
7330 int count, i;
7332 MONO_ARCH_SAVE_REGS;
7334 klass = my_mono_class_from_mono_type (tb->type.type);
7336 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7338 if (klass->generic_container || (count == 0))
7339 return;
7341 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7343 klass->generic_container = tb->generic_container;
7345 klass->generic_container->type_argc = count;
7346 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7348 for (i = 0; i < count; i++) {
7349 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7350 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7351 g_assert (klass->generic_container->type_params [i].owner);
7356 * mono_reflection_create_internal_class:
7357 * @tb: a TypeBuilder object
7359 * Actually create the MonoClass that is associated with the TypeBuilder.
7361 void
7362 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7364 MonoClass *klass;
7366 MONO_ARCH_SAVE_REGS;
7368 klass = my_mono_class_from_mono_type (tb->type.type);
7370 if (klass->enumtype && klass->enum_basetype == NULL) {
7371 MonoReflectionFieldBuilder *fb;
7372 MonoClass *ec;
7374 g_assert (tb->fields != NULL);
7375 g_assert (mono_array_length (tb->fields) >= 1);
7377 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7379 klass->enum_basetype = fb->type->type;
7380 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7381 if (!klass->element_class)
7382 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7385 * get the element_class from the current corlib.
7387 ec = default_class_from_mono_type (klass->enum_basetype);
7388 klass->instance_size = ec->instance_size;
7389 klass->size_inited = 1;
7391 * this is almost safe to do with enums and it's needed to be able
7392 * to create objects of the enum type (for use in SetConstant).
7394 /* FIXME: Does this mean enums can't have method overrides ? */
7395 mono_class_setup_vtable (klass, NULL, 0);
7399 static MonoMarshalSpec*
7400 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7401 MonoReflectionMarshal *minfo)
7403 MonoMarshalSpec *res;
7405 res = g_new0 (MonoMarshalSpec, 1);
7406 res->native = minfo->type;
7408 switch (minfo->type) {
7409 case MONO_NATIVE_LPARRAY:
7410 res->data.array_data.elem_type = minfo->eltype;
7411 res->data.array_data.param_num = 0; /* Not yet */
7412 res->data.array_data.num_elem = minfo->count;
7413 break;
7415 case MONO_NATIVE_BYVALTSTR:
7416 case MONO_NATIVE_BYVALARRAY:
7417 res->data.array_data.num_elem = minfo->count;
7418 break;
7420 case MONO_NATIVE_CUSTOM:
7421 if (minfo->marshaltyperef)
7422 res->data.custom_data.custom_name =
7423 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7424 if (minfo->mcookie)
7425 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7426 break;
7428 default:
7429 break;
7432 return res;
7435 MonoReflectionMarshal*
7436 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7437 MonoMarshalSpec *spec)
7439 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7440 MonoReflectionMarshal *minfo;
7441 MonoType *mtype;
7443 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7444 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7445 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7446 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7449 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7450 minfo->type = spec->native;
7452 switch (minfo->type) {
7453 case MONO_NATIVE_LPARRAY:
7454 minfo->eltype = spec->data.array_data.elem_type;
7455 minfo->count = spec->data.array_data.num_elem;
7456 break;
7458 case MONO_NATIVE_BYVALTSTR:
7459 case MONO_NATIVE_BYVALARRAY:
7460 minfo->count = spec->data.array_data.num_elem;
7461 break;
7463 case MONO_NATIVE_CUSTOM:
7464 if (spec->data.custom_data.custom_name) {
7465 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7466 if (mtype)
7467 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7469 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7471 if (spec->data.custom_data.cookie)
7472 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7473 break;
7475 default:
7476 break;
7479 return minfo;
7482 static MonoMethod*
7483 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7484 ReflectionMethodBuilder *rmb,
7485 MonoMethodSignature *sig)
7487 MonoMethod *m;
7488 MonoMethodNormal *pm;
7489 MonoMarshalSpec **specs;
7490 MonoReflectionMethodAux *method_aux;
7491 int i;
7493 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7494 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7495 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7496 else if (rmb->refs)
7497 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7498 else
7499 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7501 pm = (MonoMethodNormal*)m;
7503 m->slot = -1;
7504 m->flags = rmb->attrs;
7505 m->iflags = rmb->iattrs;
7506 m->name = mono_string_to_utf8 (rmb->name);
7507 m->klass = klass;
7508 m->signature = sig;
7509 if (rmb->table_idx)
7510 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7512 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7513 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7514 m->string_ctor = 1;
7516 m->signature->pinvoke = 1;
7517 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7518 m->signature->pinvoke = 1;
7520 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7522 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7523 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7525 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7527 if (klass->image->dynamic)
7528 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7530 return m;
7531 } else if (!m->klass->dummy &&
7532 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7533 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7534 MonoMethodHeader *header;
7535 guint32 code_size;
7536 gint32 max_stack, i;
7537 gint32 num_locals = 0;
7538 gint32 num_clauses = 0;
7539 guint8 *code;
7541 if (rmb->ilgen) {
7542 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7543 code_size = rmb->ilgen->code_len;
7544 max_stack = rmb->ilgen->max_stack;
7545 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7546 if (rmb->ilgen->ex_handlers)
7547 num_clauses = method_count_clauses (rmb->ilgen);
7548 } else {
7549 if (rmb->code) {
7550 code = mono_array_addr (rmb->code, guint8, 0);
7551 code_size = mono_array_length (rmb->code);
7552 /* we probably need to run a verifier on the code... */
7553 max_stack = 8;
7555 else {
7556 code = NULL;
7557 code_size = 0;
7558 max_stack = 8;
7562 header = g_malloc0 (sizeof (MonoMethodHeader) +
7563 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7564 header->code_size = code_size;
7565 header->code = g_malloc (code_size);
7566 memcpy ((char*)header->code, code, code_size);
7567 header->max_stack = max_stack;
7568 header->init_locals = rmb->init_locals;
7569 header->num_locals = num_locals;
7571 for (i = 0; i < num_locals; ++i) {
7572 MonoReflectionLocalBuilder *lb =
7573 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7575 header->locals [i] = g_new0 (MonoType, 1);
7576 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7579 header->num_clauses = num_clauses;
7580 if (num_clauses) {
7581 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7582 rmb->ilgen, num_clauses);
7585 pm->header = header;
7588 if (rmb->generic_params) {
7589 int count = mono_array_length (rmb->generic_params);
7590 MonoGenericContainer *container;
7592 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7593 container->type_argc = count;
7594 container->type_params = g_new0 (MonoGenericParam, count);
7596 for (i = 0; i < count; i++) {
7597 MonoReflectionGenericParam *gp =
7598 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7600 container->type_params [i] = *gp->type.type->data.generic_param;
7604 if (rmb->refs) {
7605 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7606 int i;
7608 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7610 for (i = 0; i < rmb->nrefs; ++i)
7611 mw->data = g_list_append (mw->data, rmb->refs [i]);
7614 method_aux = NULL;
7616 /* Parameter info */
7617 if (rmb->pinfo) {
7618 if (!method_aux)
7619 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7620 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7621 for (i = 0; i <= m->signature->param_count; ++i) {
7622 MonoReflectionParamBuilder *pb;
7623 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7624 if (i > 0)
7625 m->signature->params [i - 1]->attrs = pb->attrs;
7627 if (pb->def_value) {
7628 MonoDynamicImage *assembly;
7629 guint32 idx, def_type, len;
7630 char *p;
7631 const char *p2;
7633 if (!method_aux->param_defaults)
7634 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7635 assembly = (MonoDynamicImage*)klass->image;
7636 idx = encode_constant (assembly, pb->def_value, &def_type);
7637 /* Copy the data from the blob since it might get realloc-ed */
7638 p = assembly->blob.data + idx;
7639 len = mono_metadata_decode_blob_size (p, &p2);
7640 len += p2 - p;
7641 method_aux->param_defaults [i] = g_malloc (len);
7642 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7645 if (pb->name)
7646 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7647 if (pb->cattrs) {
7648 if (!method_aux->param_cattr)
7649 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7650 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7656 /* Parameter marshalling */
7657 specs = NULL;
7658 if (rmb->pinfo)
7659 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7660 MonoReflectionParamBuilder *pb;
7661 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7662 if (pb->marshal_info) {
7663 if (specs == NULL)
7664 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7665 specs [pb->position] =
7666 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7670 if (specs != NULL) {
7671 if (!method_aux)
7672 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7673 method_aux->param_marshall = specs;
7676 if (klass->image->dynamic && method_aux)
7677 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7679 return m;
7682 static MonoMethod*
7683 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7685 ReflectionMethodBuilder rmb;
7686 MonoMethodSignature *sig;
7688 sig = ctor_builder_to_signature (mb);
7690 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7692 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7693 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7695 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7696 /* ilgen is no longer needed */
7697 mb->ilgen = NULL;
7700 return mb->mhandle;
7703 static MonoMethod*
7704 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7706 ReflectionMethodBuilder rmb;
7707 MonoMethodSignature *sig;
7709 sig = method_builder_to_signature (mb);
7711 reflection_methodbuilder_from_method_builder (&rmb, mb);
7713 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7714 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7716 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7717 /* ilgen is no longer needed */
7718 mb->ilgen = NULL;
7720 return mb->mhandle;
7723 static MonoClassField*
7724 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7726 MonoClassField *field;
7727 const char *p, *p2;
7728 guint32 len, idx;
7730 if (fb->handle)
7731 return fb->handle;
7733 field = g_new0 (MonoClassField, 1);
7735 field->name = mono_string_to_utf8 (fb->name);
7736 if (fb->attrs) {
7737 /* FIXME: handle type modifiers */
7738 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7739 field->type->attrs = fb->attrs;
7740 } else {
7741 field->type = fb->type->type;
7743 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7744 field->data = mono_array_addr (fb->rva_data, char, 0);
7745 if (fb->offset != -1)
7746 field->offset = fb->offset;
7747 field->parent = klass;
7748 fb->handle = field;
7749 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7751 if (fb->def_value) {
7752 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7753 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7754 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7755 /* Copy the data from the blob since it might get realloc-ed */
7756 p = assembly->blob.data + idx;
7757 len = mono_metadata_decode_blob_size (p, &p2);
7758 len += p2 - p;
7759 field->data = g_malloc (len);
7760 memcpy ((gpointer)field->data, p, len);
7763 return field;
7766 static MonoType*
7767 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7769 MonoClass *klass, *gklass;
7770 MonoReflectionTypeBuilder *tb = NULL;
7771 MonoGenericInst *ginst, *cached;
7772 MonoDomain *domain;
7773 MonoType *geninst;
7774 int icount, i;
7776 klass = mono_class_from_mono_type (type->type);
7777 if (!klass->generic_container && !klass->generic_inst &&
7778 !(klass->nested_in && klass->nested_in->generic_container))
7779 return NULL;
7781 mono_loader_lock ();
7783 domain = mono_object_domain (type);
7785 ginst = g_new0 (MonoGenericInst, 1);
7787 if (!klass->generic_inst) {
7788 ginst->type_argc = type_argc;
7789 ginst->type_argv = types;
7791 for (i = 0; i < ginst->type_argc; ++i) {
7792 if (!ginst->is_open)
7793 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7796 ginst->generic_type = &klass->byval_arg;
7797 } else {
7798 MonoGenericInst *kginst = klass->generic_inst;
7800 ginst->type_argc = kginst->type_argc;
7801 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7803 for (i = 0; i < ginst->type_argc; i++) {
7804 MonoType *t = kginst->type_argv [i];
7806 if (t->type == MONO_TYPE_VAR)
7807 t = types [t->data.generic_param->num];
7809 if (!ginst->is_open)
7810 ginst->is_open = mono_class_is_open_constructed_type (t);
7812 ginst->type_argv [i] = t;
7815 ginst->generic_type = kginst->generic_type;
7818 geninst = g_new0 (MonoType, 1);
7819 geninst->type = MONO_TYPE_GENERICINST;
7821 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7822 if (cached) {
7823 g_free (ginst);
7824 mono_loader_unlock ();
7825 geninst->data.generic_inst = cached;
7826 return geninst;
7829 gklass = mono_class_from_mono_type (ginst->generic_type);
7830 g_assert ((ginst->container = gklass->generic_container) != NULL);
7832 geninst->data.generic_inst = ginst;
7834 ginst->context = g_new0 (MonoGenericContext, 1);
7835 ginst->context->ginst = ginst;
7837 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7838 tb = (MonoReflectionTypeBuilder *) type;
7840 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7841 ginst->is_dynamic = TRUE;
7842 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7843 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7844 MonoReflectionType *rgt = rgi->generic_type;
7846 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7847 tb = (MonoReflectionTypeBuilder *) rgt;
7849 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7850 ginst->is_dynamic = TRUE;
7851 } else {
7852 icount = klass->interface_count;
7855 ginst->ifaces = g_new0 (MonoType *, icount);
7856 ginst->count_ifaces = icount;
7858 for (i = 0; i < icount; i++) {
7859 MonoReflectionType *itype;
7861 if (tb)
7862 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7863 else
7864 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7865 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7866 if (!ginst->ifaces [i])
7867 ginst->ifaces [i] = itype->type;
7870 mono_class_create_generic (ginst);
7872 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7874 mono_loader_unlock ();
7876 return geninst;
7879 MonoType*
7880 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7882 MonoClass *klass, *pklass = NULL;
7883 MonoReflectionType *parent = NULL;
7884 MonoType *geninst;
7885 MonoReflectionTypeBuilder *tb = NULL;
7886 MonoGenericInst *ginst;
7887 MonoDomain *domain;
7889 domain = mono_object_domain (type);
7890 klass = mono_class_from_mono_type (type->type);
7892 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7893 tb = (MonoReflectionTypeBuilder *) type;
7895 if (tb->parent) {
7896 parent = tb->parent;
7897 pklass = mono_class_from_mono_type (parent->type);
7899 } else {
7900 pklass = klass->parent;
7901 if (pklass)
7902 parent = mono_type_get_object (domain, &pklass->byval_arg);
7903 else if (klass->generic_inst && klass->generic_inst->parent) {
7904 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7905 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7909 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7910 if (!geninst)
7911 return NULL;
7913 ginst = geninst->data.generic_inst;
7915 if (pklass && pklass->generic_inst)
7916 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7918 return geninst;
7921 MonoReflectionMethod*
7922 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7924 MonoMethod *method, *inflated;
7925 MonoReflectionMethodBuilder *mb = NULL;
7926 MonoGenericMethod *gmethod;
7927 MonoGenericContext *context;
7928 int count, i;
7930 MONO_ARCH_SAVE_REGS;
7931 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7932 MonoReflectionTypeBuilder *tb;
7933 MonoClass *klass;
7935 mb = (MonoReflectionMethodBuilder *) rmethod;
7936 tb = (MonoReflectionTypeBuilder *) mb->type;
7937 klass = mono_class_from_mono_type (tb->type.type);
7939 method = methodbuilder_to_mono_method (klass, mb);
7940 } else {
7941 method = rmethod->method;
7944 count = method->signature->generic_param_count;
7945 if (count != mono_array_length (types))
7946 return NULL;
7948 gmethod = g_new0 (MonoGenericMethod, 1);
7949 gmethod->mtype_argc = count;
7950 gmethod->mtype_argv = g_new0 (MonoType *, count);
7951 for (i = 0; i < count; i++) {
7952 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7953 gmethod->mtype_argv [i] = garg->type;
7956 gmethod->reflection_info = rmethod;
7958 context = g_new0 (MonoGenericContext, 1);
7959 context->ginst = method->klass->generic_inst;
7960 context->gmethod = gmethod;
7962 inflated = mono_class_inflate_generic_method (method, context, NULL);
7964 return mono_method_get_object (
7965 mono_object_domain (rmethod), inflated, NULL);
7968 static MonoMethod *
7969 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7971 MonoGenericMethod *gmethod;
7972 MonoGenericInst *ginst;
7973 MonoGenericContext *context;
7974 int i;
7976 ginst = type->type.type->data.generic_inst;
7978 gmethod = g_new0 (MonoGenericMethod, 1);
7979 gmethod->reflection_info = obj;
7981 gmethod->mtype_argc = method->signature->generic_param_count;
7982 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7984 for (i = 0; i < gmethod->mtype_argc; i++) {
7985 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7986 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7988 g_assert (gparam->pklass);
7989 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7992 context = g_new0 (MonoGenericContext, 1);
7993 context->ginst = ginst;
7994 context->gmethod = gmethod;
7996 return mono_class_inflate_generic_method (method, context, ginst->klass);
7999 static MonoMethod *
8000 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8002 MonoMethod *method;
8003 MonoClass *klass;
8005 klass = mono_class_from_mono_type (type->type.type);
8007 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8008 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8009 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8010 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8011 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8012 method = ((MonoReflectionMethod *) obj)->method;
8013 else {
8014 method = NULL; /* prevent compiler warning */
8015 g_assert_not_reached ();
8018 return inflate_mono_method (type, method, obj);
8021 void
8022 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8023 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8025 MonoGenericInst *ginst;
8026 MonoDynamicGenericInst *dginst;
8027 MonoClass *klass, *gklass, *pklass;
8028 int i;
8030 MONO_ARCH_SAVE_REGS;
8032 klass = mono_class_from_mono_type (type->type.type);
8033 ginst = type->type.type->data.generic_inst;
8035 if (ginst->initialized)
8036 return;
8038 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8040 gklass = mono_class_from_mono_type (ginst->generic_type);
8041 mono_class_init (gklass);
8043 if (ginst->parent)
8044 pklass = mono_class_from_mono_type (ginst->parent);
8045 else
8046 pklass = gklass->parent;
8048 mono_class_setup_parent (klass, pklass);
8050 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8051 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8052 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8053 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8054 dginst->count_events = events ? mono_array_length (events) : 0;
8056 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8057 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8058 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8059 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8060 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8062 for (i = 0; i < dginst->count_methods; i++) {
8063 MonoObject *obj = mono_array_get (methods, gpointer, i);
8065 dginst->methods [i] = inflate_method (type, obj);
8068 for (i = 0; i < dginst->count_ctors; i++) {
8069 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8071 dginst->ctors [i] = inflate_method (type, obj);
8074 for (i = 0; i < dginst->count_fields; i++) {
8075 MonoObject *obj = mono_array_get (fields, gpointer, i);
8076 MonoClassField *field;
8077 MonoInflatedField *ifield;
8079 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8080 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8081 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8082 field = ((MonoReflectionField *) obj)->field;
8083 else {
8084 field = NULL; /* prevent compiler warning */
8085 g_assert_not_reached ();
8088 ifield = g_new0 (MonoInflatedField, 1);
8089 ifield->generic_type = field->type;
8090 ifield->reflection_info = obj;
8092 dginst->fields [i] = *field;
8093 dginst->fields [i].generic_info = ifield;
8094 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8097 for (i = 0; i < dginst->count_properties; i++) {
8098 MonoObject *obj = mono_array_get (properties, gpointer, i);
8099 MonoProperty *property = &dginst->properties [i];
8101 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8102 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8104 property->parent = klass;
8105 property->attrs = pb->attrs;
8106 property->name = mono_string_to_utf8 (pb->name);
8107 if (pb->get_method)
8108 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8109 if (pb->set_method)
8110 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8111 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8112 *property = *((MonoReflectionProperty *) obj)->property;
8114 if (property->get)
8115 property->get = inflate_mono_method (type, property->get, NULL);
8116 if (property->set)
8117 property->set = inflate_mono_method (type, property->set, NULL);
8118 } else
8119 g_assert_not_reached ();
8122 for (i = 0; i < dginst->count_events; i++) {
8123 MonoObject *obj = mono_array_get (events, gpointer, i);
8124 MonoEvent *event = &dginst->events [i];
8126 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8127 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8129 event->parent = klass;
8130 event->attrs = eb->attrs;
8131 event->name = mono_string_to_utf8 (eb->name);
8132 if (eb->add_method)
8133 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8134 if (eb->remove_method)
8135 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8136 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8137 *event = *((MonoReflectionEvent *) obj)->event;
8139 if (event->add)
8140 event->add = inflate_mono_method (type, event->add, NULL);
8141 if (event->remove)
8142 event->remove = inflate_mono_method (type, event->remove, NULL);
8143 } else
8144 g_assert_not_reached ();
8147 ginst->initialized = TRUE;
8150 static void
8151 ensure_runtime_vtable (MonoClass *klass)
8153 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8154 int i, num, j, onum;
8155 MonoMethod **overrides;
8157 if (!tb || klass->wastypebuilder)
8158 return;
8159 if (klass->parent)
8160 ensure_runtime_vtable (klass->parent);
8162 num = tb->ctors? mono_array_length (tb->ctors): 0;
8163 num += tb->num_methods;
8164 klass->method.count = num;
8165 klass->methods = g_new (MonoMethod*, num);
8166 num = tb->ctors? mono_array_length (tb->ctors): 0;
8167 for (i = 0; i < num; ++i)
8168 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8169 num = tb->num_methods;
8170 j = i;
8171 for (i = 0; i < num; ++i)
8172 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8174 if (tb->interfaces) {
8175 klass->interface_count = mono_array_length (tb->interfaces);
8176 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8177 for (i = 0; i < klass->interface_count; ++i) {
8178 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8179 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8183 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8184 for (i = 0; i < klass->method.count; ++i)
8185 klass->methods [i]->slot = i;
8187 /* Overrides */
8188 onum = 0;
8189 if (tb->methods) {
8190 for (i = 0; i < tb->num_methods; ++i) {
8191 MonoReflectionMethodBuilder *mb =
8192 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8193 if (mb->override_method)
8194 onum ++;
8198 overrides = g_new0 (MonoMethod*, onum * 2);
8200 if (tb->methods) {
8201 onum = 0;
8202 for (i = 0; i < tb->num_methods; ++i) {
8203 MonoReflectionMethodBuilder *mb =
8204 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8205 if (mb->override_method) {
8206 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8207 overrides [onum * 2] =
8208 mb->override_method->method;
8209 overrides [onum * 2 + 1] =
8210 mb->mhandle;
8212 g_assert (mb->mhandle);
8214 onum ++;
8219 mono_class_setup_vtable (klass, overrides, onum);
8220 g_free (overrides);
8223 static void
8224 typebuilder_setup_fields (MonoClass *klass)
8226 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8227 MonoReflectionFieldBuilder *fb;
8228 MonoClassField *field;
8229 const char *p, *p2;
8230 int i;
8231 guint32 len, idx;
8233 klass->field.count = tb->num_fields;
8234 klass->field.first = 0;
8235 klass->field.last = klass->field.count;
8237 if (!klass->field.count)
8238 return;
8240 klass->fields = g_new0 (MonoClassField, klass->field.count);
8242 for (i = 0; i < klass->field.count; ++i) {
8243 fb = mono_array_get (tb->fields, gpointer, i);
8244 field = &klass->fields [i];
8245 field->name = mono_string_to_utf8 (fb->name);
8246 if (fb->attrs) {
8247 /* FIXME: handle type modifiers */
8248 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8249 field->type->attrs = fb->attrs;
8250 } else {
8251 field->type = fb->type->type;
8253 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8254 field->data = mono_array_addr (fb->rva_data, char, 0);
8255 if (fb->offset != -1)
8256 field->offset = fb->offset;
8257 field->parent = klass;
8258 fb->handle = field;
8259 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8261 if (fb->def_value) {
8262 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8263 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8264 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8265 /* Copy the data from the blob since it might get realloc-ed */
8266 p = assembly->blob.data + idx;
8267 len = mono_metadata_decode_blob_size (p, &p2);
8268 len += p2 - p;
8269 field->data = g_malloc (len);
8270 memcpy ((gpointer)field->data, p, len);
8273 mono_class_layout_fields (klass);
8276 static void
8277 typebuilder_setup_properties (MonoClass *klass)
8279 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8280 MonoReflectionPropertyBuilder *pb;
8281 int i;
8283 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8284 klass->property.first = 0;
8285 klass->property.last = klass->property.count;
8287 klass->properties = g_new0 (MonoProperty, klass->property.count);
8288 for (i = 0; i < klass->property.count; ++i) {
8289 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8290 klass->properties [i].parent = klass;
8291 klass->properties [i].attrs = pb->attrs;
8292 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8293 if (pb->get_method)
8294 klass->properties [i].get = pb->get_method->mhandle;
8295 if (pb->set_method)
8296 klass->properties [i].set = pb->set_method->mhandle;
8300 MonoReflectionEvent *
8301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8303 MonoEvent *event = g_new0 (MonoEvent, 1);
8304 MonoClass *klass;
8305 int j;
8307 klass = my_mono_class_from_mono_type (tb->type.type);
8309 event->parent = klass;
8310 event->attrs = eb->attrs;
8311 event->name = mono_string_to_utf8 (eb->name);
8312 if (eb->add_method)
8313 event->add = eb->add_method->mhandle;
8314 if (eb->remove_method)
8315 event->remove = eb->remove_method->mhandle;
8316 if (eb->raise_method)
8317 event->raise = eb->raise_method->mhandle;
8319 if (eb->other_methods) {
8320 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8321 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8322 MonoReflectionMethodBuilder *mb =
8323 mono_array_get (eb->other_methods,
8324 MonoReflectionMethodBuilder*, j);
8325 event->other [j] = mb->mhandle;
8329 return mono_event_get_object (mono_object_domain (tb), klass, event);
8332 static void
8333 typebuilder_setup_events (MonoClass *klass)
8335 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8336 MonoReflectionEventBuilder *eb;
8337 int i, j;
8339 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8340 klass->event.first = 0;
8341 klass->event.last = klass->event.count;
8343 klass->events = g_new0 (MonoEvent, klass->event.count);
8344 for (i = 0; i < klass->event.count; ++i) {
8345 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8346 klass->events [i].parent = klass;
8347 klass->events [i].attrs = eb->attrs;
8348 klass->events [i].name = mono_string_to_utf8 (eb->name);
8349 if (eb->add_method)
8350 klass->events [i].add = eb->add_method->mhandle;
8351 if (eb->remove_method)
8352 klass->events [i].remove = eb->remove_method->mhandle;
8353 if (eb->raise_method)
8354 klass->events [i].raise = eb->raise_method->mhandle;
8356 if (eb->other_methods) {
8357 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8358 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8359 MonoReflectionMethodBuilder *mb =
8360 mono_array_get (eb->other_methods,
8361 MonoReflectionMethodBuilder*, j);
8362 klass->events [i].other [j] = mb->mhandle;
8368 MonoReflectionType*
8369 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8371 MonoClass *klass;
8372 MonoReflectionType* res;
8373 int i;
8375 MONO_ARCH_SAVE_REGS;
8377 klass = my_mono_class_from_mono_type (tb->type.type);
8379 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8382 * Fields to set in klass:
8383 * the various flags: delegate/unicode/contextbound etc.
8385 klass->flags = tb->attrs;
8387 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8388 /* No need to fully construct the type */
8389 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8391 /* enums are done right away */
8392 if (!klass->enumtype)
8393 ensure_runtime_vtable (klass);
8395 if (tb->subtypes) {
8396 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8397 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8398 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8402 /* fields and object layout */
8403 if (klass->parent) {
8404 if (!klass->parent->size_inited)
8405 mono_class_init (klass->parent);
8406 klass->instance_size += klass->parent->instance_size;
8407 klass->class_size += klass->parent->class_size;
8408 klass->min_align = klass->parent->min_align;
8409 } else {
8410 klass->instance_size = sizeof (MonoObject);
8411 klass->min_align = 1;
8414 /* FIXME: handle packing_size and instance_size */
8415 typebuilder_setup_fields (klass);
8417 typebuilder_setup_properties (klass);
8419 typebuilder_setup_events (klass);
8421 klass->wastypebuilder = TRUE;
8423 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8424 g_assert (res != (MonoReflectionType*)tb);
8425 return res;
8428 void
8429 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8431 MonoGenericParam *param;
8432 MonoImage *image;
8434 MONO_ARCH_SAVE_REGS;
8436 param = g_new0 (MonoGenericParam, 1);
8438 if (gparam->mbuilder) {
8439 if (!gparam->mbuilder->generic_container)
8440 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8441 param->owner = gparam->mbuilder->generic_container;
8442 } else if (gparam->tbuilder) {
8443 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8444 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8446 while (nesting) {
8447 int count;
8449 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8450 if (gparam->index >= count)
8451 break;
8453 container = nesting->generic_container;
8454 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8457 g_assert (container);
8458 param->owner = container;
8461 param->method = NULL;
8462 param->name = mono_string_to_utf8 (gparam->name);
8463 param->num = gparam->index;
8465 image = &gparam->tbuilder->module->dynamic_image->image;
8466 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8468 param->pklass->reflection_info = gparam;
8470 gparam->type.type = g_new0 (MonoType, 1);
8471 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8472 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8473 gparam->type.type->data.generic_param = param;
8476 MonoArray *
8477 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8479 MonoDynamicImage *assembly = sig->module->dynamic_image;
8480 guint32 na = mono_array_length (sig->arguments);
8481 guint32 buflen, i;
8482 MonoArray *result;
8483 char *buf, *p;
8485 MONO_ARCH_SAVE_REGS;
8487 p = buf = g_malloc (10 + na * 10);
8489 mono_metadata_encode_value (0x07, p, &p);
8490 mono_metadata_encode_value (na, p, &p);
8491 for (i = 0; i < na; ++i) {
8492 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8493 encode_reflection_type (assembly, type, p, &p);
8496 buflen = p - buf;
8497 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8498 p = mono_array_addr (result, char, 0);
8499 memcpy (p, buf, buflen);
8500 g_free (buf);
8502 return result;
8505 MonoArray *
8506 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8508 MonoDynamicImage *assembly = sig->module->dynamic_image;
8509 guint32 na = mono_array_length (sig->arguments);
8510 guint32 buflen, i;
8511 MonoArray *result;
8512 char *buf, *p;
8514 MONO_ARCH_SAVE_REGS;
8516 p = buf = g_malloc (10 + na * 10);
8518 mono_metadata_encode_value (0x06, p, &p);
8519 for (i = 0; i < na; ++i) {
8520 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8521 encode_reflection_type (assembly, type, p, &p);
8524 buflen = p - buf;
8525 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8526 p = mono_array_addr (result, char, 0);
8527 memcpy (p, buf, buflen);
8528 g_free (buf);
8530 return result;
8533 void
8534 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8536 ReflectionMethodBuilder rmb;
8537 MonoMethodSignature *sig;
8538 int i;
8540 sig = dynamic_method_to_signature (mb);
8542 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8545 * Resolve references.
8547 rmb.nrefs = mb->nrefs;
8548 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8549 for (i = 0; i < mb->nrefs; ++i) {
8550 gpointer ref = resolve_object (mb->module->image,
8551 mono_array_get (mb->refs, MonoObject*, i));
8552 if (!ref) {
8553 g_free (rmb.refs);
8554 mono_raise_exception (mono_get_exception_type_load (NULL));
8555 return;
8557 rmb.refs [i] = ref;
8560 /* FIXME: class */
8561 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8563 g_free (rmb.refs);
8565 /* ilgen is no longer needed */
8566 mb->ilgen = NULL;
8570 * mono_reflection_lookup_dynamic_token:
8572 * Finish the Builder object pointed to by TOKEN and return the corresponding
8573 * runtime structure.
8575 gpointer
8576 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8578 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8579 MonoObject *obj;
8581 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8582 g_assert (obj);
8584 return resolve_object (image, obj);
8587 static gpointer
8588 resolve_object (MonoImage *image, MonoObject *obj)
8590 gpointer result = NULL;
8592 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8593 result = mono_string_intern ((MonoString*)obj);
8594 g_assert (result);
8595 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8596 MonoReflectionType *tb = (MonoReflectionType*)obj;
8597 result = mono_class_from_mono_type (tb->type);
8598 g_assert (result);
8599 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8600 result = ((MonoReflectionMethod*)obj)->method;
8601 g_assert (result);
8602 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8603 result = ((MonoReflectionMethod*)obj)->method;
8604 g_assert (result);
8605 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8606 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8607 result = mb->mhandle;
8608 if (!result) {
8609 /* Type is not yet created */
8610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8612 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8615 * Hopefully this has been filled in by calling CreateType() on the
8616 * TypeBuilder.
8619 * TODO: This won't work if the application finishes another
8620 * TypeBuilder instance instead of this one.
8622 result = mb->mhandle;
8624 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8625 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8627 result = cb->mhandle;
8628 if (!result) {
8629 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8631 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8632 result = cb->mhandle;
8634 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8635 result = ((MonoReflectionField*)obj)->field;
8636 g_assert (result);
8637 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8638 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8639 result = fb->handle;
8641 if (!result) {
8642 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8644 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8645 result = fb->handle;
8647 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8649 MonoClass *klass;
8651 klass = tb->type.type->data.klass;
8652 if (klass->wastypebuilder) {
8653 /* Already created */
8654 result = klass;
8656 else {
8657 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8658 result = tb->type.type->data.klass;
8659 g_assert (result);
8661 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8662 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8663 MonoMethodSignature *sig;
8664 int nargs, i;
8666 if (helper->arguments)
8667 nargs = mono_array_length (helper->arguments);
8668 else
8669 nargs = 0;
8671 sig = mono_metadata_signature_alloc (image, nargs);
8672 sig->explicit_this = helper->call_conv & 64;
8673 sig->hasthis = helper->call_conv & 32;
8675 if (helper->call_conv == 0) /* unmanaged */
8676 sig->call_convention = helper->unmanaged_call_conv - 1;
8677 else
8678 if (helper->call_conv & 0x02)
8679 sig->call_convention = MONO_CALL_VARARG;
8680 else
8681 sig->call_convention = MONO_CALL_DEFAULT;
8683 sig->param_count = nargs;
8684 /* TODO: Copy type ? */
8685 sig->ret = helper->return_type->type;
8686 for (i = 0; i < nargs; ++i) {
8687 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8688 sig->params [i] = rt->type;
8691 result = sig;
8692 } else {
8693 g_print (obj->vtable->klass->name);
8694 g_assert_not_reached ();
8696 return result;