2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
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/tokentype.h"
16 #include "mono/metadata/domain-internals.h"
17 #include "mono/metadata/opcodes.h"
18 #include "mono/metadata/assembly.h"
19 #include <mono/metadata/exception.h>
28 #include "rawbuffer.h"
29 #include "mono-endian.h"
31 #include <mono/os/gc_wrapper.h>
33 #define TEXT_OFFSET 512
34 #define CLI_H_SIZE 136
35 #define FILE_ALIGN 512
36 #define VIRT_ALIGN 8192
37 #define START_TEXT_RVA 0x00002000
40 MonoReflectionILGen *ilgen;
41 MonoReflectionType *rtype;
42 MonoArray *parameters;
43 MonoArray *generic_params;
49 guint32 *table_idx; /* note: it's a pointer */
53 MonoBoolean init_locals;
54 MonoArray *return_modreq;
55 MonoArray *return_modopt;
56 MonoArray *param_modreq;
57 MonoArray *param_modopt;
58 MonoArray *permissions;
62 } ReflectionMethodBuilder;
64 const unsigned char table_sizes [64] = {
74 MONO_INTERFACEIMPL_SIZE,
75 MONO_MEMBERREF_SIZE, /* 0x0A */
77 MONO_CUSTOM_ATTR_SIZE,
78 MONO_FIELD_MARSHAL_SIZE,
79 MONO_DECL_SECURITY_SIZE,
80 MONO_CLASS_LAYOUT_SIZE,
81 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
82 MONO_STAND_ALONE_SIGNATURE_SIZE,
86 MONO_PROPERTY_MAP_SIZE,
89 MONO_METHOD_SEMA_SIZE,
91 MONO_MODULEREF_SIZE, /* 0x1A */
97 MONO_ASSEMBLY_SIZE, /* 0x20 */
98 MONO_ASSEMBLY_PROCESSOR_SIZE,
100 MONO_ASSEMBLYREF_SIZE,
101 MONO_ASSEMBLYREFPROC_SIZE,
102 MONO_ASSEMBLYREFOS_SIZE,
106 MONO_NESTED_CLASS_SIZE,
108 MONO_GENERICPARAM_SIZE, /* 0x2A */
109 MONO_METHODSPEC_SIZE,
110 MONO_GENPARCONSTRAINT_SIZE,
116 * These macros can be used to allocate long living atomic data so it won't be
117 * tracked by the garbage collector. We use libgc because it's apparently faster
121 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
122 #define FREE_ATOMIC(ptr)
123 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
125 #define ALLOC_ATOMIC(size) g_malloc (size)
126 #define FREE_ATOMIC(ptr) g_free (ptr)
127 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
130 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
131 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
132 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
133 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
134 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
135 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
136 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
137 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
138 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
139 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
140 static void ensure_runtime_vtable (MonoClass *klass);
141 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
142 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
143 static guint32 type_get_signature_size (MonoType *type);
147 alloc_table (MonoDynamicTable *table, guint nrows)
150 g_assert (table->columns);
151 if (nrows + 1 >= table->alloc_rows) {
152 while (nrows + 1 >= table->alloc_rows)
153 if (table->alloc_rows == 0)
154 table->alloc_rows = 16;
156 table->alloc_rows *= 2;
159 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
161 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
166 make_room_in_stream (MonoDynamicStream *stream, int size)
168 while (stream->alloc_size <= size) {
169 if (stream->alloc_size < 4096)
170 stream->alloc_size = 4096;
172 stream->alloc_size *= 2;
175 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
177 stream->data = ALLOC_ATOMIC (stream->alloc_size);
181 string_heap_insert (MonoDynamicStream *sh, const char *str)
185 gpointer oldkey, oldval;
187 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
188 return GPOINTER_TO_UINT (oldval);
190 len = strlen (str) + 1;
192 if (idx + len > sh->alloc_size)
193 make_room_in_stream (sh, idx + len);
196 * We strdup the string even if we already copy them in sh->data
197 * so that the string pointers in the hash remain valid even if
198 * we need to realloc sh->data. We may want to avoid that later.
200 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
201 memcpy (sh->data + idx, str, len);
207 string_heap_init (MonoDynamicStream *sh)
210 sh->alloc_size = 4096;
211 sh->data = ALLOC_ATOMIC (4096);
212 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
213 string_heap_insert (sh, "");
216 #if 0 /* never used */
218 string_heap_free (MonoDynamicStream *sh)
220 FREE_ATOMIC (sh->data);
221 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
222 g_hash_table_destroy (sh->hash);
227 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
230 if (stream->alloc_size < stream->index + len)
231 make_room_in_stream (stream, stream->index + len);
232 memcpy (stream->data + stream->index, data, len);
234 stream->index += len;
236 * align index? Not without adding an additional param that controls it since
237 * we may store a blob value in pieces.
243 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
246 if (stream->alloc_size < stream->index + len)
247 make_room_in_stream (stream, stream->index + len);
248 memset (stream->data + stream->index, 0, len);
250 stream->index += len;
255 stream_data_align (MonoDynamicStream *stream)
258 guint32 count = stream->index % 4;
260 /* we assume the stream data will be aligned */
262 mono_image_add_stream_data (stream, buf, 4 - count);
266 mono_blob_entry_hash (const char* str)
270 len = mono_metadata_decode_blob_size (str, &str);
274 for (str += 1; str < end; str++)
275 h = (h << 5) - h + *str;
283 mono_blob_entry_equal (const char *str1, const char *str2) {
287 len = mono_metadata_decode_blob_size (str1, &end1);
288 len2 = mono_metadata_decode_blob_size (str2, &end2);
291 return memcmp (end1, end2, len) == 0;
295 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
299 gpointer oldkey, oldval;
301 copy = ALLOC_ATOMIC (s1+s2);
302 memcpy (copy, b1, s1);
303 memcpy (copy + s1, b2, s2);
304 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
306 idx = GPOINTER_TO_UINT (oldval);
308 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
309 mono_image_add_stream_data (&assembly->blob, b2, s2);
310 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
316 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
317 * dest may be misaligned.
320 swap_with_size (char *dest, const char* val, int len, int nelem) {
321 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
324 for (elem = 0; elem < nelem; ++elem) {
350 g_assert_not_reached ();
356 memcpy (dest, val, len * nelem);
361 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
365 guint32 idx = 0, len;
367 len = str->length * 2;
368 mono_metadata_encode_value (len, b, &b);
369 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
371 char *swapped = g_malloc (2 * mono_string_length (str));
372 const char *p = (const char*)mono_string_chars (str);
374 swap_with_size (swapped, p, 2, mono_string_length (str));
375 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
379 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
384 /* modified version needed to handle building corlib */
386 my_mono_class_from_mono_type (MonoType *type) {
387 switch (type->type) {
388 case MONO_TYPE_ARRAY:
390 case MONO_TYPE_SZARRAY:
391 case MONO_TYPE_GENERICINST:
392 return mono_class_from_mono_type (type);
395 g_assert (type->data.generic_param->pklass);
396 return type->data.generic_param->pklass;
398 /* should be always valid when we reach this case... */
399 return type->data.klass;
404 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
409 g_assert_not_reached ();
413 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
414 encode_type (assembly, ginst->generic_type, p, &p);
415 mono_metadata_encode_value (ginst->type_argc, p, &p);
416 for (i = 0; i < ginst->type_argc; ++i)
417 encode_type (assembly, ginst->type_argv [i], p, &p);
423 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
426 g_assert_not_reached ();
431 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
435 case MONO_TYPE_BOOLEAN:
449 case MONO_TYPE_STRING:
450 case MONO_TYPE_OBJECT:
451 case MONO_TYPE_TYPEDBYREF:
452 mono_metadata_encode_value (type->type, p, &p);
455 mono_metadata_encode_value (type->type, p, &p);
456 encode_type (assembly, type->data.type, p, &p);
458 case MONO_TYPE_SZARRAY:
459 mono_metadata_encode_value (type->type, p, &p);
460 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
463 case MONO_TYPE_VALUETYPE:
464 case MONO_TYPE_CLASS: {
465 MonoClass *k = mono_class_from_mono_type (type);
466 mono_metadata_encode_value (type->type, p, &p);
468 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
469 * otherwise two typerefs could point to the same type, leading to
470 * verification errors.
472 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
476 case MONO_TYPE_ARRAY:
477 mono_metadata_encode_value (type->type, p, &p);
478 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
479 mono_metadata_encode_value (type->data.array->rank, p, &p);
480 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
481 mono_metadata_encode_value (0, p, &p);
483 case MONO_TYPE_GENERICINST:
484 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
488 mono_metadata_encode_value (type->type, p, &p);
489 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
493 g_error ("need to encode type %x", type->type);
499 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
502 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
506 encode_type (assembly, type->type, p, endbuf);
510 g_assert_not_reached ();
515 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
520 for (i = 0; i < mono_array_length (modreq); ++i) {
521 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
522 *p = MONO_TYPE_CMOD_REQD;
524 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
528 for (i = 0; i < mono_array_length (modopt); ++i) {
529 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
530 *p = MONO_TYPE_CMOD_OPT;
532 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
539 generic_inst_get_signature_size (MonoGenericInst *ginst)
545 g_assert_not_reached ();
548 size += 1 + type_get_signature_size (ginst->generic_type);
550 for (i = 0; i < ginst->type_argc; ++i)
551 size += type_get_signature_size (ginst->type_argv [i]);
557 type_get_signature_size (MonoType *type)
562 g_assert_not_reached ();
570 case MONO_TYPE_BOOLEAN:
584 case MONO_TYPE_STRING:
585 case MONO_TYPE_OBJECT:
586 case MONO_TYPE_TYPEDBYREF:
589 return size + 1 + type_get_signature_size (type->data.type);
590 case MONO_TYPE_SZARRAY:
591 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
593 case MONO_TYPE_VALUETYPE:
594 case MONO_TYPE_CLASS:
597 case MONO_TYPE_ARRAY:
598 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
599 case MONO_TYPE_GENERICINST:
600 return size + generic_inst_get_signature_size (type->data.generic_inst);
606 g_error ("need to encode type %x", type->type);
612 method_get_signature_size (MonoMethodSignature *sig)
617 size = type_get_signature_size (sig->ret);
618 for (i = 0; i < sig->param_count; i++)
619 size += type_get_signature_size (sig->params [i]);
621 if (sig->generic_param_count)
623 if (sig->sentinelpos >= 0)
630 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
635 guint32 nparams = sig->param_count;
636 guint32 size = 11 + method_get_signature_size (sig);
644 p = buf = g_malloc (size);
646 * FIXME: vararg, explicit_this, differenc call_conv values...
648 *p = sig->call_convention;
650 *p |= 0x20; /* hasthis */
651 if (sig->generic_param_count)
652 *p |= 0x10; /* generic */
654 if (sig->generic_param_count)
655 mono_metadata_encode_value (sig->generic_param_count, p, &p);
656 mono_metadata_encode_value (nparams, p, &p);
657 encode_type (assembly, sig->ret, p, &p);
658 for (i = 0; i < nparams; ++i) {
659 if (i == sig->sentinelpos)
660 *p++ = MONO_TYPE_SENTINEL;
661 encode_type (assembly, sig->params [i], p, &p);
664 g_assert (p - buf < size);
665 mono_metadata_encode_value (p-buf, b, &b);
666 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
672 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
675 * FIXME: reuse code from method_encode_signature().
680 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
681 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
682 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
683 guint32 size = 21 + nparams * 20 + notypes * 20;
688 p = buf = g_malloc (size);
689 /* LAMESPEC: all the call conv spec is foobared */
690 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
691 if (mb->call_conv & 2)
692 *p |= 0x5; /* vararg */
693 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
694 *p |= 0x20; /* hasthis */
696 *p |= 0x10; /* generic */
699 mono_metadata_encode_value (ngparams, p, &p);
700 mono_metadata_encode_value (nparams + notypes, p, &p);
701 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
702 encode_reflection_type (assembly, mb->rtype, p, &p);
703 for (i = 0; i < nparams; ++i) {
704 MonoArray *modreq = NULL;
705 MonoArray *modopt = NULL;
706 MonoReflectionType *pt;
708 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
709 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
710 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
711 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
712 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
713 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
714 encode_reflection_type (assembly, pt, p, &p);
717 *p++ = MONO_TYPE_SENTINEL;
718 for (i = 0; i < notypes; ++i) {
719 MonoReflectionType *pt;
721 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
722 encode_reflection_type (assembly, pt, p, &p);
726 g_assert (p - buf < size);
727 mono_metadata_encode_value (p-buf, b, &b);
728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
734 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
736 MonoDynamicTable *table;
739 guint32 idx, sig_idx, size;
740 guint nl = mono_array_length (ilgen->locals);
747 p = buf = g_malloc (size);
748 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
749 idx = table->next_idx ++;
751 alloc_table (table, table->rows);
752 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
754 mono_metadata_encode_value (0x07, p, &p);
755 mono_metadata_encode_value (nl, p, &p);
756 for (i = 0; i < nl; ++i) {
757 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
760 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
762 encode_reflection_type (assembly, lb->type, p, &p);
764 g_assert (p - buf < size);
765 mono_metadata_encode_value (p-buf, b, &b);
766 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
769 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
775 method_count_clauses (MonoReflectionILGen *ilgen)
777 guint32 num_clauses = 0;
780 MonoILExceptionInfo *ex_info;
781 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
782 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
783 if (ex_info->handlers)
784 num_clauses += mono_array_length (ex_info->handlers);
792 static MonoExceptionClause*
793 method_encode_clauses (MonoDynamicImage *assembly,
794 MonoReflectionILGen *ilgen, guint32 num_clauses)
796 MonoExceptionClause *clauses;
797 MonoExceptionClause *clause;
798 MonoILExceptionInfo *ex_info;
799 MonoILExceptionBlock *ex_block;
800 guint32 finally_start;
801 int i, j, clause_index;;
803 clauses = g_new0 (MonoExceptionClause, num_clauses);
806 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
807 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
808 finally_start = ex_info->start + ex_info->len;
809 g_assert (ex_info->handlers);
810 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
811 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
812 clause = &(clauses [clause_index]);
814 clause->flags = ex_block->type;
815 clause->try_offset = ex_info->start;
817 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
818 clause->try_len = finally_start - ex_info->start;
820 clause->try_len = ex_info->len;
821 clause->handler_offset = ex_block->start;
822 clause->handler_len = ex_block->len;
823 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
824 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
825 if (ex_block->extype) {
826 mono_g_hash_table_insert (assembly->tokens,
827 GUINT_TO_POINTER (clause->token_or_filter),
830 finally_start = ex_block->start + ex_block->len;
840 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
846 gint32 num_locals = 0;
847 gint32 num_exception = 0;
850 char fat_header [12];
853 guint32 local_sig = 0;
854 guint32 header_size = 12;
857 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
858 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
859 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
860 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
864 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
866 code = mb->ilgen->code;
867 code_size = mb->ilgen->code_len;
868 max_stack = mb->ilgen->max_stack;
869 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
870 if (mb->ilgen->ex_handlers)
871 num_exception = method_count_clauses (mb->ilgen);
875 char *name = mono_string_to_utf8 (mb->name);
876 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
877 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
880 mono_raise_exception (exception);
883 code_size = mono_array_length (code);
884 max_stack = 8; /* we probably need to run a verifier on the code... */
887 /* check for exceptions, maxstack, locals */
888 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
890 if (code_size < 64 && !(code_size & 1)) {
891 flags = (code_size << 2) | 0x2;
892 } else if (code_size < 32 && (code_size & 1)) {
893 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
897 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
898 /* add to the fixup todo list */
899 if (mb->ilgen && mb->ilgen->num_token_fixups)
900 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
901 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
902 return assembly->text_rva + idx;
906 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
908 * FIXME: need to set also the header size in fat_flags.
909 * (and more sects and init locals flags)
913 fat_flags |= METHOD_HEADER_MORE_SECTS;
915 fat_flags |= METHOD_HEADER_INIT_LOCALS;
916 fat_header [0] = fat_flags;
917 fat_header [1] = (header_size / 4 ) << 4;
918 shortp = (guint16*)(fat_header + 2);
919 *shortp = GUINT16_TO_LE (max_stack);
920 intp = (guint32*)(fat_header + 4);
921 *intp = GUINT32_TO_LE (code_size);
922 intp = (guint32*)(fat_header + 8);
923 *intp = GUINT32_TO_LE (local_sig);
924 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
925 /* add to the fixup todo list */
926 if (mb->ilgen && mb->ilgen->num_token_fixups)
927 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
929 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
931 unsigned char sheader [4];
932 MonoExceptionClause clause;
933 MonoILExceptionInfo * ex_info;
934 MonoILExceptionBlock * ex_block;
937 stream_data_align (&assembly->code);
938 /* always use fat format for now */
939 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
940 num_exception *= sizeof (MonoExceptionClause);
941 num_exception += 4; /* include the size of the header */
942 sheader [1] = num_exception & 0xff;
943 sheader [2] = (num_exception >> 8) & 0xff;
944 sheader [3] = (num_exception >> 16) & 0xff;
945 mono_image_add_stream_data (&assembly->code, sheader, 4);
946 /* fat header, so we are already aligned */
948 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
949 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
950 if (ex_info->handlers) {
951 int finally_start = ex_info->start + ex_info->len;
952 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
953 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
954 clause.flags = GUINT32_TO_LE (ex_block->type);
955 clause.try_offset = GUINT32_TO_LE (ex_info->start);
956 /* need fault, too, probably */
957 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
958 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
960 clause.try_len = GUINT32_TO_LE (ex_info->len);
961 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
962 clause.handler_len = GUINT32_TO_LE (ex_block->len);
963 finally_start = ex_block->start + ex_block->len;
964 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
965 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
966 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
967 /*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",
968 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);*/
969 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
972 g_error ("No clauses for ex info block %d", i);
976 return assembly->text_rva + idx;
980 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
983 MonoDynamicTable *table;
986 table = &assembly->tables [table_idx];
988 g_assert (col < table->columns);
990 values = table->values + table->columns;
991 for (i = 1; i <= table->rows; ++i) {
992 if (values [col] == token)
994 values += table->columns;
999 static GHashTable *dynamic_custom_attrs = NULL;
1001 static MonoCustomAttrInfo*
1002 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1005 MonoCustomAttrInfo *ainfo;
1006 MonoReflectionCustomAttr *cattr;
1010 /* FIXME: check in assembly the Run flag is set */
1012 count = mono_array_length (cattrs);
1014 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1016 ainfo->image = image;
1017 ainfo->num_attrs = count;
1018 for (i = 0; i < count; ++i) {
1019 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1020 ainfo->attrs [i].ctor = cattr->ctor->method;
1021 /* FIXME: might want to memdup the data here */
1022 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1023 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1030 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1032 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1037 if (!dynamic_custom_attrs)
1038 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1040 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1041 ainfo->cached = TRUE;
1045 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1047 /* they are cached, so we don't free them */
1048 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1054 * idx is the table index of the object
1055 * type is one of CUSTOM_ATTR_*
1058 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1060 MonoDynamicTable *table;
1061 MonoReflectionCustomAttr *cattr;
1063 guint32 count, i, token;
1065 char *p = blob_size;
1067 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1070 count = mono_array_length (cattrs);
1071 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1072 table->rows += count;
1073 alloc_table (table, table->rows);
1074 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1075 idx <<= CUSTOM_ATTR_BITS;
1077 for (i = 0; i < count; ++i) {
1078 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1079 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1080 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1081 type = mono_metadata_token_index (token);
1082 type <<= CUSTOM_ATTR_TYPE_BITS;
1083 switch (mono_metadata_token_table (token)) {
1084 case MONO_TABLE_METHOD:
1085 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1087 case MONO_TABLE_MEMBERREF:
1088 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1091 g_warning ("got wrong token in custom attr");
1094 values [MONO_CUSTOM_ATTR_TYPE] = type;
1096 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1097 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1098 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1099 values += MONO_CUSTOM_ATTR_SIZE;
1105 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1106 MonoArray *permissions)
1108 MonoDynamicTable *table;
1110 guint32 count, i, idx;
1111 MonoReflectionPermissionSet *perm;
1116 count = mono_array_length (permissions);
1117 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1118 table->rows += count;
1119 alloc_table (table, table->rows);
1121 for (i = 0; i < mono_array_length (permissions); ++i) {
1122 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1124 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1126 idx = mono_metadata_token_index (parent_token);
1127 idx <<= HAS_DECL_SECURITY_BITS;
1128 switch (mono_metadata_token_table (parent_token)) {
1129 case MONO_TABLE_TYPEDEF:
1130 idx |= HAS_DECL_SECURITY_TYPEDEF;
1132 case MONO_TABLE_METHOD:
1133 idx |= HAS_DECL_SECURITY_METHODDEF;
1135 case MONO_TABLE_ASSEMBLY:
1136 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1139 g_assert_not_reached ();
1142 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1143 values [MONO_DECL_SECURITY_PARENT] = idx;
1144 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1151 * Fill in the MethodDef and ParamDef tables for a method.
1152 * This is used for both normal methods and constructors.
1155 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1157 MonoDynamicTable *table;
1162 /* room in this table is already allocated */
1163 table = &assembly->tables [MONO_TABLE_METHOD];
1164 *mb->table_idx = table->next_idx ++;
1165 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1166 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1167 name = mono_string_to_utf8 (mb->name);
1168 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1170 values [MONO_METHOD_FLAGS] = mb->attrs;
1171 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1172 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1173 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1175 table = &assembly->tables [MONO_TABLE_PARAM];
1176 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1178 mono_image_add_decl_security (assembly,
1179 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1183 MonoDynamicTable *mtable;
1186 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1187 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1190 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1191 if (mono_array_get (mb->pinfo, gpointer, i))
1194 table->rows += count;
1195 alloc_table (table, table->rows);
1196 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1197 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1198 MonoReflectionParamBuilder *pb;
1199 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1200 values [MONO_PARAM_FLAGS] = pb->attrs;
1201 values [MONO_PARAM_SEQUENCE] = i;
1202 if (pb->name != NULL) {
1203 name = mono_string_to_utf8 (pb->name);
1204 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1208 values [MONO_PARAM_NAME] = 0;
1209 values += MONO_PARAM_SIZE;
1210 if (pb->marshal_info) {
1212 alloc_table (mtable, mtable->rows);
1213 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1214 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1215 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1217 pb->table_idx = table->next_idx++;
1224 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1225 MonoReflectionMethodBuilder *mb)
1227 rmb->ilgen = mb->ilgen;
1228 rmb->rtype = mb->rtype;
1229 rmb->parameters = mb->parameters;
1230 rmb->generic_params = mb->generic_params;
1231 rmb->opt_types = NULL;
1232 rmb->pinfo = mb->pinfo;
1233 rmb->attrs = mb->attrs;
1234 rmb->iattrs = mb->iattrs;
1235 rmb->call_conv = mb->call_conv;
1236 rmb->code = mb->code;
1237 rmb->type = mb->type;
1238 rmb->name = mb->name;
1239 rmb->table_idx = &mb->table_idx;
1240 rmb->init_locals = mb->init_locals;
1241 rmb->return_modreq = mb->return_modreq;
1242 rmb->return_modopt = mb->return_modopt;
1243 rmb->param_modreq = mb->param_modreq;
1244 rmb->param_modopt = mb->param_modopt;
1245 rmb->permissions = mb->permissions;
1246 rmb->mhandle = mb->mhandle;
1252 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1253 MonoReflectionCtorBuilder *mb)
1255 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1257 rmb->ilgen = mb->ilgen;
1258 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1259 rmb->parameters = mb->parameters;
1260 rmb->generic_params = NULL;
1261 rmb->opt_types = NULL;
1262 rmb->pinfo = mb->pinfo;
1263 rmb->attrs = mb->attrs;
1264 rmb->iattrs = mb->iattrs;
1265 rmb->call_conv = mb->call_conv;
1267 rmb->type = mb->type;
1268 rmb->name = mono_string_new (mono_domain_get (), name);
1269 rmb->table_idx = &mb->table_idx;
1270 rmb->init_locals = mb->init_locals;
1271 rmb->return_modreq = NULL;
1272 rmb->return_modopt = NULL;
1273 rmb->param_modreq = mb->param_modreq;
1274 rmb->param_modopt = mb->param_modopt;
1275 rmb->permissions = mb->permissions;
1276 rmb->mhandle = mb->mhandle;
1282 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1283 MonoReflectionDynamicMethod *mb)
1285 rmb->ilgen = mb->ilgen;
1286 rmb->rtype = mb->rtype;
1287 rmb->parameters = mb->parameters;
1288 rmb->generic_params = NULL;
1289 rmb->opt_types = NULL;
1291 rmb->attrs = mb->attrs;
1293 rmb->call_conv = mb->call_conv;
1296 rmb->name = mb->name;
1297 rmb->table_idx = NULL;
1298 rmb->init_locals = mb->init_locals;
1299 rmb->return_modreq = NULL;
1300 rmb->return_modopt = NULL;
1301 rmb->param_modreq = NULL;
1302 rmb->param_modopt = NULL;
1303 rmb->permissions = NULL;
1304 rmb->mhandle = mb->mhandle;
1310 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1312 MonoDynamicTable *table;
1315 ReflectionMethodBuilder rmb;
1318 reflection_methodbuilder_from_method_builder (&rmb, mb);
1320 mono_image_basic_method (&rmb, assembly);
1322 if (mb->dll) { /* It's a P/Invoke method */
1324 int charset = mb->charset & 0xf;
1325 int lasterr = mb->charset & 0x40;
1326 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1328 alloc_table (table, table->rows);
1329 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1330 /* map CharSet values to on-disk values */
1332 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1333 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1334 name = mono_string_to_utf8 (mb->dllentry);
1335 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1337 name = mono_string_to_utf8 (mb->dll);
1338 moduleref = string_heap_insert (&assembly->sheap, name);
1340 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1341 table = &assembly->tables [MONO_TABLE_MODULEREF];
1343 alloc_table (table, table->rows);
1344 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1345 values [MONO_IMPLMAP_SCOPE] = table->rows;
1349 if (mb->override_method) {
1350 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1352 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1354 alloc_table (table, table->rows);
1355 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1356 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1357 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1358 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1359 switch (mono_metadata_token_table (tok)) {
1360 case MONO_TABLE_MEMBERREF:
1361 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1363 case MONO_TABLE_METHOD:
1364 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1367 g_assert_not_reached ();
1369 values [MONO_METHODIMPL_DECLARATION] = tok;
1372 if (mb->generic_params) {
1373 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1374 table->rows += mono_array_length (mb->generic_params);
1375 alloc_table (table, table->rows);
1376 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1377 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1379 mono_image_get_generic_param_info (
1380 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1387 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1389 ReflectionMethodBuilder rmb;
1391 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1393 mono_image_basic_method (&rmb, assembly);
1397 type_get_fully_qualified_name (MonoType *type) {
1398 char *name, *result;
1402 name = mono_type_get_name (type);
1403 klass = my_mono_class_from_mono_type (type);
1404 ta = klass->image->assembly;
1406 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1407 name, ta->aname.name,
1408 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1409 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1410 ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
1416 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1420 klass = my_mono_class_from_mono_type (type);
1421 ta = klass->image->assembly;
1422 if (ta == ass || klass->image == mono_defaults.corlib)
1423 return mono_type_get_name (type);
1425 return type_get_fully_qualified_name (type);
1429 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1431 char blob_size [64];
1432 char *b = blob_size;
1437 if (!assembly->save)
1440 p = buf = g_malloc (64);
1442 mono_metadata_encode_value (0x06, p, &p);
1443 /* encode custom attributes before the type */
1444 encode_type (assembly, type, p, &p);
1445 g_assert (p-buf < 64);
1446 mono_metadata_encode_value (p-buf, b, &b);
1447 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1453 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1455 char blob_size [64];
1456 char *b = blob_size;
1461 p = buf = g_malloc (64);
1463 mono_metadata_encode_value (0x06, p, &p);
1464 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1465 /* encode custom attributes before the type */
1466 encode_reflection_type (assembly, fb->type, p, &p);
1467 g_assert (p-buf < 64);
1468 mono_metadata_encode_value (p-buf, b, &b);
1469 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1475 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1476 char blob_size [64];
1477 char *b = blob_size;
1480 guint32 idx = 0, len = 0, dummy = 0;
1482 p = buf = g_malloc (64);
1484 *ret_type = MONO_TYPE_CLASS;
1486 box_val = (char*)&dummy;
1488 box_val = ((char*)val) + sizeof (MonoObject);
1489 *ret_type = val->vtable->klass->byval_arg.type;
1492 switch (*ret_type) {
1493 case MONO_TYPE_BOOLEAN:
1498 case MONO_TYPE_CHAR:
1513 case MONO_TYPE_VALUETYPE:
1514 if (val->vtable->klass->enumtype) {
1515 *ret_type = val->vtable->klass->enum_basetype->type;
1518 g_error ("we can't encode valuetypes");
1519 case MONO_TYPE_CLASS:
1521 case MONO_TYPE_STRING: {
1522 MonoString *str = (MonoString*)val;
1523 /* there is no signature */
1524 len = str->length * 2;
1525 mono_metadata_encode_value (len, b, &b);
1526 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1528 char *swapped = g_malloc (2 * mono_string_length (str));
1529 const char *p = (const char*)mono_string_chars (str);
1531 swap_with_size (swapped, p, 2, mono_string_length (str));
1532 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1536 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1543 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1546 /* there is no signature */
1547 mono_metadata_encode_value (len, b, &b);
1548 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1549 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1550 swap_with_size (blob_size, box_val, len, 1);
1551 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1553 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1561 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1562 char blob_size [64];
1563 char *b = blob_size;
1564 char *p, *buf, *str;
1565 guint32 idx, len, bufsize = 256;
1567 p = buf = g_malloc (bufsize);
1569 switch (minfo->type) {
1570 case MONO_NATIVE_BYVALTSTR:
1571 case MONO_NATIVE_BYVALARRAY:
1572 mono_metadata_encode_value (minfo->type, p, &p);
1573 mono_metadata_encode_value (minfo->count, p, &p);
1575 case MONO_NATIVE_LPARRAY:
1576 mono_metadata_encode_value (minfo->type, p, &p);
1577 if (minfo->eltype || (minfo->count > 0)) {
1578 mono_metadata_encode_value (minfo->eltype, p, &p);
1579 if (minfo->count > 0) {
1580 mono_metadata_encode_value (0, p, &p);
1581 mono_metadata_encode_value (minfo->count, p, &p);
1585 case MONO_NATIVE_CUSTOM:
1586 mono_metadata_encode_value (minfo->type, p, &p);
1588 str = mono_string_to_utf8 (minfo->guid);
1590 mono_metadata_encode_value (len, p, &p);
1591 memcpy (p, str, len);
1595 mono_metadata_encode_value (0, p, &p);
1597 if (minfo->marshaltype) {
1598 str = mono_string_to_utf8 (minfo->marshaltype);
1600 mono_metadata_encode_value (len, p, &p);
1601 if (p + len >= buf + bufsize) {
1604 buf = g_realloc (buf, bufsize);
1607 memcpy (p, str, len);
1611 mono_metadata_encode_value (0, p, &p);
1613 if (minfo->marshaltyperef) {
1614 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1616 mono_metadata_encode_value (len, p, &p);
1617 if (p + len >= buf + bufsize) {
1620 buf = g_realloc (buf, bufsize);
1623 memcpy (p, str, len);
1627 mono_metadata_encode_value (0, p, &p);
1629 if (minfo->mcookie) {
1630 str = mono_string_to_utf8 (minfo->mcookie);
1632 mono_metadata_encode_value (len, p, &p);
1633 if (p + len >= buf + bufsize) {
1636 buf = g_realloc (buf, bufsize);
1639 memcpy (p, str, len);
1643 mono_metadata_encode_value (0, p, &p);
1647 mono_metadata_encode_value (minfo->type, p, &p);
1651 mono_metadata_encode_value (len, b, &b);
1652 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1658 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1660 MonoDynamicTable *table;
1664 /* maybe this fixup should be done in the C# code */
1665 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1666 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1667 table = &assembly->tables [MONO_TABLE_FIELD];
1668 fb->table_idx = table->next_idx ++;
1669 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1670 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1671 name = mono_string_to_utf8 (fb->name);
1672 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1674 values [MONO_FIELD_FLAGS] = fb->attrs;
1675 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1677 if (fb->offset != -1) {
1678 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1680 alloc_table (table, table->rows);
1681 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1682 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1683 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1685 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1686 guint32 field_type = 0;
1687 table = &assembly->tables [MONO_TABLE_CONSTANT];
1689 alloc_table (table, table->rows);
1690 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1691 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1692 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1693 values [MONO_CONSTANT_TYPE] = field_type;
1694 values [MONO_CONSTANT_PADDING] = 0;
1696 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1698 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1700 alloc_table (table, table->rows);
1701 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1702 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1704 * We store it in the code section because it's simpler for now.
1707 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1709 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1710 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1712 if (fb->marshal_info) {
1713 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1715 alloc_table (table, table->rows);
1716 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1717 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1718 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1723 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1727 char *b = blob_size;
1728 guint32 nparams = 0;
1729 MonoReflectionMethodBuilder *mb = fb->get_method;
1730 MonoReflectionMethodBuilder *smb = fb->set_method;
1731 guint32 idx, i, size;
1733 if (mb && mb->parameters)
1734 nparams = mono_array_length (mb->parameters);
1735 if (!mb && smb && smb->parameters)
1736 nparams = mono_array_length (smb->parameters) - 1;
1737 size = 24 + nparams * 10;
1738 buf = p = g_malloc (size);
1741 mono_metadata_encode_value (nparams, p, &p);
1743 encode_reflection_type (assembly, mb->rtype, p, &p);
1744 for (i = 0; i < nparams; ++i) {
1745 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1746 encode_reflection_type (assembly, pt, p, &p);
1749 /* the property type is the last param */
1750 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1751 for (i = 0; i < nparams; ++i) {
1752 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1753 encode_reflection_type (assembly, pt, p, &p);
1757 g_assert (p - buf < size);
1758 mono_metadata_encode_value (p-buf, b, &b);
1759 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1765 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1767 MonoDynamicTable *table;
1770 guint num_methods = 0;
1774 * we need to set things in the following tables:
1775 * PROPERTYMAP (info already filled in _get_type_info ())
1776 * PROPERTY (rows already preallocated in _get_type_info ())
1777 * METHOD (method info already done with the generic method code)
1780 table = &assembly->tables [MONO_TABLE_PROPERTY];
1781 pb->table_idx = table->next_idx ++;
1782 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1783 name = mono_string_to_utf8 (pb->name);
1784 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1786 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1787 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1789 /* FIXME: we still don't handle 'other' methods */
1790 if (pb->get_method) num_methods ++;
1791 if (pb->set_method) num_methods ++;
1793 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1794 table->rows += num_methods;
1795 alloc_table (table, table->rows);
1797 if (pb->get_method) {
1798 semaidx = table->next_idx ++;
1799 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1800 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1801 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1802 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1804 if (pb->set_method) {
1805 semaidx = table->next_idx ++;
1806 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1807 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1808 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1809 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1814 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1816 MonoDynamicTable *table;
1819 guint num_methods = 0;
1823 * we need to set things in the following tables:
1824 * EVENTMAP (info already filled in _get_type_info ())
1825 * EVENT (rows already preallocated in _get_type_info ())
1826 * METHOD (method info already done with the generic method code)
1829 table = &assembly->tables [MONO_TABLE_EVENT];
1830 eb->table_idx = table->next_idx ++;
1831 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1832 name = mono_string_to_utf8 (eb->name);
1833 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1835 values [MONO_EVENT_FLAGS] = eb->attrs;
1836 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1839 * FIXME: we still don't handle 'other' methods
1841 if (eb->add_method) num_methods ++;
1842 if (eb->remove_method) num_methods ++;
1843 if (eb->raise_method) num_methods ++;
1845 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1846 table->rows += num_methods;
1847 alloc_table (table, table->rows);
1849 if (eb->add_method) {
1850 semaidx = table->next_idx ++;
1851 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1852 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1853 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1854 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1856 if (eb->remove_method) {
1857 semaidx = table->next_idx ++;
1858 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1859 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1860 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1861 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1863 if (eb->raise_method) {
1864 semaidx = table->next_idx ++;
1865 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1866 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1867 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1868 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1873 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1875 static MonoClass *NewConstraintAttr;
1876 static MonoMethod *NewConstraintAttr_ctor;
1877 MonoDynamicTable *table;
1879 guint32 token, type;
1880 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1883 if (!NewConstraintAttr)
1884 NewConstraintAttr = mono_class_from_name (
1885 mono_defaults.corlib, "System.Runtime.CompilerServices",
1886 "NewConstraintAttribute");
1887 g_assert (NewConstraintAttr);
1889 if (!NewConstraintAttr_ctor) {
1892 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1893 MonoMethod *m = NewConstraintAttr->methods [i];
1895 if (strcmp (m->name, ".ctor"))
1898 NewConstraintAttr_ctor = m;
1902 g_assert (NewConstraintAttr_ctor);
1905 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1907 alloc_table (table, table->rows);
1909 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1910 owner <<= CUSTOM_ATTR_BITS;
1911 owner |= CUSTOM_ATTR_GENERICPAR;
1912 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1914 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1916 type = mono_metadata_token_index (token);
1917 type <<= CUSTOM_ATTR_TYPE_BITS;
1918 switch (mono_metadata_token_table (token)) {
1919 case MONO_TABLE_METHOD:
1920 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1922 case MONO_TABLE_MEMBERREF:
1923 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1926 g_warning ("got wrong token in custom attr");
1929 values [MONO_CUSTOM_ATTR_TYPE] = type;
1931 buf = p = g_malloc (1);
1932 mono_metadata_encode_value (4, p, &p);
1933 g_assert (p-buf == 1);
1935 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1937 values += MONO_CUSTOM_ATTR_SIZE;
1942 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1944 MonoDynamicTable *table;
1945 guint32 num_constraints, i;
1949 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1950 num_constraints = gparam->iface_constraints ?
1951 mono_array_length (gparam->iface_constraints) : 0;
1952 table->rows += num_constraints;
1953 if (gparam->base_type)
1955 alloc_table (table, table->rows);
1957 if (gparam->base_type) {
1958 table_idx = table->next_idx ++;
1959 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1961 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1962 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1963 assembly, gparam->base_type->type);
1966 for (i = 0; i < num_constraints; i++) {
1967 MonoReflectionType *constraint = mono_array_get (
1968 gparam->iface_constraints, gpointer, i);
1970 table_idx = table->next_idx ++;
1971 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1973 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1974 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1975 assembly, constraint->type);
1978 if (gparam->has_ctor_constraint)
1979 encode_new_constraint (assembly, owner);
1983 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1985 MonoDynamicTable *table;
1986 MonoGenericParam *param;
1990 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1991 table_idx = table->next_idx ++;
1992 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1994 param = gparam->type.type->data.generic_param;
1996 values [MONO_GENERICPARAM_OWNER] = owner;
1997 if (gparam->has_value_type)
1998 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1999 else if (gparam->has_reference_type)
2000 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2002 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2003 values [MONO_GENERICPARAM_NUMBER] = param->num;
2004 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2005 values [MONO_GENERICPARAM_KIND] = 0;
2007 encode_constraints (gparam, table_idx, assembly);
2011 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2013 MonoDynamicTable *table;
2016 guint32 cols [MONO_ASSEMBLY_SIZE];
2020 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2023 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2024 table = &assembly->tables [MONO_TABLE_MODULEREF];
2025 token = table->next_idx ++;
2027 alloc_table (table, table->rows);
2028 values = table->values + token * MONO_MODULEREF_SIZE;
2029 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2031 token <<= RESOLTION_SCOPE_BITS;
2032 token |= RESOLTION_SCOPE_MODULEREF;
2033 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2038 if (image->assembly->dynamic)
2040 memset (cols, 0, sizeof (cols));
2042 /* image->assembly->image is the manifest module */
2043 image = image->assembly->image;
2044 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2047 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2048 token = table->next_idx ++;
2050 alloc_table (table, table->rows);
2051 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2052 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2053 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2054 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2055 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2056 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2057 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2058 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2059 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2061 if (strcmp ("", image->assembly->aname.culture)) {
2062 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2063 image->assembly->aname.culture);
2066 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2067 guchar pubtoken [9];
2069 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2070 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2072 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2074 token <<= RESOLTION_SCOPE_BITS;
2075 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2076 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2081 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2083 MonoDynamicTable *table;
2089 char *b = blob_size;
2091 switch (type->type) {
2092 case MONO_TYPE_FNPTR:
2094 case MONO_TYPE_SZARRAY:
2095 case MONO_TYPE_ARRAY:
2097 case MONO_TYPE_MVAR:
2098 case MONO_TYPE_GENERICINST:
2099 encode_type (assembly, type, p, &p);
2101 case MONO_TYPE_CLASS:
2102 case MONO_TYPE_VALUETYPE: {
2103 MonoClass *k = mono_class_from_mono_type (type);
2104 if (!k || !k->generic_inst)
2106 encode_generic_inst (assembly, k->generic_inst, p, &p);
2113 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2114 if (assembly->save) {
2115 g_assert (p-sig < 128);
2116 mono_metadata_encode_value (p-sig, b, &b);
2117 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2118 alloc_table (table, table->rows + 1);
2119 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2120 values [MONO_TYPESPEC_SIGNATURE] = token;
2123 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2124 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2130 * Despite the name, we handle also TypeSpec (with the above helper).
2133 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2135 MonoDynamicTable *table;
2137 guint32 token, scope, enclosing;
2140 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2143 token = create_typespec (assembly, type);
2146 klass = my_mono_class_from_mono_type (type);
2148 klass = mono_class_from_mono_type (type);
2151 * If it's in the same module and not a generic type parameter:
2153 if ((klass->image == &assembly->image) &&
2154 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2155 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2156 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2157 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2161 if (klass->nested_in) {
2162 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2163 /* get the typeref idx of the enclosing type */
2164 enclosing >>= TYPEDEFORREF_BITS;
2165 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2167 scope = resolution_scope_from_image (assembly, klass->image);
2169 table = &assembly->tables [MONO_TABLE_TYPEREF];
2170 if (assembly->save) {
2171 alloc_table (table, table->rows + 1);
2172 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2173 values [MONO_TYPEREF_SCOPE] = scope;
2174 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2175 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2177 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2178 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2180 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2185 * Insert a memberef row into the metadata: the token that point to the memberref
2186 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2187 * mono_image_get_fieldref_token()).
2188 * The sig param is an index to an already built signature.
2191 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2193 MonoDynamicTable *table;
2195 guint32 token, pclass;
2198 parent = mono_image_typedef_or_ref (assembly, type);
2199 switch (parent & TYPEDEFORREF_MASK) {
2200 case TYPEDEFORREF_TYPEREF:
2201 pclass = MEMBERREF_PARENT_TYPEREF;
2203 case TYPEDEFORREF_TYPESPEC:
2204 pclass = MEMBERREF_PARENT_TYPESPEC;
2206 case TYPEDEFORREF_TYPEDEF:
2207 pclass = MEMBERREF_PARENT_TYPEDEF;
2210 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2213 /* extract the index */
2214 parent >>= TYPEDEFORREF_BITS;
2216 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2218 if (assembly->save) {
2219 alloc_table (table, table->rows + 1);
2220 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2221 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2222 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2223 values [MONO_MEMBERREF_SIGNATURE] = sig;
2226 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2233 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2237 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2240 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2241 method->name, method_encode_signature (assembly, method->signature));
2242 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2247 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2248 const gchar *name, guint32 sig)
2250 MonoDynamicTable *table;
2251 guint32 parent, token;
2254 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2256 if (assembly->save) {
2257 alloc_table (table, table->rows + 1);
2258 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2259 values [MONO_MEMBERREF_CLASS] = original;
2260 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2261 values [MONO_MEMBERREF_SIGNATURE] = sig;
2264 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2271 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2274 ReflectionMethodBuilder rmb;
2276 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2280 reflection_methodbuilder_from_method_builder (&rmb, mb);
2282 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2283 mono_string_to_utf8 (rmb.name),
2284 method_builder_encode_signature (assembly, &rmb));
2285 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2290 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2293 ReflectionMethodBuilder rmb;
2295 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2299 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2301 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2302 mono_string_to_utf8 (rmb.name),
2303 method_builder_encode_signature (assembly, &rmb));
2304 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2309 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2314 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2317 g_assert (f->field->parent);
2318 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2319 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2320 f->field->name, fieldref_encode_signature (assembly, type));
2321 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2326 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2331 guint32 nparams = gmethod->mtype_argc;
2332 guint32 size = 10 + nparams * 10;
2335 char *b = blob_size;
2337 if (!assembly->save)
2340 p = buf = g_malloc (size);
2342 * FIXME: vararg, explicit_this, differenc call_conv values...
2344 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2345 mono_metadata_encode_value (nparams, p, &p);
2347 for (i = 0; i < nparams; i++)
2348 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2351 g_assert (p - buf < size);
2352 mono_metadata_encode_value (p-buf, b, &b);
2353 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2359 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2361 MonoDynamicTable *table;
2363 guint32 token, mtoken = 0, sig;
2364 MonoMethodInflated *imethod;
2365 MonoMethod *declaring;
2367 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2369 g_assert (method->signature->is_inflated);
2370 imethod = (MonoMethodInflated *) method;
2371 declaring = imethod->declaring;
2373 sig = method_encode_signature (assembly, declaring->signature);
2374 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2375 declaring->name, sig);
2377 if (!declaring->signature->generic_param_count)
2380 switch (mono_metadata_token_table (mtoken)) {
2381 case MONO_TABLE_MEMBERREF:
2382 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2384 case MONO_TABLE_METHOD:
2385 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2388 g_assert_not_reached ();
2391 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2393 if (assembly->save) {
2394 alloc_table (table, table->rows + 1);
2395 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2396 values [MONO_METHODSPEC_METHOD] = mtoken;
2397 values [MONO_METHODSPEC_SIGNATURE] = sig;
2400 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2407 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2409 MonoMethodInflated *imethod;
2412 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2416 g_assert (m->signature->is_inflated);
2417 imethod = (MonoMethodInflated *) m;
2419 if (imethod->declaring->signature->generic_param_count)
2420 token = method_encode_methodspec (assembly, m);
2422 guint32 sig = method_encode_signature (
2423 assembly, imethod->declaring->signature);
2424 token = mono_image_get_memberref_token (
2425 assembly, &m->klass->byval_arg, m->name, sig);
2428 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2433 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2435 MonoDynamicTable *table;
2442 char *b = blob_size;
2446 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2447 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2448 * Because of this, we must not insert it into the `typeref' hash table.
2451 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2455 g_assert (tb->generic_params);
2456 klass = mono_class_from_mono_type (tb->type.type);
2458 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2459 encode_type (assembly, &klass->byval_arg, p, &p);
2461 count = mono_array_length (tb->generic_params);
2462 mono_metadata_encode_value (count, p, &p);
2463 for (i = 0; i < count; i++) {
2464 MonoReflectionGenericParam *gparam;
2466 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2468 encode_type (assembly, gparam->type.type, p, &p);
2471 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2472 if (assembly->save) {
2473 g_assert (p-sig < 128);
2474 mono_metadata_encode_value (p-sig, b, &b);
2475 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2476 alloc_table (table, table->rows + 1);
2477 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2478 values [MONO_TYPESPEC_SIGNATURE] = token;
2481 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2482 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2488 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2490 MonoDynamicTable *table;
2493 guint32 token, pclass, parent, sig;
2496 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2500 klass = mono_class_from_mono_type (fb->typeb->type);
2501 name = mono_string_to_utf8 (fb->name);
2503 sig = fieldref_encode_signature (assembly, fb->type->type);
2505 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2506 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2508 pclass = MEMBERREF_PARENT_TYPESPEC;
2509 parent >>= TYPEDEFORREF_BITS;
2511 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2513 if (assembly->save) {
2514 alloc_table (table, table->rows + 1);
2515 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2516 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2517 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2518 values [MONO_MEMBERREF_SIGNATURE] = sig;
2521 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2523 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2528 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2536 char *b = blob_size;
2538 if (!assembly->save)
2542 g_assert (helper->type == 2);
2544 if (helper->arguments)
2545 nargs = mono_array_length (helper->arguments);
2549 size = 10 + (nargs * 10);
2551 p = buf = g_malloc (size);
2553 /* Encode calling convention */
2554 /* Change Any to Standard */
2555 if ((helper->call_conv & 0x03) == 0x03)
2556 helper->call_conv = 0x01;
2557 /* explicit_this implies has_this */
2558 if (helper->call_conv & 0x40)
2559 helper->call_conv &= 0x20;
2561 if (helper->call_conv == 0) /* Unmanaged */
2562 *p = helper->unmanaged_call_conv - 1;
2565 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2566 if (helper->call_conv & 0x02) /* varargs */
2571 mono_metadata_encode_value (nargs, p, &p);
2572 encode_reflection_type (assembly, helper->return_type, p, &p);
2573 for (i = 0; i < nargs; ++i) {
2574 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2575 encode_reflection_type (assembly, pt, p, &p);
2578 g_assert (p - buf < size);
2579 mono_metadata_encode_value (p-buf, b, &b);
2580 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2587 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2590 MonoDynamicTable *table;
2593 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2594 idx = table->next_idx ++;
2596 alloc_table (table, table->rows);
2597 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2599 values [MONO_STAND_ALONE_SIGNATURE] =
2600 mono_reflection_encode_sighelper (assembly, helper);
2606 reflection_cc_to_file (int call_conv) {
2607 switch (call_conv & 0x3) {
2609 case 1: return MONO_CALL_DEFAULT;
2610 case 2: return MONO_CALL_VARARG;
2612 g_assert_not_reached ();
2619 MonoMethodSignature *sig;
2625 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2630 MonoMethodSignature *sig;
2633 name = mono_string_to_utf8 (m->name);
2634 nparams = mono_array_length (m->parameters);
2635 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2637 sig->sentinelpos = -1;
2638 sig->call_convention = reflection_cc_to_file (m->call_conv);
2639 sig->param_count = nparams;
2640 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2641 for (i = 0; i < nparams; ++i) {
2642 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2643 sig->params [i] = t->type;
2646 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2648 if (strcmp (name, am->name) == 0 &&
2649 mono_metadata_type_equal (am->parent, m->parent->type) &&
2650 mono_metadata_signature_equal (am->sig, sig)) {
2653 m->table_idx = am->token & 0xffffff;
2657 am = g_new0 (ArrayMethod, 1);
2660 am->parent = m->parent->type;
2661 am->token = mono_image_get_memberref_token (assembly, am->parent,
2662 name, method_encode_signature (assembly, sig));
2663 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2664 m->table_idx = am->token & 0xffffff;
2669 * Insert into the metadata tables all the info about the TypeBuilder tb.
2670 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2673 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2675 MonoDynamicTable *table;
2677 int i, is_object = 0, is_system = 0;
2680 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2681 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2682 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2683 n = mono_string_to_utf8 (tb->name);
2684 if (strcmp (n, "Object") == 0)
2686 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2688 n = mono_string_to_utf8 (tb->nspace);
2689 if (strcmp (n, "System") == 0)
2691 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2693 if (tb->parent && !(is_system && is_object) &&
2694 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2695 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2697 values [MONO_TYPEDEF_EXTENDS] = 0;
2698 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2699 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2702 * if we have explicitlayout or sequentiallayouts, output data in the
2703 * ClassLayout table.
2705 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2706 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2708 alloc_table (table, table->rows);
2709 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2710 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2711 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2712 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2715 /* handle interfaces */
2716 if (tb->interfaces) {
2717 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2719 table->rows += mono_array_length (tb->interfaces);
2720 alloc_table (table, table->rows);
2721 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2722 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2723 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2724 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2725 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2726 values += MONO_INTERFACEIMPL_SIZE;
2730 /* handle generic parameters */
2731 if (tb->generic_params) {
2732 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2733 table->rows += mono_array_length (tb->generic_params);
2734 alloc_table (table, table->rows);
2735 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2736 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2738 mono_image_get_generic_param_info (
2739 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2745 table = &assembly->tables [MONO_TABLE_FIELD];
2746 table->rows += tb->num_fields;
2747 alloc_table (table, table->rows);
2748 for (i = 0; i < tb->num_fields; ++i)
2749 mono_image_get_field_info (
2750 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2753 /* handle constructors */
2755 table = &assembly->tables [MONO_TABLE_METHOD];
2756 table->rows += mono_array_length (tb->ctors);
2757 alloc_table (table, table->rows);
2758 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2759 mono_image_get_ctor_info (domain,
2760 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2763 /* handle methods */
2765 table = &assembly->tables [MONO_TABLE_METHOD];
2766 table->rows += tb->num_methods;
2767 alloc_table (table, table->rows);
2768 for (i = 0; i < tb->num_methods; ++i)
2769 mono_image_get_method_info (
2770 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2773 /* Do the same with properties etc.. */
2774 if (tb->events && mono_array_length (tb->events)) {
2775 table = &assembly->tables [MONO_TABLE_EVENT];
2776 table->rows += mono_array_length (tb->events);
2777 alloc_table (table, table->rows);
2778 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2780 alloc_table (table, table->rows);
2781 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2782 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2783 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2784 for (i = 0; i < mono_array_length (tb->events); ++i)
2785 mono_image_get_event_info (
2786 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2788 if (tb->properties && mono_array_length (tb->properties)) {
2789 table = &assembly->tables [MONO_TABLE_PROPERTY];
2790 table->rows += mono_array_length (tb->properties);
2791 alloc_table (table, table->rows);
2792 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2794 alloc_table (table, table->rows);
2795 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2796 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2797 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2798 for (i = 0; i < mono_array_length (tb->properties); ++i)
2799 mono_image_get_property_info (
2800 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2803 mono_image_add_decl_security (assembly,
2804 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2808 MonoDynamicTable *ntable;
2810 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2811 ntable->rows += mono_array_length (tb->subtypes);
2812 alloc_table (ntable, ntable->rows);
2813 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2815 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2816 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2818 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2819 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2820 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2821 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2822 mono_string_to_utf8 (tb->name), tb->table_idx,
2823 ntable->next_idx, ntable->rows);*/
2824 values += MONO_NESTED_CLASS_SIZE;
2831 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2835 g_ptr_array_add (types, type);
2837 if (!type->subtypes)
2840 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2841 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2842 collect_types (types, subtype);
2847 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2848 MonoReflectionTypeBuilder **type2)
2850 if ((*type1)->table_idx < (*type2)->table_idx)
2853 if ((*type1)->table_idx > (*type2)->table_idx)
2860 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2865 for (i = 0; i < mono_array_length (pinfo); ++i) {
2866 MonoReflectionParamBuilder *pb;
2867 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2870 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2875 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2878 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2880 for (i = 0; i < tb->num_fields; ++i) {
2881 MonoReflectionFieldBuilder* fb;
2882 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2883 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2887 for (i = 0; i < mono_array_length (tb->events); ++i) {
2888 MonoReflectionEventBuilder* eb;
2889 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2890 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2893 if (tb->properties) {
2894 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2895 MonoReflectionPropertyBuilder* pb;
2896 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2897 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2901 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2902 MonoReflectionCtorBuilder* cb;
2903 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2904 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2905 params_add_cattrs (assembly, cb->pinfo);
2910 for (i = 0; i < tb->num_methods; ++i) {
2911 MonoReflectionMethodBuilder* mb;
2912 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2913 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2914 params_add_cattrs (assembly, mb->pinfo);
2919 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2920 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2925 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2928 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2930 /* no types in the module */
2934 for (i = 0; i < mb->num_types; ++i)
2935 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2939 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2940 MonoDynamicImage *assembly)
2942 MonoDynamicTable *table;
2946 char *b = blob_size;
2949 table = &assembly->tables [MONO_TABLE_FILE];
2951 alloc_table (table, table->rows);
2952 values = table->values + table->next_idx * MONO_FILE_SIZE;
2953 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2954 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2955 if (module->image->dynamic) {
2956 /* This depends on the fact that the main module is emitted last */
2957 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2958 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2962 path = g_strdup (module->image->name);
2964 mono_sha1_get_digest_from_file (path, hash);
2967 mono_metadata_encode_value (20, b, &b);
2968 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2969 mono_image_add_stream_data (&assembly->blob, hash, 20);
2974 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2976 MonoDynamicTable *table;
2980 table = &assembly->tables [MONO_TABLE_MODULE];
2981 mb->table_idx = table->next_idx ++;
2982 name = mono_string_to_utf8 (mb->module.name);
2983 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2985 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2988 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2989 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2990 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2994 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2995 guint32 module_index, guint32 parent_index,
2996 MonoDynamicImage *assembly)
2998 MonoDynamicTable *table;
3002 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3003 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3006 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3008 alloc_table (table, table->rows);
3009 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3011 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3012 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3013 if (klass->nested_in)
3014 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3016 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3017 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3018 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3020 res = table->next_idx;
3024 /* Emit nested types */
3025 if (klass->nested_classes) {
3028 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3029 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3036 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3037 guint32 module_index, guint32 parent_index,
3038 MonoDynamicImage *assembly)
3043 klass = mono_class_from_mono_type (tb->type.type);
3045 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3047 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3048 parent_index, assembly);
3052 * We need to do this ourselves since klass->nested_classes is not set up.
3055 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3056 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3061 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3062 guint32 module_index,
3063 MonoDynamicImage *assembly)
3065 MonoImage *image = module->image;
3069 t = &image->tables [MONO_TABLE_TYPEDEF];
3071 for (i = 0; i < t->rows; ++i) {
3072 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3074 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3075 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3079 #define align_pointer(base,p)\
3081 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3083 (p) += 4 - (__diff & 3);\
3087 compare_semantics (const void *a, const void *b)
3089 const guint32 *a_values = a;
3090 const guint32 *b_values = b;
3091 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3094 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3098 compare_custom_attrs (const void *a, const void *b)
3100 const guint32 *a_values = a;
3101 const guint32 *b_values = b;
3103 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3107 compare_field_marshal (const void *a, const void *b)
3109 const guint32 *a_values = a;
3110 const guint32 *b_values = b;
3112 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3116 compare_nested (const void *a, const void *b)
3118 const guint32 *a_values = a;
3119 const guint32 *b_values = b;
3121 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3125 * build_compressed_metadata() fills in the blob of data that represents the
3126 * raw metadata as it will be saved in the PE file. The five streams are output
3127 * and the metadata tables are comnpressed from the guint32 array representation,
3128 * to the compressed on-disk format.
3131 build_compressed_metadata (MonoDynamicImage *assembly)
3133 MonoDynamicTable *table;
3135 guint64 valid_mask = 0;
3136 guint64 sorted_mask;
3137 guint32 heapt_size = 0;
3138 guint32 meta_size = 256; /* allow for header and other stuff */
3139 guint32 table_offset;
3140 guint32 ntables = 0;
3149 MonoDynamicStream *stream;
3152 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3153 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3154 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3155 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3156 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3158 /* tables that are sorted */
3159 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3160 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3161 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3162 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3163 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3164 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3166 /* Compute table sizes */
3167 /* the MonoImage has already been created in mono_image_basic_init() */
3168 meta = &assembly->image;
3170 /* Setup the info used by compute_sizes () */
3171 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3172 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3173 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3175 meta_size += assembly->blob.index;
3176 meta_size += assembly->guid.index;
3177 meta_size += assembly->sheap.index;
3178 meta_size += assembly->us.index;
3180 for (i=0; i < 64; ++i)
3181 meta->tables [i].rows = assembly->tables [i].rows;
3183 for (i = 0; i < 64; i++){
3184 if (meta->tables [i].rows == 0)
3186 valid_mask |= (guint64)1 << i;
3188 meta->tables [i].row_size = mono_metadata_compute_size (
3189 meta, i, &meta->tables [i].size_bitfield);
3190 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3192 heapt_size += 24; /* #~ header size */
3193 heapt_size += ntables * 4;
3194 meta_size += heapt_size;
3195 meta->raw_metadata = g_malloc0 (meta_size);
3196 p = meta->raw_metadata;
3197 /* the metadata signature */
3198 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3199 /* version numbers and 4 bytes reserved */
3200 int16val = (guint16*)p;
3201 *int16val++ = GUINT16_TO_LE (1);
3202 *int16val = GUINT16_TO_LE (1);
3204 /* version string */
3205 int32val = (guint32*)p;
3206 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3208 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3209 p += GUINT32_FROM_LE (*int32val);
3210 align_pointer (meta->raw_metadata, p);
3211 int16val = (guint16*)p;
3212 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3213 *int16val = GUINT16_TO_LE (5); /* number of streams */
3217 * write the stream info.
3219 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3220 table_offset += 3; table_offset &= ~3;
3222 assembly->tstream.index = heapt_size;
3223 for (i = 0; i < 5; ++i) {
3224 int32val = (guint32*)p;
3225 stream_desc [i].stream->offset = table_offset;
3226 *int32val++ = GUINT32_TO_LE (table_offset);
3227 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3228 table_offset += GUINT32_FROM_LE (*int32val);
3229 table_offset += 3; table_offset &= ~3;
3231 strcpy (p, stream_desc [i].name);
3232 p += strlen (stream_desc [i].name) + 1;
3233 align_pointer (meta->raw_metadata, p);
3236 * now copy the data, the table stream header and contents goes first.
3238 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3239 p = meta->raw_metadata + assembly->tstream.offset;
3240 int32val = (guint32*)p;
3241 *int32val = GUINT32_TO_LE (0); /* reserved */
3244 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3245 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3246 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3247 *p++ = 1; /* version */
3250 *p++ = 1; /* version */
3254 if (meta->idx_string_wide)
3256 if (meta->idx_guid_wide)
3258 if (meta->idx_blob_wide)
3261 *p++ = 0; /* reserved */
3262 int64val = (guint64*)p;
3263 *int64val++ = GUINT64_TO_LE (valid_mask);
3264 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3266 int32val = (guint32*)p;
3267 for (i = 0; i < 64; i++){
3268 if (meta->tables [i].rows == 0)
3270 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3272 p = (unsigned char*)int32val;
3274 /* sort the tables that still need sorting */
3275 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3277 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3278 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3280 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3281 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3283 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3284 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3286 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3288 /* compress the tables */
3289 for (i = 0; i < 64; i++){
3292 guint32 bitfield = meta->tables [i].size_bitfield;
3293 if (!meta->tables [i].rows)
3295 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3296 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3297 meta->tables [i].base = p;
3298 for (row = 1; row <= meta->tables [i].rows; ++row) {
3299 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3300 for (col = 0; col < assembly->tables [i].columns; ++col) {
3301 switch (mono_metadata_table_size (bitfield, col)) {
3303 *p++ = values [col];
3306 *p++ = values [col] & 0xff;
3307 *p++ = (values [col] >> 8) & 0xff;
3310 *p++ = values [col] & 0xff;
3311 *p++ = (values [col] >> 8) & 0xff;
3312 *p++ = (values [col] >> 16) & 0xff;
3313 *p++ = (values [col] >> 24) & 0xff;
3316 g_assert_not_reached ();
3320 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3323 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3324 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3325 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3326 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3327 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3329 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3333 * Some tables in metadata need to be sorted according to some criteria, but
3334 * when methods and fields are first created with reflection, they may be assigned a token
3335 * that doesn't correspond to the final token they will get assigned after the sorting.
3336 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3337 * with the reflection objects that represent them. Once all the tables are set up, the
3338 * reflection objects will contains the correct table index. fixup_method() will fixup the
3339 * tokens for the method with ILGenerator @ilgen.
3342 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3343 guint32 code_idx = GPOINTER_TO_UINT (value);
3344 MonoReflectionILTokenInfo *iltoken;
3345 MonoReflectionFieldBuilder *field;
3346 MonoReflectionCtorBuilder *ctor;
3347 MonoReflectionMethodBuilder *method;
3348 MonoReflectionTypeBuilder *tb;
3349 MonoReflectionArrayMethod *am;
3351 unsigned char *target;
3353 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3354 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3355 target = assembly->code.data + code_idx + iltoken->code_pos;
3356 switch (target [3]) {
3357 case MONO_TABLE_FIELD:
3358 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3359 field = (MonoReflectionFieldBuilder *)iltoken->member;
3360 idx = field->table_idx;
3361 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3362 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3363 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3365 g_assert_not_reached ();
3368 case MONO_TABLE_METHOD:
3369 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3370 method = (MonoReflectionMethodBuilder *)iltoken->member;
3371 idx = method->table_idx;
3372 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3373 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3374 idx = ctor->table_idx;
3375 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3376 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3377 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3378 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3380 g_assert_not_reached ();
3383 case MONO_TABLE_TYPEDEF:
3384 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3385 g_assert_not_reached ();
3386 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3387 idx = tb->table_idx;
3389 case MONO_TABLE_MEMBERREF:
3390 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3391 am = (MonoReflectionArrayMethod*)iltoken->member;
3392 idx = am->table_idx;
3393 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3394 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3395 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3396 g_assert (m->klass->generic_inst);
3398 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3400 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3401 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3402 g_assert (f->generic_info);
3404 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3407 g_assert_not_reached ();
3410 case MONO_TABLE_METHODSPEC:
3411 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3412 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3413 g_assert (m->signature->generic_param_count);
3416 g_assert_not_reached ();
3420 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3422 target [0] = idx & 0xff;
3423 target [1] = (idx >> 8) & 0xff;
3424 target [2] = (idx >> 16) & 0xff;
3431 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3432 * value is not known when the table is emitted.
3435 fixup_cattrs (MonoDynamicImage *assembly)
3437 MonoDynamicTable *table;
3439 guint32 type, i, idx, token;
3442 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3444 for (i = 0; i < table->rows; ++i) {
3445 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3447 type = values [MONO_CUSTOM_ATTR_TYPE];
3448 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3449 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3450 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3451 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3454 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3455 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3456 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3457 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3464 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3466 MonoDynamicTable *table;
3470 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3472 alloc_table (table, table->rows);
3473 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3474 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3475 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3476 name = mono_string_to_utf8 (rsrc->name);
3477 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3479 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3484 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3486 MonoDynamicTable *table;
3490 char *b = blob_size;
3492 guint32 idx, offset;
3494 if (rsrc->filename) {
3495 name = mono_string_to_utf8 (rsrc->filename);
3496 sname = g_path_get_basename (name);
3498 table = &assembly->tables [MONO_TABLE_FILE];
3500 alloc_table (table, table->rows);
3501 values = table->values + table->next_idx * MONO_FILE_SIZE;
3502 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3503 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3506 mono_sha1_get_digest_from_file (name, hash);
3507 mono_metadata_encode_value (20, b, &b);
3508 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3509 mono_image_add_stream_data (&assembly->blob, hash, 20);
3511 idx = table->next_idx++;
3513 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3516 offset = mono_array_length (rsrc->data);
3517 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3518 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3519 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3520 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3524 * The entry should be emitted into the MANIFESTRESOURCE table of
3525 * the main module, but that needs to reference the FILE table
3526 * which isn't emitted yet.
3533 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3537 set_version_from_string (MonoString *version, guint32 *values)
3539 gchar *ver, *p, *str;
3542 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3543 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3544 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3545 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3548 ver = str = mono_string_to_utf8 (version);
3549 for (i = 0; i < 4; ++i) {
3550 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3556 /* handle Revision and Build */
3566 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3570 char *b = blob_size;
3575 len = mono_array_length (pkey);
3576 mono_metadata_encode_value (len, b, &b);
3577 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3578 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3580 /* need to get the actual value from the key type... */
3581 assembly->strong_name_size = 128;
3582 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3588 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3590 MonoDynamicTable *table;
3591 MonoDynamicImage *assembly;
3592 MonoReflectionAssemblyBuilder *assemblyb;
3597 guint32 module_index;
3599 assemblyb = moduleb->assemblyb;
3600 assembly = moduleb->dynamic_image;
3601 domain = mono_object_domain (assemblyb);
3603 /* Emit ASSEMBLY table */
3604 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3605 alloc_table (table, 1);
3606 values = table->values + MONO_ASSEMBLY_SIZE;
3607 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3608 name = mono_string_to_utf8 (assemblyb->name);
3609 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3611 if (assemblyb->culture) {
3612 name = mono_string_to_utf8 (assemblyb->culture);
3613 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3616 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3618 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3619 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3620 set_version_from_string (assemblyb->version, values);
3622 /* Emit FILE + EXPORTED_TYPE table */
3624 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3626 MonoReflectionModuleBuilder *file_module =
3627 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3628 if (file_module != moduleb) {
3629 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3631 if (file_module->types) {
3632 for (j = 0; j < file_module->num_types; ++j) {
3633 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3634 mono_image_fill_export_table (domain, tb, module_index, 0,
3640 if (assemblyb->loaded_modules) {
3641 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3642 MonoReflectionModule *file_module =
3643 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3644 mono_image_fill_file_table (domain, file_module, assembly);
3646 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3650 /* Emit MANIFESTRESOURCE table */
3652 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3654 MonoReflectionModuleBuilder *file_module =
3655 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3656 /* The table for the main module is emitted later */
3657 if (file_module != moduleb) {
3659 if (file_module->resources) {
3660 int len = mono_array_length (file_module->resources);
3661 for (j = 0; j < len; ++j) {
3662 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3663 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3671 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3672 * for the modulebuilder @moduleb.
3673 * At the end of the process, method and field tokens are fixed up and the
3674 * on-disk compressed metadata representation is created.
3677 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3679 MonoDynamicTable *table;
3680 MonoDynamicImage *assembly;
3681 MonoReflectionAssemblyBuilder *assemblyb;
3686 assemblyb = moduleb->assemblyb;
3687 assembly = moduleb->dynamic_image;
3688 domain = mono_object_domain (assemblyb);
3690 if (assembly->text_rva)
3693 assembly->text_rva = START_TEXT_RVA;
3695 if (moduleb->is_main) {
3696 mono_image_emit_manifest (moduleb);
3699 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3700 table->rows = 1; /* .<Module> */
3702 alloc_table (table, table->rows);
3704 * Set the first entry.
3706 values = table->values + table->columns;
3707 values [MONO_TYPEDEF_FLAGS] = 0;
3708 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3709 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3710 values [MONO_TYPEDEF_EXTENDS] = 0;
3711 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3712 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3715 * handle global methods
3716 * FIXME: test what to do when global methods are defined in multiple modules.
3718 if (moduleb->global_methods) {
3719 table = &assembly->tables [MONO_TABLE_METHOD];
3720 table->rows += mono_array_length (moduleb->global_methods);
3721 alloc_table (table, table->rows);
3722 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3723 mono_image_get_method_info (
3724 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3726 if (moduleb->global_fields) {
3727 table = &assembly->tables [MONO_TABLE_FIELD];
3728 table->rows += mono_array_length (moduleb->global_fields);
3729 alloc_table (table, table->rows);
3730 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3731 mono_image_get_field_info (
3732 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3735 table = &assembly->tables [MONO_TABLE_MODULE];
3736 alloc_table (table, 1);
3737 mono_image_fill_module_table (domain, moduleb, assembly);
3741 /* Collect all types into a list sorted by their table_idx */
3742 GPtrArray *types = g_ptr_array_new ();
3745 for (i = 0; i < moduleb->num_types; ++i) {
3746 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3747 collect_types (types, type);
3750 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3751 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3752 table->rows += types->len;
3753 alloc_table (table, table->rows);
3755 for (i = 0; i < types->len; ++i) {
3756 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3757 mono_image_get_type_info (domain, type, assembly);
3759 g_ptr_array_free (types, TRUE);
3763 * table->rows is already set above and in mono_image_fill_module_table.
3765 /* add all the custom attributes at the end, once all the indexes are stable */
3766 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3768 module_add_cattrs (assembly, moduleb);
3771 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3772 fixup_cattrs (assembly);
3776 * mono_image_insert_string:
3777 * @module: module builder object
3780 * Insert @str into the user string stream of @module.
3783 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3785 MonoDynamicImage *assembly;
3790 MONO_ARCH_SAVE_REGS;
3792 if (!module->dynamic_image)
3793 mono_image_module_basic_init (module);
3795 assembly = module->dynamic_image;
3797 if (assembly->save) {
3798 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3799 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3800 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3802 char *swapped = g_malloc (2 * mono_string_length (str));
3803 const char *p = (const char*)mono_string_chars (str);
3805 swap_with_size (swapped, p, 2, mono_string_length (str));
3806 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3810 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3812 mono_image_add_stream_data (&assembly->us, "", 1);
3815 idx = assembly->us.index ++;
3817 mono_g_hash_table_insert (assembly->tokens,
3818 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3820 return MONO_TOKEN_STRING | idx;
3824 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3825 MonoArray *opt_param_types)
3830 klass = obj->vtable->klass;
3831 if (strcmp (klass->name, "MonoMethod") == 0) {
3832 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3833 MonoMethodSignature *sig, *old;
3834 guint32 sig_token, parent;
3837 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3839 nargs = mono_array_length (opt_param_types);
3840 old = method->signature;
3841 sig = mono_metadata_signature_alloc (
3842 &assembly->image, old->param_count + nargs);
3844 sig->hasthis = old->hasthis;
3845 sig->explicit_this = old->explicit_this;
3846 sig->call_convention = old->call_convention;
3847 sig->generic_param_count = old->generic_param_count;
3848 sig->param_count = old->param_count + nargs;
3849 sig->sentinelpos = old->param_count;
3850 sig->ret = old->ret;
3852 for (i = 0; i < old->param_count; i++)
3853 sig->params [i] = old->params [i];
3855 for (i = 0; i < nargs; i++) {
3856 MonoReflectionType *rt = mono_array_get (
3857 opt_param_types, MonoReflectionType *, i);
3858 sig->params [old->param_count + i] = rt->type;
3861 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3862 g_assert ((parent & TYPEDEFORREF_MASK) == MEMBERREF_PARENT_TYPEREF);
3863 parent >>= TYPEDEFORREF_BITS;
3865 parent <<= MEMBERREF_PARENT_BITS;
3866 parent |= MEMBERREF_PARENT_TYPEREF;
3868 sig_token = method_encode_signature (assembly, sig);
3869 token = mono_image_get_varargs_method_token (
3870 assembly, parent, method->name, sig_token);
3871 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3872 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3873 ReflectionMethodBuilder rmb;
3874 guint32 parent, sig;
3876 reflection_methodbuilder_from_method_builder (&rmb, mb);
3877 rmb.opt_types = opt_param_types;
3879 sig = method_builder_encode_signature (assembly, &rmb);
3881 parent = mono_image_create_token (assembly, obj);
3882 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3884 parent = mono_metadata_token_index (parent) << MEMBERREF_PARENT_BITS;
3885 parent |= MEMBERREF_PARENT_METHODDEF;
3887 token = mono_image_get_varargs_method_token (
3888 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3890 g_error ("requested method token for %s\n", klass->name);
3896 * mono_image_create_token:
3897 * @assembly: a dynamic assembly
3900 * Get a token to insert in the IL code stream for the given MemberInfo.
3901 * @obj can be one of:
3902 * ConstructorBuilder
3912 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3917 klass = obj->vtable->klass;
3918 if (strcmp (klass->name, "MethodBuilder") == 0) {
3919 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3921 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3922 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3924 token = mono_image_get_methodbuilder_token (assembly, mb);
3925 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3927 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3928 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3930 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3931 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3933 token = mono_image_get_ctorbuilder_token (assembly, mb);
3934 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3936 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3937 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3938 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3939 if (tb->generic_params) {
3940 token = mono_image_get_generic_field_token (assembly, fb);
3942 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3945 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3946 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3947 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3949 else if (strcmp (klass->name, "MonoType") == 0 ||
3950 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3951 MonoReflectionType *tb = (MonoReflectionType *)obj;
3952 token = mono_metadata_token_from_dor (
3953 mono_image_typedef_or_ref (assembly, tb->type));
3955 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3956 MonoReflectionType *tb = (MonoReflectionType *)obj;
3957 token = mono_metadata_token_from_dor (
3958 mono_image_typedef_or_ref (assembly, tb->type));
3960 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3961 strcmp (klass->name, "MonoMethod") == 0) {
3962 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3963 if (m->method->signature->is_inflated) {
3964 token = mono_image_get_methodspec_token (assembly, m->method);
3965 } else if (m->method->signature->generic_param_count) {
3966 g_assert_not_reached ();
3967 } else if ((m->method->klass->image == &assembly->image) &&
3968 !m->method->klass->generic_inst) {
3969 static guint32 method_table_idx = 0xffffff;
3970 if (m->method->klass->wastypebuilder) {
3971 /* we use the same token as the one that was assigned
3972 * to the Methodbuilder.
3973 * FIXME: do the equivalent for Fields.
3975 token = m->method->token;
3978 * Each token should have a unique index, but the indexes are
3979 * assigned by managed code, so we don't know about them. An
3980 * easy solution is to count backwards...
3982 method_table_idx --;
3983 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3986 token = mono_image_get_methodref_token (assembly, m->method);
3987 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3989 else if (strcmp (klass->name, "MonoField") == 0) {
3990 MonoReflectionField *f = (MonoReflectionField *)obj;
3991 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
3992 static guint32 field_table_idx = 0xffffff;
3994 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3996 token = mono_image_get_fieldref_token (assembly, f);
3997 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3999 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4000 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4001 token = mono_image_get_array_token (assembly, m);
4003 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4004 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4005 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4008 g_error ("requested token for %s\n", klass->name);
4010 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4017 guint32 import_lookup_table;
4021 guint32 import_address_table_rva;
4029 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4031 static MonoDynamicImage*
4032 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4033 char *assembly_name, char *module_name)
4035 static const guchar entrycode [16] = {0xff, 0x25, 0};
4036 MonoDynamicImage *image;
4040 * We need to use the current ms version or the ms runtime it won't find
4041 * the support dlls. D'oh!
4042 * const char *version = "mono-" VERSION;
4045 * To make binaries default to the .Net 1.0 version
4046 * const char *version = "v1.0.3705";
4048 const char *version = "v1.1.4322";
4051 image = GC_MALLOC (sizeof (MonoDynamicImage));
4053 image = g_new0 (MonoDynamicImage, 1);
4056 /* keep in sync with image.c */
4057 image->image.name = assembly_name;
4058 image->image.assembly_name = image->image.name; /* they may be different */
4059 image->image.module_name = module_name;
4060 image->image.version = g_strdup (version);
4061 image->image.dynamic = TRUE;
4063 image->image.references = g_new0 (MonoAssembly*, 1);
4064 image->image.references [0] = NULL;
4066 mono_image_init (&image->image);
4068 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4069 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4070 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4071 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4072 image->handleref = g_hash_table_new (NULL, NULL);
4073 image->tokens = mono_g_hash_table_new (NULL, NULL);
4074 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4075 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4076 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4078 string_heap_init (&image->sheap);
4079 mono_image_add_stream_data (&image->us, "", 1);
4080 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4081 /* import tables... */
4082 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4083 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4084 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4085 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4086 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4087 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4088 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4089 stream_data_align (&image->code);
4091 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4093 for (i=0; i < 64; ++i) {
4094 image->tables [i].next_idx = 1;
4095 image->tables [i].columns = table_sizes [i];
4098 image->image.assembly = (MonoAssembly*)assembly;
4099 image->run = assembly->run;
4100 image->save = assembly->save;
4106 * mono_image_basic_init:
4107 * @assembly: an assembly builder object
4109 * Create the MonoImage that represents the assembly builder and setup some
4110 * of the helper hash table and the basic metadata streams.
4113 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4115 MonoDynamicAssembly *assembly;
4116 MonoDynamicImage *image;
4118 MONO_ARCH_SAVE_REGS;
4120 if (assemblyb->dynamic_assembly)
4124 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4126 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4129 assembly->assembly.dynamic = TRUE;
4130 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4131 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4132 if (assemblyb->culture)
4133 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4135 assembly->assembly.aname.culture = g_strdup ("");
4137 assembly->run = assemblyb->access != 2;
4138 assembly->save = assemblyb->access != 1;
4140 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4141 assembly->assembly.aname.name = image->image.name;
4142 assembly->assembly.image = &image->image;
4144 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4145 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4149 calc_section_size (MonoDynamicImage *assembly)
4153 /* alignment constraints */
4154 assembly->code.index += 3;
4155 assembly->code.index &= ~3;
4156 assembly->meta_size += 3;
4157 assembly->meta_size &= ~3;
4158 assembly->resources.index += 3;
4159 assembly->resources.index &= ~3;
4161 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4162 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4165 if (assembly->win32_res) {
4166 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4168 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4169 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4173 assembly->sections [MONO_SECTION_RELOC].size = 12;
4174 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4184 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4188 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4190 ResTreeNode *t1 = (ResTreeNode*)a;
4191 ResTreeNode *t2 = (ResTreeNode*)b;
4193 return t1->id - t2->id;
4197 * resource_tree_create:
4199 * Organize the resources into a resource tree.
4201 static ResTreeNode *
4202 resource_tree_create (MonoArray *win32_resources)
4204 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4208 tree = g_new0 (ResTreeNode, 1);
4210 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4211 MonoReflectionWin32Resource *win32_res =
4212 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4216 lang_node = g_new0 (ResTreeNode, 1);
4217 lang_node->id = win32_res->lang_id;
4218 lang_node->win32_res = win32_res;
4220 /* Create type node if neccesary */
4222 for (l = tree->children; l; l = l->next)
4223 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4224 type_node = (ResTreeNode*)l->data;
4229 type_node = g_new0 (ResTreeNode, 1);
4230 type_node->id = win32_res->res_type;
4233 * The resource types have to be sorted otherwise
4234 * Windows Explorer can't display the version information.
4236 tree->children = g_slist_insert_sorted (tree->children, type_node,
4237 resource_tree_compare_by_id);
4240 /* Create res node if neccesary */
4242 for (l = type_node->children; l; l = l->next)
4243 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4244 res_node = (ResTreeNode*)l->data;
4249 res_node = g_new0 (ResTreeNode, 1);
4250 res_node->id = win32_res->res_id;
4251 type_node->children = g_slist_append (type_node->children, res_node);
4254 res_node->children = g_slist_append (res_node->children, lang_node);
4261 * resource_tree_encode:
4263 * Encode the resource tree into the format used in the PE file.
4266 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4269 MonoPEResourceDir dir;
4270 MonoPEResourceDirEntry dir_entry;
4271 MonoPEResourceDataEntry data_entry;
4275 * For the format of the resource directory, see the article
4276 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4280 memset (&dir, 0, sizeof (dir));
4281 memset (&dir_entry, 0, sizeof (dir_entry));
4282 memset (&data_entry, 0, sizeof (data_entry));
4284 g_assert (sizeof (dir) == 16);
4285 g_assert (sizeof (dir_entry) == 8);
4286 g_assert (sizeof (data_entry) == 16);
4288 node->offset = p - begin;
4290 /* IMAGE_RESOURCE_DIRECTORY */
4291 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4293 memcpy (p, &dir, sizeof (dir));
4296 /* Reserve space for entries */
4298 p += sizeof (dir_entry) * dir.res_id_entries;
4300 /* Write children */
4301 for (l = node->children; l; l = l->next) {
4302 ResTreeNode *child = (ResTreeNode*)l->data;
4304 if (child->win32_res) {
4306 child->offset = p - begin;
4308 /* IMAGE_RESOURCE_DATA_ENTRY */
4309 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4310 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4312 memcpy (p, &data_entry, sizeof (data_entry));
4313 p += sizeof (data_entry);
4315 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4316 p += data_entry.rde_size;
4319 resource_tree_encode (child, begin, p, &p);
4322 /* IMAGE_RESOURCE_ENTRY */
4323 for (l = node->children; l; l = l->next) {
4324 ResTreeNode *child = (ResTreeNode*)l->data;
4325 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4327 dir_entry.is_dir = child->win32_res ? 0 : 1;
4328 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4330 memcpy (entries, &dir_entry, sizeof (dir_entry));
4331 entries += sizeof (dir_entry);
4338 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4343 MonoReflectionWin32Resource *win32_res;
4346 if (!assemblyb->win32_resources)
4350 * Resources are stored in a three level tree inside the PE file.
4351 * - level one contains a node for each type of resource
4352 * - level two contains a node for each resource
4353 * - level three contains a node for each instance of a resource for a
4354 * specific language.
4357 tree = resource_tree_create (assemblyb->win32_resources);
4359 /* Estimate the size of the encoded tree */
4361 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4362 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4363 size += mono_array_length (win32_res->res_data);
4365 /* Directory structure */
4366 size += mono_array_length (assemblyb->win32_resources) * 256;
4367 p = buf = g_malloc (size);
4369 resource_tree_encode (tree, p, p, &p);
4371 g_assert (p - buf < size);
4373 assembly->win32_res = g_malloc (p - buf);
4374 assembly->win32_res_size = p - buf;
4375 memcpy (assembly->win32_res, buf, p - buf);
4381 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4383 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4386 p += sizeof (MonoPEResourceDir);
4387 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4388 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4389 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4390 if (dir_entry->is_dir)
4391 fixup_resource_directory (res_section, child, rva);
4393 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4394 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4397 p += sizeof (MonoPEResourceDirEntry);
4402 * mono_image_create_pefile:
4403 * @mb: a module builder object
4405 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4406 * assembly->pefile where it can be easily retrieved later in chunks.
4409 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4410 MonoMSDOSHeader *msdos;
4411 MonoDotNetHeader *header;
4412 MonoSectionTable *section;
4413 MonoCLIHeader *cli_header;
4414 guint32 size, image_size, virtual_base, text_offset;
4415 guint32 header_start, section_start, file_offset, virtual_offset;
4416 MonoDynamicImage *assembly;
4417 MonoReflectionAssemblyBuilder *assemblyb;
4418 MonoDynamicStream *pefile;
4420 guint32 *rva, value;
4423 static const unsigned char msheader[] = {
4424 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4425 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4428 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4429 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4430 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4431 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4434 assemblyb = mb->assemblyb;
4436 mono_image_basic_init (assemblyb);
4437 assembly = mb->dynamic_image;
4439 /* already created */
4440 if (assembly->pefile.index)
4443 mono_image_build_metadata (mb);
4445 if (mb->is_main && assemblyb->resources) {
4446 int len = mono_array_length (assemblyb->resources);
4447 for (i = 0; i < len; ++i)
4448 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4451 if (mb->resources) {
4452 int len = mono_array_length (mb->resources);
4453 for (i = 0; i < len; ++i)
4454 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4457 build_compressed_metadata (assembly);
4460 assembly_add_win32_resources (assembly, assemblyb);
4462 nsections = calc_section_size (assembly);
4464 pefile = &assembly->pefile;
4466 /* The DOS header and stub */
4467 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4468 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4470 /* the dotnet header */
4471 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4473 /* the section tables */
4474 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4476 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4477 virtual_offset = VIRT_ALIGN;
4480 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4481 if (!assembly->sections [i].size)
4484 file_offset += FILE_ALIGN - 1;
4485 file_offset &= ~(FILE_ALIGN - 1);
4486 virtual_offset += VIRT_ALIGN - 1;
4487 virtual_offset &= ~(VIRT_ALIGN - 1);
4489 assembly->sections [i].offset = file_offset;
4490 assembly->sections [i].rva = virtual_offset;
4492 file_offset += assembly->sections [i].size;
4493 virtual_offset += assembly->sections [i].size;
4494 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4497 file_offset += FILE_ALIGN - 1;
4498 file_offset &= ~(FILE_ALIGN - 1);
4499 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4501 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4503 /* back-patch info */
4504 msdos = (MonoMSDOSHeader*)pefile->data;
4505 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4506 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4507 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4509 header = (MonoDotNetHeader*)(pefile->data + header_start);
4510 header->pesig [0] = 'P';
4511 header->pesig [1] = 'E';
4513 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4514 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4515 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4516 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4517 if (assemblyb->pekind == 1) {
4519 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4522 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4525 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4527 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4528 header->pe.pe_major = 6;
4529 header->pe.pe_minor = 0;
4530 size = assembly->sections [MONO_SECTION_TEXT].size;
4531 size += FILE_ALIGN - 1;
4532 size &= ~(FILE_ALIGN - 1);
4533 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4534 size = assembly->sections [MONO_SECTION_RSRC].size;
4535 size += FILE_ALIGN - 1;
4536 size &= ~(FILE_ALIGN - 1);
4537 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4538 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4539 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4540 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4541 /* pe_rva_entry_point always at the beginning of the text section */
4542 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4544 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4545 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4546 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4547 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4548 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4549 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4550 size = section_start;
4551 size += FILE_ALIGN - 1;
4552 size &= ~(FILE_ALIGN - 1);
4553 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4555 size += VIRT_ALIGN - 1;
4556 size &= ~(VIRT_ALIGN - 1);
4557 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4560 // Translate the PEFileKind value to the value expected by the Windows loader
4563 short kind = assemblyb->pekind;
4566 // PEFileKinds.ConsoleApplication == 2
4567 // PEFileKinds.WindowApplication == 3
4570 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4571 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4577 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4579 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4580 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4581 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4582 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4583 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4584 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4586 /* fill data directory entries */
4588 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4589 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4591 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4592 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4594 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4595 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4596 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4597 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4598 /* patch imported function RVA name */
4599 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4600 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4602 /* the import table */
4603 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4604 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4605 /* patch imported dll RVA name and other entries in the dir */
4606 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4607 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4608 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4609 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4610 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4611 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4613 p = (assembly->code.data + assembly->ilt_offset);
4614 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4615 *p++ = (value) & 0xff;
4616 *p++ = (value >> 8) & (0xff);
4617 *p++ = (value >> 16) & (0xff);
4618 *p++ = (value >> 24) & (0xff);
4620 /* the CLI header info */
4621 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4622 cli_header->ch_size = GUINT32_FROM_LE (72);
4623 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4624 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4625 if (assemblyb->entry_point) {
4626 guint32 table_idx = 0;
4627 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4628 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4629 table_idx = methodb->table_idx;
4632 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4633 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4636 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4637 /* The embedded managed resources */
4638 text_offset = assembly->text_rva + assembly->code.index;
4639 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4640 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4641 text_offset += assembly->resources.index;
4642 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4643 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4644 text_offset += assembly->meta_size;
4645 if (assembly->strong_name_size) {
4646 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4647 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4648 text_offset += assembly->strong_name_size;
4651 /* write the section tables and section content */
4652 section = (MonoSectionTable*)(pefile->data + section_start);
4653 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4654 static const char *section_names [] = {
4655 ".text", ".rsrc", ".reloc"
4657 if (!assembly->sections [i].size)
4659 strcpy (section->st_name, section_names [i]);
4660 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4661 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4662 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4663 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4664 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4665 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4666 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4668 case MONO_SECTION_TEXT:
4669 /* patch entry point */
4670 p = (assembly->code.data + 2);
4671 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4672 *p++ = (value) & 0xff;
4673 *p++ = (value >> 8) & 0xff;
4674 *p++ = (value >> 16) & 0xff;
4675 *p++ = (value >> 24) & 0xff;
4677 text_offset = assembly->sections [i].offset;
4678 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4679 text_offset += assembly->code.index;
4680 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4681 text_offset += assembly->resources.index;
4682 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4683 text_offset += assembly->meta_size;
4684 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4686 g_free (assembly->image.raw_metadata);
4688 case MONO_SECTION_RELOC:
4689 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4690 *rva = GUINT32_FROM_LE (assembly->text_rva);
4692 *rva = GUINT32_FROM_LE (12);
4694 data16 = (guint16*)rva;
4696 * the entrypoint is always at the start of the text section
4697 * 3 is IMAGE_REL_BASED_HIGHLOW
4698 * 2 is patch_size_rva - text_rva
4700 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4702 *data16 = 0; /* terminate */
4704 case MONO_SECTION_RSRC:
4705 if (assembly->win32_res) {
4706 text_offset = assembly->sections [i].offset;
4708 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4709 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4711 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4715 g_assert_not_reached ();
4720 /* check that the file is properly padded */
4723 FILE *f = fopen ("mypetest.exe", "w");
4724 fwrite (pefile->data, pefile->index, 1, f);
4730 MonoReflectionModule *
4731 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4735 MonoImageOpenStatus status;
4736 MonoDynamicAssembly *assembly;
4738 name = mono_string_to_utf8 (fileName);
4740 image = mono_image_open (name, &status);
4743 if (status == MONO_IMAGE_ERROR_ERRNO)
4744 exc = mono_get_exception_file_not_found (fileName);
4746 exc = mono_get_exception_bad_image_format (name);
4748 mono_raise_exception (exc);
4753 assembly = ab->dynamic_assembly;
4754 image->assembly = (MonoAssembly*)assembly;
4756 mono_assembly_load_references (image, &status);
4758 mono_image_close (image);
4759 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4762 return mono_module_get_object (mono_domain_get (), image);
4766 * We need to return always the same object for MethodInfo, FieldInfo etc..
4767 * but we need to consider the reflected type.
4768 * type uses a different hash, since it uses custom hash/equal functions.
4773 MonoClass *refclass;
4777 reflected_equal (gconstpointer a, gconstpointer b) {
4778 const ReflectedEntry *ea = a;
4779 const ReflectedEntry *eb = b;
4781 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4785 reflected_hash (gconstpointer a) {
4786 const ReflectedEntry *ea = a;
4787 return GPOINTER_TO_UINT (ea->item);
4790 #define CHECK_OBJECT(t,p,k) \
4796 mono_domain_lock (domain); \
4797 if (!domain->refobject_hash) \
4798 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4799 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4800 mono_domain_unlock (domain); \
4806 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4808 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4811 #define CACHE_OBJECT(p,o,k) \
4813 ReflectedEntry *e = ALLOC_REFENTRY; \
4815 e->refclass = (k); \
4816 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4817 mono_domain_unlock (domain); \
4821 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4823 /* this is done only once */
4824 mono_domain_lock (domain);
4825 CACHE_OBJECT (assembly, res, NULL);
4829 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4831 /* this is done only once */
4832 mono_domain_lock (domain);
4833 CACHE_OBJECT (module, res, NULL);
4837 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4839 MonoDynamicImage *image = moduleb->dynamic_image;
4840 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4843 * FIXME: we already created an image in mono_image_basic_init (), but
4844 * we don't know which module it belongs to, since that is only
4845 * determined at assembly save time.
4847 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4848 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4850 moduleb->module.image = &image->image;
4851 moduleb->dynamic_image = image;
4852 register_module (mono_object_domain (moduleb), moduleb, image);
4857 * mono_assembly_get_object:
4858 * @domain: an app domain
4859 * @assembly: an assembly
4861 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4863 MonoReflectionAssembly*
4864 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4866 static MonoClass *System_Reflection_Assembly;
4867 MonoReflectionAssembly *res;
4869 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4870 if (!System_Reflection_Assembly)
4871 System_Reflection_Assembly = mono_class_from_name (
4872 mono_defaults.corlib, "System.Reflection", "Assembly");
4873 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4874 res->assembly = assembly;
4875 CACHE_OBJECT (assembly, res, NULL);
4881 MonoReflectionModule*
4882 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4884 static MonoClass *System_Reflection_Module;
4885 MonoReflectionModule *res;
4887 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4888 if (!System_Reflection_Module)
4889 System_Reflection_Module = mono_class_from_name (
4890 mono_defaults.corlib, "System.Reflection", "Module");
4891 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4894 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4896 res->fqname = mono_string_new (domain, image->name);
4897 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4898 res->scopename = mono_string_new (domain, image->module_name);
4900 mono_image_addref (image);
4902 CACHE_OBJECT (image, res, NULL);
4906 MonoReflectionModule*
4907 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4909 static MonoClass *System_Reflection_Module;
4910 MonoReflectionModule *res;
4911 MonoTableInfo *table;
4912 guint32 cols [MONO_FILE_SIZE];
4914 guint32 i, name_idx;
4917 if (!System_Reflection_Module)
4918 System_Reflection_Module = mono_class_from_name (
4919 mono_defaults.corlib, "System.Reflection", "Module");
4920 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4922 table = &image->tables [MONO_TABLE_FILE];
4923 g_assert (table_index < table->rows);
4924 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4927 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4928 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4930 // Check whenever the row has a corresponding row in the moduleref table
4931 table = &image->tables [MONO_TABLE_MODULEREF];
4932 for (i = 0; i < table->rows; ++i) {
4933 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4934 val = mono_metadata_string_heap (image, name_idx);
4935 if (strcmp (val, name) == 0)
4936 res->image = image->modules [i];
4939 res->fqname = mono_string_new (domain, name);
4940 res->name = mono_string_new (domain, name);
4941 res->scopename = mono_string_new (domain, name);
4942 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4948 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4950 if ((t1->type != t2->type) ||
4951 (t1->byref != t2->byref))
4955 case MONO_TYPE_VOID:
4956 case MONO_TYPE_BOOLEAN:
4957 case MONO_TYPE_CHAR:
4968 case MONO_TYPE_STRING:
4971 case MONO_TYPE_OBJECT:
4972 case MONO_TYPE_TYPEDBYREF:
4974 case MONO_TYPE_VALUETYPE:
4975 case MONO_TYPE_CLASS:
4976 case MONO_TYPE_SZARRAY:
4977 return t1->data.klass == t2->data.klass;
4979 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4980 case MONO_TYPE_ARRAY:
4981 if (t1->data.array->rank != t2->data.array->rank)
4983 return t1->data.array->eklass == t2->data.array->eklass;
4984 case MONO_TYPE_GENERICINST: {
4986 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4988 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4990 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4991 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4997 case MONO_TYPE_MVAR:
4998 return t1->data.generic_param == t2->data.generic_param;
5000 g_error ("implement type compare for %0x!", t1->type);
5008 mymono_metadata_type_hash (MonoType *t1)
5014 hash |= t1->byref << 6; /* do not collide with t1->type values */
5016 case MONO_TYPE_VALUETYPE:
5017 case MONO_TYPE_CLASS:
5018 case MONO_TYPE_SZARRAY:
5019 /* check if the distribution is good enough */
5020 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5022 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5027 static MonoReflectionGenericInst*
5028 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5030 static MonoClass *System_Reflection_MonoGenericInst;
5031 MonoReflectionGenericInst *res;
5032 MonoGenericInst *ginst;
5035 if (!System_Reflection_MonoGenericInst) {
5036 System_Reflection_MonoGenericInst = mono_class_from_name (
5037 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5038 g_assert (System_Reflection_MonoGenericInst);
5041 ginst = geninst->data.generic_inst;
5042 gklass = mono_class_from_mono_type (ginst->generic_type);
5044 mono_class_init (ginst->klass);
5046 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5048 res->type.type = geninst;
5049 if (gklass->wastypebuilder && gklass->reflection_info)
5050 res->generic_type = gklass->reflection_info;
5052 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5058 * mono_type_get_object:
5059 * @domain: an app domain
5062 * Return an System.MonoType object representing the type @type.
5065 mono_type_get_object (MonoDomain *domain, MonoType *type)
5067 MonoReflectionType *res;
5068 MonoClass *klass = mono_class_from_mono_type (type);
5070 mono_domain_lock (domain);
5071 if (!domain->type_hash)
5072 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5073 (GCompareFunc)mymono_metadata_type_equal);
5074 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5075 mono_domain_unlock (domain);
5078 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5079 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5080 mono_g_hash_table_insert (domain->type_hash, type, res);
5081 mono_domain_unlock (domain);
5084 if (klass->reflection_info && !klass->wastypebuilder) {
5085 //g_assert_not_reached ();
5086 /* should this be considered an error condition? */
5088 mono_domain_unlock (domain);
5089 return klass->reflection_info;
5092 mono_class_init (klass);
5093 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5095 mono_g_hash_table_insert (domain->type_hash, type, res);
5096 mono_domain_unlock (domain);
5101 * mono_method_get_object:
5102 * @domain: an app domain
5104 * @refclass: the reflected type (can be NULL)
5106 * Return an System.Reflection.MonoMethod object representing the method @method.
5108 MonoReflectionMethod*
5109 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5112 * We use the same C representation for methods and constructors, but the type
5113 * name in C# is different.
5117 MonoReflectionMethod *ret;
5120 refclass = method->klass;
5122 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5123 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5124 cname = "MonoCMethod";
5126 cname = "MonoMethod";
5127 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5129 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5130 ret->method = method;
5131 ret->name = mono_string_new (domain, method->name);
5132 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5133 CACHE_OBJECT (method, ret, refclass);
5138 * mono_field_get_object:
5139 * @domain: an app domain
5143 * Return an System.Reflection.MonoField object representing the field @field
5146 MonoReflectionField*
5147 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5149 MonoReflectionField *res;
5152 CHECK_OBJECT (MonoReflectionField *, field, klass);
5153 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5154 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5157 res->name = mono_string_new (domain, field->name);
5158 res->attrs = field->type->attrs;
5159 res->type = mono_type_get_object (domain, field->type);
5160 CACHE_OBJECT (field, res, klass);
5165 * mono_property_get_object:
5166 * @domain: an app domain
5168 * @property: a property
5170 * Return an System.Reflection.MonoProperty object representing the property @property
5173 MonoReflectionProperty*
5174 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5176 MonoReflectionProperty *res;
5179 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5180 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5181 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5183 res->property = property;
5184 CACHE_OBJECT (property, res, klass);
5189 * mono_event_get_object:
5190 * @domain: an app domain
5194 * Return an System.Reflection.MonoEvent object representing the event @event
5197 MonoReflectionEvent*
5198 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5200 MonoReflectionEvent *res;
5203 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5204 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5205 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5208 CACHE_OBJECT (event, res, klass);
5213 * mono_param_get_objects:
5214 * @domain: an app domain
5217 * Return an System.Reflection.ParameterInfo array object representing the parameters
5218 * in the method @method.
5221 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5223 static MonoClass *System_Reflection_ParameterInfo;
5224 MonoArray *res = NULL;
5225 MonoReflectionMethod *member = NULL;
5226 MonoReflectionParameter *param = NULL;
5230 if (!System_Reflection_ParameterInfo)
5231 System_Reflection_ParameterInfo = mono_class_from_name (
5232 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5234 if (!method->signature->param_count)
5235 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5237 /* Note: the cache is based on the address of the signature into the method
5238 * since we already cache MethodInfos with the method as keys.
5240 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5242 member = mono_method_get_object (domain, method, NULL);
5243 names = g_new (char *, method->signature->param_count);
5244 mono_method_get_param_names (method, (const char **) names);
5246 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5247 for (i = 0; i < method->signature->param_count; ++i) {
5248 param = (MonoReflectionParameter *)mono_object_new (domain,
5249 System_Reflection_ParameterInfo);
5250 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5251 param->DefaultValueImpl = NULL; /* FIXME */
5252 param->MemberImpl = (MonoObject*)member;
5253 param->NameImpl = mono_string_new (domain, names [i]);
5254 param->PositionImpl = i;
5255 param->AttrsImpl = method->signature->params [i]->attrs;
5256 mono_array_set (res, gpointer, i, param);
5259 CACHE_OBJECT (&(method->signature), res, NULL);
5264 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5268 memset (assembly, 0, sizeof (MonoAssemblyName));
5270 assembly->culture = "";
5271 assembly->public_tok_value = NULL;
5273 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5276 while (*p == ' ' || *p == ',') {
5285 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5287 assembly->major = strtoul (p, &s, 10);
5288 if (s == p || *s != '.')
5291 assembly->minor = strtoul (p, &s, 10);
5292 if (s == p || *s != '.')
5295 assembly->build = strtoul (p, &s, 10);
5296 if (s == p || *s != '.')
5299 assembly->revision = strtoul (p, &s, 10);
5303 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5305 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5306 assembly->culture = "";
5309 assembly->culture = p;
5310 while (*p && *p != ',') {
5314 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5316 if (strncmp (p, "null", 4) == 0) {
5319 assembly->public_tok_value = p;
5320 while (*p && *p != ',') {
5325 while (*p && *p != ',')
5329 while (*p == ' ' || *p == ',') {
5343 * mono_reflection_parse_type:
5346 * Parse a type name as accepted by the GetType () method and output the info
5347 * extracted in the info structure.
5348 * the name param will be mangled, so, make a copy before passing it to this function.
5349 * The fields in info will be valid until the memory pointed to by name is valid.
5350 * Returns 0 on parse error.
5351 * See also mono_type_get_name () below.
5354 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5356 char *start, *p, *w, *last_point, *startn;
5357 int in_modifiers = 0;
5358 int isbyref = 0, rank;
5360 start = p = w = name;
5362 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5363 info->name = info->name_space = NULL;
5364 info->nested = NULL;
5365 info->modifiers = NULL;
5367 /* last_point separates the namespace from the name */
5373 *p = 0; /* NULL terminate the name */
5375 info->nested = g_list_append (info->nested, startn);
5376 /* we have parsed the nesting namespace + name */
5380 info->name_space = start;
5382 info->name = last_point + 1;
5384 info->name_space = (char *)"";
5410 info->name_space = start;
5412 info->name = last_point + 1;
5414 info->name_space = (char *)"";
5421 if (isbyref) /* only one level allowed by the spec */
5424 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5428 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5439 else if (*p != '*') /* '*' means unknown lower bound */
5445 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5457 return 0; /* missing assembly name */
5458 if (!assembly_name_to_aname (&info->assembly, p))
5465 if (info->assembly.name)
5468 *w = 0; /* terminate class name */
5469 if (!info->name || !*info->name)
5471 /* add other consistency checks */
5476 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5483 image = mono_defaults.corlib;
5486 klass = mono_class_from_name_case (image, info->name_space, info->name);
5488 klass = mono_class_from_name (image, info->name_space, info->name);
5491 for (mod = info->nested; mod; mod = mod->next) {
5494 mono_class_init (klass);
5495 nested = klass->nested_classes;
5498 klass = nested->data;
5500 if (g_strcasecmp (klass->name, mod->data) == 0)
5503 if (strcmp (klass->name, mod->data) == 0)
5507 nested = nested->next;
5514 mono_class_init (klass);
5515 for (mod = info->modifiers; mod; mod = mod->next) {
5516 modval = GPOINTER_TO_UINT (mod->data);
5517 if (!modval) { /* byref: must be last modifier */
5518 return &klass->this_arg;
5519 } else if (modval == -1) {
5520 klass = mono_ptr_class_get (&klass->byval_arg);
5521 } else { /* array rank */
5522 klass = mono_array_class_get (klass, modval);
5524 mono_class_init (klass);
5527 return &klass->byval_arg;
5531 * mono_reflection_get_type:
5532 * @image: a metadata context
5533 * @info: type description structure
5534 * @ignorecase: flag for case-insensitive string compares
5536 * Build a MonoType from the type description in @info.
5541 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5544 MonoReflectionAssembly *assembly;
5548 type = mono_reflection_get_type_internal (image, info, ignorecase);
5551 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5554 // Reconstruct the type name
5555 fullName = g_string_new ("");
5556 if (info->name_space && (info->name_space [0] != '\0'))
5557 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5559 g_string_printf (fullName, info->name);
5560 for (mod = info->nested; mod; mod = mod->next)
5561 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5564 mono_domain_try_type_resolve (
5565 mono_domain_get (), fullName->str, NULL);
5566 if (assembly && (!image || (assembly->assembly->image == image))) {
5568 if (assembly->assembly->dynamic) {
5569 /* Enumerate all modules */
5570 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5574 if (abuilder->modules) {
5575 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5576 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5577 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5583 if (!type && abuilder->loaded_modules) {
5584 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5585 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5586 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5593 type = mono_reflection_get_type_internal (assembly->assembly->image,
5596 g_string_free (fullName, TRUE);
5601 * mono_reflection_type_from_name:
5603 * @image: a metadata context (can be NULL).
5605 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5606 * it defaults to get the type from @image or, if @image is NULL or loading
5607 * from it fails, uses corlib.
5611 mono_reflection_type_from_name (char *name, MonoImage *image)
5614 MonoTypeNameParse info;
5615 MonoAssembly *assembly;
5618 /* Make a copy since parse_type modifies its argument */
5619 tmp = g_strdup (name);
5621 /*g_print ("requested type %s\n", str);*/
5622 if (!mono_reflection_parse_type (tmp, &info)) {
5624 g_list_free (info.modifiers);
5625 g_list_free (info.nested);
5629 if (info.assembly.name) {
5630 assembly = mono_assembly_loaded (&info.assembly);
5631 /* do we need to load if it's not already loaded? */
5634 g_list_free (info.modifiers);
5635 g_list_free (info.nested);
5639 image = assembly->image;
5640 } else if (image == NULL) {
5641 image = mono_defaults.corlib;
5644 type = mono_reflection_get_type (image, &info, FALSE);
5645 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5646 image = mono_defaults.corlib;
5647 type = mono_reflection_get_type (image, &info, FALSE);
5651 g_list_free (info.modifiers);
5652 g_list_free (info.nested);
5657 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5659 int slen, type = t->type;
5664 case MONO_TYPE_BOOLEAN: {
5665 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5670 case MONO_TYPE_CHAR:
5672 case MONO_TYPE_I2: {
5673 guint16 *val = g_malloc (sizeof (guint16));
5678 #if SIZEOF_VOID_P == 4
5684 case MONO_TYPE_I4: {
5685 guint32 *val = g_malloc (sizeof (guint32));
5690 #if SIZEOF_VOID_P == 8
5691 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5696 case MONO_TYPE_I8: {
5697 guint64 *val = g_malloc (sizeof (guint64));
5702 case MONO_TYPE_VALUETYPE:
5703 if (t->data.klass->enumtype) {
5704 type = t->data.klass->enum_basetype->type;
5707 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5710 case MONO_TYPE_STRING:
5711 if (*p == (char)0xFF) {
5715 slen = mono_metadata_decode_value (p, &p);
5717 return mono_string_new_len (mono_domain_get (), p, slen);
5718 case MONO_TYPE_CLASS: {
5721 if (*p == (char)0xFF) {
5726 slen = mono_metadata_decode_value (p, &p);
5727 n = g_memdup (p, slen + 1);
5729 t = mono_reflection_type_from_name (n, image);
5731 g_warning ("Cannot load type '%s'", n);
5735 return mono_type_get_object (mono_domain_get (), t);
5739 case MONO_TYPE_OBJECT: {
5742 MonoClass *subc = NULL;
5747 } else if (subt == 0x0E) {
5748 type = MONO_TYPE_STRING;
5750 } else if (subt == 0x55) {
5753 slen = mono_metadata_decode_value (p, &p);
5754 n = g_memdup (p, slen + 1);
5756 t = mono_reflection_type_from_name (n, image);
5758 g_warning ("Cannot load type '%s'", n);
5761 subc = mono_class_from_mono_type (t);
5762 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5763 MonoType simple_type = {{0}};
5764 simple_type.type = subt;
5765 subc = mono_class_from_mono_type (&simple_type);
5767 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5769 val = load_cattr_value (image, &subc->byval_arg, p, end);
5770 obj = mono_object_new (mono_domain_get (), subc);
5771 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5775 case MONO_TYPE_SZARRAY:
5778 guint32 i, alen, basetype;
5781 if (alen == 0xffffffff) {
5785 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5786 basetype = t->data.klass->byval_arg.type;
5791 case MONO_TYPE_BOOLEAN:
5792 for (i=0;i<alen;i++)
5794 MonoBoolean val=*p++;
5795 mono_array_set(arr,MonoBoolean,i,val);
5798 case MONO_TYPE_CHAR:
5801 for (i=0;i<alen;i++)
5803 guint16 val=read16(p);
5804 mono_array_set(arr,guint16,i,val);
5811 for (i=0;i<alen;i++)
5813 guint32 val=read32(p);
5814 mono_array_set(arr,guint32,i,val);
5821 for (i=0;i<alen;i++)
5823 guint64 val=read64(p);
5824 mono_array_set(arr,guint64,i,val);
5828 case MONO_TYPE_CLASS:
5829 case MONO_TYPE_STRING:
5830 for (i = 0; i < alen; i++) {
5831 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5832 mono_array_set (arr, gpointer, i, item);
5836 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5842 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5848 type_is_reference (MonoType *type)
5850 switch (type->type) {
5851 case MONO_TYPE_BOOLEAN:
5852 case MONO_TYPE_CHAR:
5865 case MONO_TYPE_VALUETYPE:
5873 free_param_data (MonoMethodSignature *sig, void **params) {
5875 for (i = 0; i < sig->param_count; ++i) {
5876 if (!type_is_reference (sig->params [i]))
5877 g_free (params [i]);
5882 * Find the method index in the metadata methodDef table.
5883 * Later put these three helper methods in metadata and export them.
5886 find_method_index (MonoMethod *method) {
5887 MonoClass *klass = method->klass;
5890 for (i = 0; i < klass->method.count; ++i) {
5891 if (method == klass->methods [i])
5892 return klass->method.first + 1 + i;
5898 * Find the field index in the metadata FieldDef table.
5901 find_field_index (MonoClass *klass, MonoClassField *field) {
5904 for (i = 0; i < klass->field.count; ++i) {
5905 if (field == &klass->fields [i])
5906 return klass->field.first + 1 + i;
5912 * Find the property index in the metadata Property table.
5915 find_property_index (MonoClass *klass, MonoProperty *property) {
5918 for (i = 0; i < klass->property.count; ++i) {
5919 if (property == &klass->properties [i])
5920 return klass->property.first + 1 + i;
5926 * Find the event index in the metadata Event table.
5929 find_event_index (MonoClass *klass, MonoEvent *event) {
5932 for (i = 0; i < klass->event.count; ++i) {
5933 if (event == &klass->events [i])
5934 return klass->event.first + 1 + i;
5940 create_custom_attr (MonoImage *image, MonoMethod *method,
5941 const char *data, guint32 len)
5943 const char *p = data;
5945 guint32 i, j, num_named;
5949 mono_class_init (method->klass);
5952 attr = mono_object_new (mono_domain_get (), method->klass);
5953 mono_runtime_invoke (method, attr, NULL, NULL);
5957 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5960 /*g_print ("got attr %s\n", method->klass->name);*/
5962 params = g_new (void*, method->signature->param_count);
5966 for (i = 0; i < method->signature->param_count; ++i) {
5967 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5971 attr = mono_object_new (mono_domain_get (), method->klass);
5972 mono_runtime_invoke (method, attr, params, NULL);
5973 free_param_data (method->signature, params);
5975 num_named = read16 (named);
5977 for (j = 0; j < num_named; j++) {
5979 char *name, named_type, data_type;
5980 named_type = *named++;
5981 data_type = *named++; /* type of data */
5982 if (data_type == 0x55) {
5985 type_len = mono_metadata_decode_blob_size (named, &named);
5986 type_name = g_malloc (type_len + 1);
5987 memcpy (type_name, named, type_len);
5988 type_name [type_len] = 0;
5990 /* FIXME: lookup the type and check type consistency */
5993 if (data_type == MONO_TYPE_SZARRAY)
5994 /* The spec does not mention this */
5996 name_len = mono_metadata_decode_blob_size (named, &named);
5997 name = g_malloc (name_len + 1);
5998 memcpy (name, named, name_len);
5999 name [name_len] = 0;
6001 if (named_type == 0x53) {
6002 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6003 void *val = load_cattr_value (image, field->type, named, &named);
6004 mono_field_set_value (attr, field, val);
6005 if (!type_is_reference (field->type))
6007 } else if (named_type == 0x54) {
6010 MonoType *prop_type;
6012 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6013 /* can we have more that 1 arg in a custom attr named property? */
6014 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6015 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6016 mono_property_set_value (prop, attr, pparams, NULL);
6017 if (!type_is_reference (prop_type))
6018 g_free (pparams [0]);
6027 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6034 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6035 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6036 for (i = 0; i < cinfo->num_attrs; ++i) {
6037 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6038 mono_array_set (result, gpointer, i, attr);
6044 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6046 guint32 mtoken, i, len;
6047 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6049 MonoCustomAttrInfo *ainfo;
6050 GList *tmp, *list = NULL;
6053 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6055 i = mono_metadata_custom_attrs_from_index (image, idx);
6059 while (i < ca->rows) {
6060 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6062 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6065 len = g_list_length (list);
6068 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6069 ainfo->num_attrs = len;
6070 ainfo->image = image;
6071 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6072 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6073 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
6074 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
6075 case CUSTOM_ATTR_TYPE_METHODDEF:
6076 mtoken |= MONO_TOKEN_METHOD_DEF;
6078 case CUSTOM_ATTR_TYPE_MEMBERREF:
6079 mtoken |= MONO_TOKEN_MEMBER_REF;
6082 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6085 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6086 if (!ainfo->attrs [i].ctor)
6087 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6088 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6089 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6090 ainfo->attrs [i].data = data;
6098 mono_custom_attrs_from_method (MonoMethod *method)
6100 MonoCustomAttrInfo *cinfo;
6103 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6105 idx = find_method_index (method);
6106 idx <<= CUSTOM_ATTR_BITS;
6107 idx |= CUSTOM_ATTR_METHODDEF;
6108 return mono_custom_attrs_from_index (method->klass->image, idx);
6112 mono_custom_attrs_from_class (MonoClass *klass)
6114 MonoCustomAttrInfo *cinfo;
6117 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6119 idx = mono_metadata_token_index (klass->type_token);
6120 idx <<= CUSTOM_ATTR_BITS;
6121 idx |= CUSTOM_ATTR_TYPEDEF;
6122 return mono_custom_attrs_from_index (klass->image, idx);
6126 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6128 MonoCustomAttrInfo *cinfo;
6131 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6133 idx = 1; /* there is only one assembly */
6134 idx <<= CUSTOM_ATTR_BITS;
6135 idx |= CUSTOM_ATTR_ASSEMBLY;
6136 return mono_custom_attrs_from_index (assembly->image, idx);
6139 static MonoCustomAttrInfo*
6140 mono_custom_attrs_from_module (MonoImage *image)
6142 MonoCustomAttrInfo *cinfo;
6145 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6147 idx = 1; /* there is only one module */
6148 idx <<= CUSTOM_ATTR_BITS;
6149 idx |= CUSTOM_ATTR_MODULE;
6150 return mono_custom_attrs_from_index (image, idx);
6154 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6156 MonoCustomAttrInfo *cinfo;
6159 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6161 idx = find_property_index (klass, property);
6162 idx <<= CUSTOM_ATTR_BITS;
6163 idx |= CUSTOM_ATTR_PROPERTY;
6164 return mono_custom_attrs_from_index (klass->image, idx);
6168 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6170 MonoCustomAttrInfo *cinfo;
6173 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6175 idx = find_event_index (klass, event);
6176 idx <<= CUSTOM_ATTR_BITS;
6177 idx |= CUSTOM_ATTR_EVENT;
6178 return mono_custom_attrs_from_index (klass->image, idx);
6182 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6184 MonoCustomAttrInfo *cinfo;
6187 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6189 idx = find_field_index (klass, field);
6190 idx <<= CUSTOM_ATTR_BITS;
6191 idx |= CUSTOM_ATTR_FIELDDEF;
6192 return mono_custom_attrs_from_index (klass->image, idx);
6196 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6199 guint32 i, idx, method_index;
6200 guint32 param_list, param_last, param_pos, found;
6202 MonoReflectionMethodAux *aux;
6204 if (method->klass->image->dynamic) {
6205 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6206 if (!aux || !aux->param_cattr)
6208 return aux->param_cattr [param];
6211 image = method->klass->image;
6212 method_index = find_method_index (method);
6213 ca = &image->tables [MONO_TABLE_METHOD];
6215 if (method->klass->generic_inst || method->klass->gen_params ||
6216 method->signature->generic_param_count) {
6217 // FIXME FIXME FIXME
6221 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6222 if (method_index == ca->rows) {
6223 ca = &image->tables [MONO_TABLE_PARAM];
6224 param_last = ca->rows + 1;
6226 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6227 ca = &image->tables [MONO_TABLE_PARAM];
6230 for (i = param_list; i < param_last; ++i) {
6231 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6232 if (param_pos == param) {
6240 idx <<= CUSTOM_ATTR_BITS;
6241 idx |= CUSTOM_ATTR_PARAMDEF;
6242 return mono_custom_attrs_from_index (image, idx);
6246 * mono_reflection_get_custom_attrs:
6247 * @obj: a reflection object handle
6249 * Return an array with all the custom attributes defined of the
6250 * reflection handle @obj. The objects are fully build.
6253 mono_reflection_get_custom_attrs (MonoObject *obj)
6257 MonoCustomAttrInfo *cinfo = NULL;
6259 MONO_ARCH_SAVE_REGS;
6261 klass = obj->vtable->klass;
6262 /* FIXME: need to handle: Module */
6263 if (klass == mono_defaults.monotype_class) {
6264 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6265 klass = mono_class_from_mono_type (rtype->type);
6266 cinfo = mono_custom_attrs_from_class (klass);
6267 } else if (strcmp ("Assembly", klass->name) == 0) {
6268 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6269 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6270 } else if (strcmp ("Module", klass->name) == 0) {
6271 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6272 cinfo = mono_custom_attrs_from_module (module->image);
6273 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6274 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6275 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6276 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6277 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6278 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6279 } else if (strcmp ("MonoField", klass->name) == 0) {
6280 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6281 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6282 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6283 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6284 cinfo = mono_custom_attrs_from_method (rmethod->method);
6285 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6286 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6287 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6288 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6289 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6290 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6291 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6292 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6293 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6294 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6295 } else { /* handle other types here... */
6296 g_error ("get custom attrs not yet supported for %s", klass->name);
6300 result = mono_custom_attrs_construct (cinfo);
6302 mono_custom_attrs_free (cinfo);
6304 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6305 result = mono_array_new (mono_domain_get (), klass, 0);
6311 static MonoMethodSignature*
6312 parameters_to_signature (MonoArray *parameters) {
6313 MonoMethodSignature *sig;
6316 count = parameters? mono_array_length (parameters): 0;
6318 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6319 sig->param_count = count;
6320 sig->sentinelpos = -1; /* FIXME */
6321 for (i = 0; i < count; ++i) {
6322 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6323 sig->params [i] = pt->type;
6328 static MonoMethodSignature*
6329 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6330 MonoMethodSignature *sig;
6332 sig = parameters_to_signature (ctor->parameters);
6333 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6334 sig->ret = &mono_defaults.void_class->byval_arg;
6338 static MonoMethodSignature*
6339 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6340 MonoMethodSignature *sig;
6342 sig = parameters_to_signature (method->parameters);
6343 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6344 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6345 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6349 static MonoMethodSignature*
6350 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6351 MonoMethodSignature *sig;
6353 sig = parameters_to_signature (method->parameters);
6354 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6355 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6356 sig->generic_param_count = 0;
6361 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6363 MonoClass *klass = mono_object_class (prop);
6364 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6365 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6366 *name = mono_string_to_utf8 (pb->name);
6367 *type = pb->type->type;
6369 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6370 *name = g_strdup (p->property->name);
6371 if (p->property->get)
6372 *type = p->property->get->signature->ret;
6374 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6379 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6381 MonoClass *klass = mono_object_class (field);
6382 if (strcmp (klass->name, "FieldBuilder") == 0) {
6383 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6384 *name = mono_string_to_utf8 (fb->name);
6385 *type = fb->type->type;
6387 MonoReflectionField *f = (MonoReflectionField *)field;
6388 *name = g_strdup (f->field->name);
6389 *type = f->field->type;
6394 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6397 MonoTypeEnum simple_type;
6399 if ((p-buffer) + 10 >= *buflen) {
6402 newbuf = g_realloc (buffer, *buflen);
6403 p = newbuf + (p-buffer);
6406 argval = ((char*)arg + sizeof (MonoObject));
6407 simple_type = type->type;
6409 switch (simple_type) {
6410 case MONO_TYPE_BOOLEAN:
6415 case MONO_TYPE_CHAR:
6418 swap_with_size (p, argval, 2, 1);
6424 swap_with_size (p, argval, 4, 1);
6430 swap_with_size (p, argval, 8, 1);
6433 case MONO_TYPE_VALUETYPE:
6434 if (type->data.klass->enumtype) {
6435 simple_type = type->data.klass->enum_basetype->type;
6438 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6441 case MONO_TYPE_STRING: {
6448 str = mono_string_to_utf8 ((MonoString*)arg);
6449 slen = strlen (str);
6450 if ((p-buffer) + 10 + slen >= *buflen) {
6454 newbuf = g_realloc (buffer, *buflen);
6455 p = newbuf + (p-buffer);
6458 mono_metadata_encode_value (slen, p, &p);
6459 memcpy (p, str, slen);
6464 case MONO_TYPE_CLASS: {
6472 k = mono_object_class (arg);
6473 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6474 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6475 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6477 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6478 slen = strlen (str);
6479 if ((p-buffer) + 10 + slen >= *buflen) {
6483 newbuf = g_realloc (buffer, *buflen);
6484 p = newbuf + (p-buffer);
6487 mono_metadata_encode_value (slen, p, &p);
6488 memcpy (p, str, slen);
6493 case MONO_TYPE_SZARRAY: {
6498 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6501 len = mono_array_length ((MonoArray*)arg);
6503 *p++ = (len >> 8) & 0xff;
6504 *p++ = (len >> 16) & 0xff;
6505 *p++ = (len >> 24) & 0xff;
6507 *retbuffer = buffer;
6508 eclass = type->data.klass;
6509 for (i = 0; i < len; ++i) {
6510 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6514 /* it may be a boxed value or a Type */
6515 case MONO_TYPE_OBJECT: {
6516 MonoClass *klass = mono_object_class (arg);
6520 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6523 } else if (klass->enumtype) {
6525 } else if (klass == mono_defaults.string_class) {
6526 simple_type = MONO_TYPE_STRING;
6529 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6530 *p++ = simple_type = klass->byval_arg.type;
6533 g_error ("unhandled type in custom attr");
6535 str = type_get_qualified_name (klass->enum_basetype, NULL);
6536 slen = strlen (str);
6537 if ((p-buffer) + 10 + slen >= *buflen) {
6541 newbuf = g_realloc (buffer, *buflen);
6542 p = newbuf + (p-buffer);
6545 mono_metadata_encode_value (slen, p, &p);
6546 memcpy (p, str, slen);
6549 simple_type = klass->enum_basetype->type;
6553 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6556 *retbuffer = buffer;
6560 * mono_reflection_get_custom_attrs_blob:
6561 * @ctor: custom attribute constructor
6562 * @ctorArgs: arguments o the constructor
6568 * Creates the blob of data that needs to be saved in the metadata and that represents
6569 * the custom attributed described by @ctor, @ctorArgs etc.
6570 * Returns: a Byte array representing the blob of data.
6573 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6576 MonoMethodSignature *sig;
6581 MONO_ARCH_SAVE_REGS;
6583 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6584 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6586 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6588 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6590 p = buffer = g_malloc (buflen);
6591 /* write the prolog */
6594 for (i = 0; i < sig->param_count; ++i) {
6595 arg = mono_array_get (ctorArgs, MonoObject*, i);
6596 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6600 i += mono_array_length (properties);
6602 i += mono_array_length (fields);
6604 *p++ = (i >> 8) & 0xff;
6607 for (i = 0; i < mono_array_length (properties); ++i) {
6612 prop = mono_array_get (properties, gpointer, i);
6613 get_prop_name_and_type (prop, &pname, &ptype);
6614 *p++ = 0x54; /* PROPERTY signature */
6616 /* Preallocate a large enough buffer */
6617 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6618 char *str = type_get_qualified_name (ptype, NULL);
6624 len += strlen (pname);
6626 if ((p-buffer) + 20 + len >= buflen) {
6630 newbuf = g_realloc (buffer, buflen);
6631 p = newbuf + (p-buffer);
6635 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6636 char *str = type_get_qualified_name (ptype, NULL);
6637 int slen = strlen (str);
6641 * This seems to be optional...
6644 mono_metadata_encode_value (slen, p, &p);
6645 memcpy (p, str, slen);
6649 mono_metadata_encode_value (ptype->type, p, &p);
6650 if (ptype->type == MONO_TYPE_SZARRAY)
6651 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6653 len = strlen (pname);
6654 mono_metadata_encode_value (len, p, &p);
6655 memcpy (p, pname, len);
6657 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6664 for (i = 0; i < mono_array_length (fields); ++i) {
6669 field = mono_array_get (fields, gpointer, i);
6670 get_field_name_and_type (field, &fname, &ftype);
6671 *p++ = 0x53; /* FIELD signature */
6672 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6673 char *str = type_get_qualified_name (ftype, NULL);
6674 int slen = strlen (str);
6675 if ((p-buffer) + 10 + slen >= buflen) {
6679 newbuf = g_realloc (buffer, buflen);
6680 p = newbuf + (p-buffer);
6685 * This seems to be optional...
6688 mono_metadata_encode_value (slen, p, &p);
6689 memcpy (p, str, slen);
6693 mono_metadata_encode_value (ftype->type, p, &p);
6695 len = strlen (fname);
6696 mono_metadata_encode_value (len, p, &p);
6697 memcpy (p, fname, len);
6699 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6704 g_assert (p - buffer <= buflen);
6705 buflen = p - buffer;
6706 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6707 p = mono_array_addr (result, char, 0);
6708 memcpy (p, buffer, buflen);
6710 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6716 * mono_reflection_setup_internal_class:
6717 * @tb: a TypeBuilder object
6719 * Creates a MonoClass that represents the TypeBuilder.
6720 * This is a trick that lets us simplify a lot of reflection code
6721 * (and will allow us to support Build and Run assemblies easier).
6724 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6726 MonoClass *klass, *parent;
6728 MONO_ARCH_SAVE_REGS;
6730 klass = g_new0 (MonoClass, 1);
6732 klass->image = &tb->module->dynamic_image->image;
6735 /* check so we can compile corlib correctly */
6736 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6737 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6738 parent = tb->parent->type->data.klass;
6740 parent = my_mono_class_from_mono_type (tb->parent->type);
6744 klass->inited = 1; /* we lie to the runtime */
6745 klass->name = mono_string_to_utf8 (tb->name);
6746 klass->name_space = mono_string_to_utf8 (tb->nspace);
6747 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6748 klass->flags = tb->attrs;
6750 klass->element_class = klass;
6751 klass->reflection_info = tb; /* need to pin. */
6753 /* Put into cache so mono_class_get () will find it */
6754 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6757 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6758 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6762 mono_class_setup_parent (klass, parent);
6763 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6764 const char *old_n = klass->name;
6765 /* trick to get relative numbering right when compiling corlib */
6766 klass->name = "BuildingObject";
6767 mono_class_setup_parent (klass, mono_defaults.object_class);
6768 klass->name = old_n;
6770 mono_class_setup_mono_type (klass);
6772 mono_class_setup_supertypes (klass);
6775 * FIXME: handle interfaces.
6778 tb->type.type = &klass->byval_arg;
6780 if (tb->nesting_type) {
6781 g_assert (tb->nesting_type->type);
6782 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6785 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6789 * mono_reflection_setup_generic_class:
6790 * @tb: a TypeBuilder object
6792 * Setup the generic class after all generic parameters have been added.
6795 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6800 MONO_ARCH_SAVE_REGS;
6802 klass = my_mono_class_from_mono_type (tb->type.type);
6804 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6806 if (klass->gen_params || (count == 0))
6809 klass->num_gen_params = count;
6810 klass->gen_params = g_new0 (MonoGenericParam, count);
6812 for (i = 0; i < count; i++) {
6813 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6814 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6819 * mono_reflection_create_internal_class:
6820 * @tb: a TypeBuilder object
6822 * Actually create the MonoClass that is associated with the TypeBuilder.
6825 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6829 MONO_ARCH_SAVE_REGS;
6831 klass = my_mono_class_from_mono_type (tb->type.type);
6833 if (klass->enumtype && klass->enum_basetype == NULL) {
6834 MonoReflectionFieldBuilder *fb;
6836 g_assert (tb->fields != NULL);
6837 g_assert (mono_array_length (tb->fields) >= 1);
6839 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6841 klass->enum_basetype = fb->type->type;
6842 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6843 if (!klass->element_class)
6844 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6845 klass->instance_size = klass->element_class->instance_size;
6846 klass->size_inited = 1;
6848 * this is almost safe to do with enums and it's needed to be able
6849 * to create objects of the enum type (for use in SetConstant).
6851 /* FIXME: Does this mean enums can't have method overrides ? */
6852 mono_class_setup_vtable (klass, NULL, 0);
6856 static MonoMarshalSpec*
6857 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6858 MonoReflectionMarshal *minfo)
6860 MonoMarshalSpec *res;
6862 res = g_new0 (MonoMarshalSpec, 1);
6863 res->native = minfo->type;
6865 switch (minfo->type) {
6866 case MONO_NATIVE_LPARRAY:
6867 res->data.array_data.elem_type = minfo->eltype;
6868 res->data.array_data.param_num = 0; /* Not yet */
6869 res->data.array_data.num_elem = minfo->count;
6872 case MONO_NATIVE_BYVALTSTR:
6873 case MONO_NATIVE_BYVALARRAY:
6874 res->data.array_data.num_elem = minfo->count;
6877 case MONO_NATIVE_CUSTOM:
6878 if (minfo->marshaltyperef)
6879 res->data.custom_data.custom_name =
6880 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6882 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6893 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6894 ReflectionMethodBuilder *rmb,
6895 MonoMethodSignature *sig)
6898 MonoMethodNormal *pm;
6899 MonoMarshalSpec **specs;
6900 MonoReflectionMethodAux *method_aux;
6903 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6904 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6905 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6908 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6910 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6912 pm = (MonoMethodNormal*)m;
6915 m->flags = rmb->attrs;
6916 m->iflags = rmb->iattrs;
6917 m->name = mono_string_to_utf8 (rmb->name);
6921 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6923 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6924 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6927 m->signature->pinvoke = 1;
6928 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6930 m->signature->pinvoke = 1;
6932 } else if (!m->klass->dummy &&
6933 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6934 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6935 MonoMethodHeader *header;
6937 gint32 max_stack, i;
6938 gint32 num_locals = 0;
6939 gint32 num_clauses = 0;
6943 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6944 code_size = rmb->ilgen->code_len;
6945 max_stack = rmb->ilgen->max_stack;
6946 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6947 if (rmb->ilgen->ex_handlers)
6948 num_clauses = method_count_clauses (rmb->ilgen);
6951 code = mono_array_addr (rmb->code, guint8, 0);
6952 code_size = mono_array_length (rmb->code);
6953 /* we probably need to run a verifier on the code... */
6963 header = g_malloc0 (sizeof (MonoMethodHeader) +
6964 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6965 header->code_size = code_size;
6966 header->code = g_malloc (code_size);
6967 memcpy ((char*)header->code, code, code_size);
6968 header->max_stack = max_stack;
6969 header->init_locals = rmb->init_locals;
6970 header->num_locals = num_locals;
6972 for (i = 0; i < num_locals; ++i) {
6973 MonoReflectionLocalBuilder *lb =
6974 mono_array_get (rmb->ilgen->locals,
6975 MonoReflectionLocalBuilder*, i);
6977 header->locals [i] = g_new0 (MonoType, 1);
6978 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6981 header->num_clauses = num_clauses;
6983 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6988 if (rmb->generic_params) {
6989 int count = mono_array_length (rmb->generic_params);
6990 header->gen_params = g_new0 (MonoGenericParam, count);
6991 for (i = 0; i < count; i++) {
6992 MonoReflectionGenericParam *gp =
6993 mono_array_get (rmb->generic_params,
6994 MonoReflectionGenericParam*, i);
6996 header->gen_params [i] = *gp->type.type->data.generic_param;
7000 pm->header = header;
7004 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7007 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7009 for (i = 0; i < rmb->nrefs; ++i)
7010 mw->data = g_list_append (mw->data, rmb->refs [i]);
7015 /* Parameter names */
7018 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7019 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7020 for (i = 0; i <= m->signature->param_count; ++i) {
7021 MonoReflectionParamBuilder *pb;
7022 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7024 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7026 if (!method_aux->param_cattr)
7027 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7028 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7034 /* Parameter marshalling */
7037 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7038 MonoReflectionParamBuilder *pb;
7039 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7040 if (pb->marshal_info) {
7042 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7043 specs [pb->position] =
7044 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7048 if (specs != NULL) {
7050 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7051 method_aux->param_marshall = specs;
7054 if (klass->image->dynamic && method_aux)
7055 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7061 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7063 ReflectionMethodBuilder rmb;
7064 MonoMethodSignature *sig;
7066 sig = ctor_builder_to_signature (mb);
7068 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7070 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7071 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7073 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7074 /* ilgen is no longer needed */
7082 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7084 ReflectionMethodBuilder rmb;
7085 MonoMethodSignature *sig;
7087 sig = method_builder_to_signature (mb);
7089 reflection_methodbuilder_from_method_builder (&rmb, mb);
7091 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7092 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7094 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7095 /* ilgen is no longer needed */
7101 static MonoClassField*
7102 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7104 MonoClassField *field;
7111 field = g_new0 (MonoClassField, 1);
7113 field->name = mono_string_to_utf8 (fb->name);
7115 /* FIXME: handle type modifiers */
7116 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7117 field->type->attrs = fb->attrs;
7119 field->type = fb->type->type;
7121 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7122 field->data = mono_array_addr (fb->rva_data, char, 0);
7123 if (fb->offset != -1)
7124 field->offset = fb->offset;
7125 field->parent = klass;
7127 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7129 if (fb->def_value) {
7130 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7131 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7132 field->def_value = g_new0 (MonoConstant, 1);
7133 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7134 /* Copy the data from the blob since it might get realloc-ed */
7135 p = assembly->blob.data + idx;
7136 len = mono_metadata_decode_blob_size (p, &p2);
7138 field->def_value->value = g_malloc (len);
7139 memcpy (field->def_value->value, p, len);
7146 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7150 MonoReflectionTypeBuilder *tb = NULL;
7151 MonoGenericInst *ginst;
7156 klass = mono_class_from_mono_type (type->type);
7157 if (!klass->gen_params && !klass->generic_inst &&
7158 !(klass->nested_in && klass->nested_in->gen_params))
7161 mono_loader_lock ();
7163 domain = mono_object_domain (type);
7165 ginst = g_new0 (MonoGenericInst, 1);
7167 if (!klass->generic_inst) {
7168 ginst->type_argc = type_argc;
7169 ginst->type_argv = types;
7171 for (i = 0; i < ginst->type_argc; ++i) {
7172 if (!ginst->is_open)
7173 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7176 ginst->generic_type = &klass->byval_arg;
7178 MonoGenericInst *kginst = klass->generic_inst;
7180 ginst->type_argc = kginst->type_argc;
7181 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7183 for (i = 0; i < ginst->type_argc; i++) {
7184 MonoType *t = kginst->type_argv [i];
7186 if (t->type == MONO_TYPE_VAR)
7187 t = types [t->data.generic_param->num];
7189 if (!ginst->is_open)
7190 ginst->is_open = mono_class_is_open_constructed_type (t);
7192 ginst->type_argv [i] = t;
7195 ginst->generic_type = kginst->generic_type;
7198 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7201 mono_loader_unlock ();
7205 ginst->context = g_new0 (MonoGenericContext, 1);
7206 ginst->context->ginst = ginst;
7208 geninst = g_new0 (MonoType, 1);
7209 geninst->type = MONO_TYPE_GENERICINST;
7210 geninst->data.generic_inst = ginst;
7212 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7213 tb = (MonoReflectionTypeBuilder *) type;
7215 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7216 ginst->is_dynamic = TRUE;
7217 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7218 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7219 MonoReflectionType *rgt = rgi->generic_type;
7221 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7222 tb = (MonoReflectionTypeBuilder *) rgt;
7224 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7225 ginst->is_dynamic = TRUE;
7227 icount = klass->interface_count;
7229 ginst->ifaces = g_new0 (MonoType *, icount);
7230 ginst->count_ifaces = icount;
7232 for (i = 0; i < icount; i++) {
7233 MonoReflectionType *itype;
7236 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7238 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7239 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7240 if (!ginst->ifaces [i])
7241 ginst->ifaces [i] = itype->type;
7244 mono_class_create_generic (ginst);
7246 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7248 mono_loader_unlock ();
7254 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7256 MonoClass *klass, *pklass = NULL;
7257 MonoReflectionType *parent = NULL;
7259 MonoReflectionTypeBuilder *tb = NULL;
7260 MonoGenericInst *ginst;
7263 domain = mono_object_domain (type);
7264 klass = mono_class_from_mono_type (type->type);
7266 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7267 tb = (MonoReflectionTypeBuilder *) type;
7270 parent = tb->parent;
7271 pklass = mono_class_from_mono_type (parent->type);
7274 pklass = klass->parent;
7276 parent = mono_type_get_object (domain, &pklass->byval_arg);
7279 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7283 ginst = geninst->data.generic_inst;
7285 if (pklass && pklass->generic_inst)
7286 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7291 MonoReflectionMethod*
7292 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7294 MonoMethod *method, *inflated;
7295 MonoReflectionMethodBuilder *mb = NULL;
7296 MonoGenericMethod *gmethod;
7297 MonoGenericContext *context;
7300 MONO_ARCH_SAVE_REGS;
7301 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7302 MonoReflectionTypeBuilder *tb;
7305 mb = (MonoReflectionMethodBuilder *) rmethod;
7306 tb = (MonoReflectionTypeBuilder *) mb->type;
7307 klass = mono_class_from_mono_type (tb->type.type);
7309 method = methodbuilder_to_mono_method (klass, mb);
7311 method = rmethod->method;
7313 count = method->signature->generic_param_count;
7314 if (count != mono_array_length (types))
7317 gmethod = g_new0 (MonoGenericMethod, 1);
7318 gmethod->mtype_argc = count;
7319 gmethod->mtype_argv = g_new0 (MonoType *, count);
7320 for (i = 0; i < count; i++) {
7321 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7322 gmethod->mtype_argv [i] = garg->type;
7325 context = g_new0 (MonoGenericContext, 1);
7326 context->ginst = method->klass->generic_inst;
7327 context->gmethod = gmethod;
7329 inflated = mono_class_inflate_generic_method (method, context, NULL);
7331 return mono_method_get_object (
7332 mono_object_domain (rmethod), inflated, NULL);
7336 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7338 MonoGenericMethod *gmethod;
7339 MonoGenericInst *ginst;
7340 MonoGenericContext *context;
7343 ginst = type->type.type->data.generic_inst;
7345 gmethod = g_new0 (MonoGenericMethod, 1);
7346 gmethod->reflection_info = obj;
7348 gmethod->mtype_argc = method->signature->generic_param_count;
7349 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7351 for (i = 0; i < gmethod->mtype_argc; i++) {
7352 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7353 MonoGenericParam *gparam = &mn->header->gen_params [i];
7355 g_assert (gparam->pklass);
7356 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7359 context = g_new0 (MonoGenericContext, 1);
7360 context->ginst = ginst;
7361 context->gmethod = gmethod;
7363 return mono_class_inflate_generic_method (method, context, ginst->klass);
7367 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7372 klass = mono_class_from_mono_type (type->type.type);
7374 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7375 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7376 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7377 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7378 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7379 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7380 method = ((MonoReflectionMethod *) obj)->method;
7382 method = NULL; /* prevent compiler warning */
7383 g_assert_not_reached ();
7386 return inflate_mono_method (type, method, obj);
7390 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7391 MonoArray *methods, MonoArray *ctors,
7392 MonoArray *fields, MonoArray *properties,
7395 MonoGenericInst *ginst;
7396 MonoDynamicGenericInst *dginst;
7397 MonoClass *klass, *gklass, *pklass;
7400 MONO_ARCH_SAVE_REGS;
7402 klass = mono_class_from_mono_type (type->type.type);
7403 ginst = type->type.type->data.generic_inst;
7405 if (ginst->initialized)
7408 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7410 gklass = mono_class_from_mono_type (ginst->generic_type);
7411 mono_class_init (gklass);
7414 pklass = mono_class_from_mono_type (ginst->parent);
7416 pklass = gklass->parent;
7418 mono_class_setup_parent (klass, pklass);
7420 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7421 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7422 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7423 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7424 dginst->count_events = events ? mono_array_length (events) : 0;
7426 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7427 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7428 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7429 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7430 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7432 for (i = 0; i < dginst->count_methods; i++) {
7433 MonoObject *obj = mono_array_get (methods, gpointer, i);
7435 dginst->methods [i] = inflate_method (type, obj);
7438 for (i = 0; i < dginst->count_ctors; i++) {
7439 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7441 dginst->ctors [i] = inflate_method (type, obj);
7444 for (i = 0; i < dginst->count_fields; i++) {
7445 MonoObject *obj = mono_array_get (fields, gpointer, i);
7446 MonoClassField *field;
7447 MonoInflatedField *ifield;
7449 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7450 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7451 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7452 field = ((MonoReflectionField *) obj)->field;
7454 field = NULL; /* prevent compiler warning */
7455 g_assert_not_reached ();
7458 ifield = g_new0 (MonoInflatedField, 1);
7459 ifield->generic_type = field->type;
7460 ifield->reflection_info = obj;
7462 dginst->fields [i] = *field;
7463 dginst->fields [i].generic_info = ifield;
7464 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7467 for (i = 0; i < dginst->count_properties; i++) {
7468 MonoObject *obj = mono_array_get (properties, gpointer, i);
7469 MonoProperty *property = &dginst->properties [i];
7471 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7472 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7474 property->parent = klass;
7475 property->attrs = pb->attrs;
7476 property->name = mono_string_to_utf8 (pb->name);
7478 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7480 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7481 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7482 *property = *((MonoReflectionProperty *) obj)->property;
7485 property->get = inflate_mono_method (type, property->get, NULL);
7487 property->set = inflate_mono_method (type, property->set, NULL);
7489 g_assert_not_reached ();
7492 for (i = 0; i < dginst->count_events; i++) {
7493 MonoObject *obj = mono_array_get (events, gpointer, i);
7494 MonoEvent *event = &dginst->events [i];
7496 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7497 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7499 event->parent = klass;
7500 event->attrs = eb->attrs;
7501 event->name = mono_string_to_utf8 (eb->name);
7503 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7504 if (eb->remove_method)
7505 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7506 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7507 *event = *((MonoReflectionEvent *) obj)->event;
7510 event->add = inflate_mono_method (type, event->add, NULL);
7512 event->remove = inflate_mono_method (type, event->remove, NULL);
7514 g_assert_not_reached ();
7517 ginst->initialized = TRUE;
7521 ensure_runtime_vtable (MonoClass *klass)
7523 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7524 int i, num, j, onum;
7525 MonoMethod **overrides;
7527 if (!tb || klass->wastypebuilder)
7530 ensure_runtime_vtable (klass->parent);
7532 num = tb->ctors? mono_array_length (tb->ctors): 0;
7533 num += tb->num_methods;
7534 klass->method.count = num;
7535 klass->methods = g_new (MonoMethod*, num);
7536 num = tb->ctors? mono_array_length (tb->ctors): 0;
7537 for (i = 0; i < num; ++i)
7538 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7539 num = tb->num_methods;
7541 for (i = 0; i < num; ++i)
7542 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7544 klass->wastypebuilder = TRUE;
7545 if (tb->interfaces) {
7546 klass->interface_count = mono_array_length (tb->interfaces);
7547 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7548 for (i = 0; i < klass->interface_count; ++i) {
7549 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7550 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7554 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7555 for (i = 0; i < klass->method.count; ++i)
7556 klass->methods [i]->slot = i;
7561 for (i = 0; i < tb->num_methods; ++i) {
7562 MonoReflectionMethodBuilder *mb =
7563 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7564 if (mb->override_method)
7569 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7573 for (i = 0; i < tb->num_methods; ++i) {
7574 MonoReflectionMethodBuilder *mb =
7575 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7576 if (mb->override_method) {
7577 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7578 overrides [onum * 2] =
7579 mb->override_method->method;
7580 overrides [onum * 2 + 1] =
7583 g_assert (mb->mhandle);
7590 mono_class_setup_vtable (klass, overrides, onum);
7594 typebuilder_setup_fields (MonoClass *klass)
7596 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7597 MonoReflectionFieldBuilder *fb;
7598 MonoClassField *field;
7603 klass->field.count = tb->num_fields;
7604 klass->field.first = 0;
7605 klass->field.last = klass->field.count;
7607 if (!klass->field.count)
7610 klass->fields = g_new0 (MonoClassField, klass->field.count);
7612 for (i = 0; i < klass->field.count; ++i) {
7613 fb = mono_array_get (tb->fields, gpointer, i);
7614 field = &klass->fields [i];
7615 field->name = mono_string_to_utf8 (fb->name);
7617 /* FIXME: handle type modifiers */
7618 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7619 field->type->attrs = fb->attrs;
7621 field->type = fb->type->type;
7623 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7624 field->data = mono_array_addr (fb->rva_data, char, 0);
7625 if (fb->offset != -1)
7626 field->offset = fb->offset;
7627 field->parent = klass;
7629 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7631 if (fb->def_value) {
7632 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7633 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7634 field->def_value = g_new0 (MonoConstant, 1);
7635 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7636 /* Copy the data from the blob since it might get realloc-ed */
7637 p = assembly->blob.data + idx;
7638 len = mono_metadata_decode_blob_size (p, &p2);
7640 field->def_value->value = g_malloc (len);
7641 memcpy (field->def_value->value, p, len);
7644 mono_class_layout_fields (klass);
7648 typebuilder_setup_properties (MonoClass *klass)
7650 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7651 MonoReflectionPropertyBuilder *pb;
7654 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7655 klass->property.first = 0;
7656 klass->property.last = klass->property.count;
7658 klass->properties = g_new0 (MonoProperty, klass->property.count);
7659 for (i = 0; i < klass->property.count; ++i) {
7660 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7661 klass->properties [i].parent = klass;
7662 klass->properties [i].attrs = pb->attrs;
7663 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7665 klass->properties [i].get = pb->get_method->mhandle;
7667 klass->properties [i].set = pb->set_method->mhandle;
7671 MonoReflectionEvent *
7672 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7674 MonoEvent *event = g_new0 (MonoEvent, 1);
7678 klass = my_mono_class_from_mono_type (tb->type.type);
7680 event->parent = klass;
7681 event->attrs = eb->attrs;
7682 event->name = mono_string_to_utf8 (eb->name);
7684 event->add = eb->add_method->mhandle;
7685 if (eb->remove_method)
7686 event->remove = eb->remove_method->mhandle;
7687 if (eb->raise_method)
7688 event->raise = eb->raise_method->mhandle;
7690 if (eb->other_methods) {
7691 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7692 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7693 MonoReflectionMethodBuilder *mb =
7694 mono_array_get (eb->other_methods,
7695 MonoReflectionMethodBuilder*, j);
7696 event->other [j] = mb->mhandle;
7700 return mono_event_get_object (mono_object_domain (tb), klass, event);
7704 typebuilder_setup_events (MonoClass *klass)
7706 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7707 MonoReflectionEventBuilder *eb;
7710 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7711 klass->event.first = 0;
7712 klass->event.last = klass->event.count;
7714 klass->events = g_new0 (MonoEvent, klass->event.count);
7715 for (i = 0; i < klass->event.count; ++i) {
7716 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7717 klass->events [i].parent = klass;
7718 klass->events [i].attrs = eb->attrs;
7719 klass->events [i].name = mono_string_to_utf8 (eb->name);
7721 klass->events [i].add = eb->add_method->mhandle;
7722 if (eb->remove_method)
7723 klass->events [i].remove = eb->remove_method->mhandle;
7724 if (eb->raise_method)
7725 klass->events [i].raise = eb->raise_method->mhandle;
7727 if (eb->other_methods) {
7728 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7729 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7730 MonoReflectionMethodBuilder *mb =
7731 mono_array_get (eb->other_methods,
7732 MonoReflectionMethodBuilder*, j);
7733 klass->events [i].other [j] = mb->mhandle;
7740 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7743 MonoReflectionType* res;
7745 MONO_ARCH_SAVE_REGS;
7747 klass = my_mono_class_from_mono_type (tb->type.type);
7749 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7752 * Fields to set in klass:
7753 * the various flags: delegate/unicode/contextbound etc.
7756 klass->flags = tb->attrs;
7758 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7759 /* No need to fully construct the type */
7760 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7762 /* enums are done right away */
7763 if (!klass->enumtype)
7764 ensure_runtime_vtable (klass);
7766 /* fields and object layout */
7767 if (klass->parent) {
7768 if (!klass->parent->size_inited)
7769 mono_class_init (klass->parent);
7770 klass->instance_size += klass->parent->instance_size;
7771 klass->class_size += klass->parent->class_size;
7772 klass->min_align = klass->parent->min_align;
7774 klass->instance_size = sizeof (MonoObject);
7775 klass->min_align = 1;
7778 /* FIXME: handle packing_size and instance_size */
7779 typebuilder_setup_fields (klass);
7781 typebuilder_setup_properties (klass);
7783 typebuilder_setup_events (klass);
7785 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7786 /* with enums res == tb: need to fix that. */
7787 if (!klass->enumtype)
7788 g_assert (res != (MonoReflectionType*)tb);
7793 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7795 MonoGenericParam *param;
7798 MONO_ARCH_SAVE_REGS;
7800 param = g_new0 (MonoGenericParam, 1);
7802 param->method = NULL;
7803 param->name = mono_string_to_utf8 (gparam->name);
7804 param->num = gparam->index;
7806 image = &gparam->tbuilder->module->dynamic_image->image;
7807 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7809 param->pklass->reflection_info = gparam;
7811 gparam->type.type = g_new0 (MonoType, 1);
7812 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7813 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7814 gparam->type.type->data.generic_param = param;
7818 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7820 MonoDynamicImage *assembly = sig->module->dynamic_image;
7821 guint32 na = mono_array_length (sig->arguments);
7826 MONO_ARCH_SAVE_REGS;
7828 p = buf = g_malloc (10 + na * 10);
7830 mono_metadata_encode_value (0x07, p, &p);
7831 mono_metadata_encode_value (na, p, &p);
7832 for (i = 0; i < na; ++i) {
7833 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7834 encode_reflection_type (assembly, type, p, &p);
7838 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7839 p = mono_array_addr (result, char, 0);
7840 memcpy (p, buf, buflen);
7847 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7849 MonoDynamicImage *assembly = sig->module->dynamic_image;
7850 guint32 na = mono_array_length (sig->arguments);
7855 MONO_ARCH_SAVE_REGS;
7857 p = buf = g_malloc (10 + na * 10);
7859 mono_metadata_encode_value (0x06, p, &p);
7860 for (i = 0; i < na; ++i) {
7861 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7862 encode_reflection_type (assembly, type, p, &p);
7866 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7867 p = mono_array_addr (result, char, 0);
7868 memcpy (p, buf, buflen);
7875 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7877 ReflectionMethodBuilder rmb;
7878 MonoMethodSignature *sig;
7881 sig = dynamic_method_to_signature (mb);
7883 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7886 * Resolve references.
7888 rmb.nrefs = mb->nrefs;
7889 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7890 for (i = 0; i < mb->nrefs; ++i) {
7891 gpointer ref = resolve_object (mb->module->image,
7892 mono_array_get (mb->refs, MonoObject*, i));
7895 mono_raise_exception (mono_get_exception_type_load (NULL));
7902 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7906 /* ilgen is no longer needed */
7911 * mono_reflection_lookup_dynamic_token:
7913 * Finish the Builder object pointed to by TOKEN and return the corresponding
7914 * runtime structure.
7917 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7919 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7922 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7925 return resolve_object (image, obj);
7929 resolve_object (MonoImage *image, MonoObject *obj)
7931 gpointer result = NULL;
7933 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7934 result = mono_string_intern ((MonoString*)obj);
7937 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7938 MonoReflectionType *tb = (MonoReflectionType*)obj;
7939 result = mono_class_from_mono_type (tb->type);
7942 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7943 result = ((MonoReflectionMethod*)obj)->method;
7946 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7947 result = ((MonoReflectionMethod*)obj)->method;
7950 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7951 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7952 result = mb->mhandle;
7954 /* Type is not yet created */
7955 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7957 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7960 * Hopefully this has been filled in by calling CreateType() on the
7964 * TODO: This won't work if the application finishes another
7965 * TypeBuilder instance instead of this one.
7967 result = mb->mhandle;
7970 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7971 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7973 result = cb->mhandle;
7975 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7977 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7978 result = cb->mhandle;
7981 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7982 result = ((MonoReflectionField*)obj)->field;
7985 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7986 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7987 result = fb->handle;
7990 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7992 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7993 result = fb->handle;
7996 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7997 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8000 klass = tb->type.type->data.klass;
8001 if (klass->wastypebuilder) {
8002 /* Already created */
8006 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8007 result = tb->type.type->data.klass;
8011 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8012 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8013 MonoMethodSignature *sig;
8016 if (helper->arguments)
8017 nargs = mono_array_length (helper->arguments);
8021 sig = mono_metadata_signature_alloc (image, nargs);
8022 sig->explicit_this = helper->call_conv & 64;
8023 sig->hasthis = helper->call_conv & 32;
8025 if (helper->call_conv == 0) /* unmanaged */
8026 sig->call_convention = helper->unmanaged_call_conv - 1;
8028 if (helper->call_conv & 0x02)
8029 sig->call_convention = MONO_CALL_VARARG;
8031 sig->call_convention = MONO_CALL_DEFAULT;
8033 sig->param_count = nargs;
8034 /* TODO: Copy type ? */
8035 sig->ret = helper->return_type->type;
8036 for (i = 0; i < nargs; ++i) {
8037 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8038 sig->params [i] = rt->type;
8044 g_print (obj->vtable->klass->name);
8045 g_assert_not_reached ();