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/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
17 #include "mono/metadata/assembly.h"
18 #include <mono/metadata/exception.h>
27 #include "rawbuffer.h"
28 #include "mono-endian.h"
30 #include <mono/os/gc_wrapper.h>
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA 0x00002000
39 MonoReflectionILGen *ilgen;
40 MonoReflectionType *rtype;
41 MonoArray *parameters;
42 MonoArray *generic_params;
47 guint32 *table_idx; /* note: it's a pointer */
51 MonoBoolean init_locals;
52 MonoArray *return_modreq;
53 MonoArray *return_modopt;
54 MonoArray *param_modreq;
55 MonoArray *param_modopt;
56 MonoArray *permissions;
60 } ReflectionMethodBuilder;
62 const unsigned char table_sizes [64] = {
72 MONO_INTERFACEIMPL_SIZE,
73 MONO_MEMBERREF_SIZE, /* 0x0A */
75 MONO_CUSTOM_ATTR_SIZE,
76 MONO_FIELD_MARSHAL_SIZE,
77 MONO_DECL_SECURITY_SIZE,
78 MONO_CLASS_LAYOUT_SIZE,
79 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
80 MONO_STAND_ALONE_SIGNATURE_SIZE,
84 MONO_PROPERTY_MAP_SIZE,
87 MONO_METHOD_SEMA_SIZE,
89 MONO_MODULEREF_SIZE, /* 0x1A */
95 MONO_ASSEMBLY_SIZE, /* 0x20 */
96 MONO_ASSEMBLY_PROCESSOR_SIZE,
98 MONO_ASSEMBLYREF_SIZE,
99 MONO_ASSEMBLYREFPROC_SIZE,
100 MONO_ASSEMBLYREFOS_SIZE,
104 MONO_NESTED_CLASS_SIZE,
106 MONO_GENERICPARAM_SIZE, /* 0x2A */
107 MONO_METHODSPEC_SIZE,
108 MONO_GENPARCONSTRAINT_SIZE,
114 * These macros can be used to allocate long living atomic data so it won't be
115 * tracked by the garbage collector. We use libgc because it's apparently faster
119 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
120 #define FREE_ATOMIC(ptr)
121 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
123 #define ALLOC_ATOMIC(size) g_malloc (size)
124 #define FREE_ATOMIC(ptr) g_free (ptr)
125 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
128 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
129 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
130 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
131 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
132 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
133 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
134 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
135 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
136 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
137 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
138 static void ensure_runtime_vtable (MonoClass *klass);
139 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
140 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
141 static guint32 type_get_signature_size (MonoType *type);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows)
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
159 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
164 make_room_in_stream (MonoDynamicStream *stream, int size)
166 while (stream->alloc_size <= size) {
167 if (stream->alloc_size < 4096)
168 stream->alloc_size = 4096;
170 stream->alloc_size *= 2;
173 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
175 stream->data = ALLOC_ATOMIC (stream->alloc_size);
179 string_heap_insert (MonoDynamicStream *sh, const char *str)
183 gpointer oldkey, oldval;
185 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
186 return GPOINTER_TO_UINT (oldval);
188 len = strlen (str) + 1;
190 if (idx + len > sh->alloc_size)
191 make_room_in_stream (sh, idx + len);
194 * We strdup the string even if we already copy them in sh->data
195 * so that the string pointers in the hash remain valid even if
196 * we need to realloc sh->data. We may want to avoid that later.
198 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
199 memcpy (sh->data + idx, str, len);
205 string_heap_init (MonoDynamicStream *sh)
208 sh->alloc_size = 4096;
209 sh->data = ALLOC_ATOMIC (4096);
210 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
211 string_heap_insert (sh, "");
214 #if 0 /* never used */
216 string_heap_free (MonoDynamicStream *sh)
218 FREE_ATOMIC (sh->data);
219 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
220 g_hash_table_destroy (sh->hash);
225 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
228 if (stream->alloc_size < stream->index + len)
229 make_room_in_stream (stream, stream->index + len);
230 memcpy (stream->data + stream->index, data, len);
232 stream->index += len;
234 * align index? Not without adding an additional param that controls it since
235 * we may store a blob value in pieces.
241 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memset (stream->data + stream->index, 0, len);
248 stream->index += len;
253 stream_data_align (MonoDynamicStream *stream)
256 guint32 count = stream->index % 4;
258 /* we assume the stream data will be aligned */
260 mono_image_add_stream_data (stream, buf, 4 - count);
264 mono_blob_entry_hash (const char* str)
268 len = mono_metadata_decode_blob_size (str, &str);
272 for (str += 1; str < end; str++)
273 h = (h << 5) - h + *str;
281 mono_blob_entry_equal (const char *str1, const char *str2) {
285 len = mono_metadata_decode_blob_size (str1, &end1);
286 len2 = mono_metadata_decode_blob_size (str2, &end2);
289 return memcmp (end1, end2, len) == 0;
293 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
297 gpointer oldkey, oldval;
299 copy = ALLOC_ATOMIC (s1+s2);
300 memcpy (copy, b1, s1);
301 memcpy (copy + s1, b2, s2);
302 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
304 idx = GPOINTER_TO_UINT (oldval);
306 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
307 mono_image_add_stream_data (&assembly->blob, b2, s2);
308 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
314 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
315 * dest may be misaligned.
318 swap_with_size (char *dest, const char* val, int len, int nelem) {
319 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
322 for (elem = 0; elem < nelem; ++elem) {
348 g_assert_not_reached ();
354 memcpy (dest, val, len * nelem);
359 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
363 guint32 idx = 0, len;
365 len = str->length * 2;
366 mono_metadata_encode_value (len, b, &b);
367 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
369 char *swapped = g_malloc (2 * mono_string_length (str));
370 const char *p = (const char*)mono_string_chars (str);
372 swap_with_size (swapped, p, 2, mono_string_length (str));
373 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
377 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
382 /* modified version needed to handle building corlib */
384 my_mono_class_from_mono_type (MonoType *type) {
385 switch (type->type) {
386 case MONO_TYPE_ARRAY:
388 case MONO_TYPE_SZARRAY:
389 case MONO_TYPE_GENERICINST:
390 return mono_class_from_mono_type (type);
393 g_assert (type->data.generic_param->pklass);
394 return type->data.generic_param->pklass;
396 /* should be always valid when we reach this case... */
397 return type->data.klass;
402 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
407 g_assert_not_reached ();
411 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
412 encode_type (assembly, ginst->generic_type, p, &p);
413 mono_metadata_encode_value (ginst->type_argc, p, &p);
414 for (i = 0; i < ginst->type_argc; ++i)
415 encode_type (assembly, ginst->type_argv [i], p, &p);
421 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
424 g_assert_not_reached ();
429 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
433 case MONO_TYPE_BOOLEAN:
447 case MONO_TYPE_STRING:
448 case MONO_TYPE_OBJECT:
449 case MONO_TYPE_TYPEDBYREF:
450 mono_metadata_encode_value (type->type, p, &p);
453 mono_metadata_encode_value (type->type, p, &p);
454 encode_type (assembly, type->data.type, p, &p);
456 case MONO_TYPE_SZARRAY:
457 mono_metadata_encode_value (type->type, p, &p);
458 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
461 case MONO_TYPE_VALUETYPE:
462 case MONO_TYPE_CLASS: {
463 MonoClass *k = mono_class_from_mono_type (type);
464 mono_metadata_encode_value (type->type, p, &p);
466 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
467 * otherwise two typerefs could point to the same type, leading to
468 * verification errors.
470 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
474 case MONO_TYPE_ARRAY:
475 mono_metadata_encode_value (type->type, p, &p);
476 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
477 mono_metadata_encode_value (type->data.array->rank, p, &p);
478 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
479 mono_metadata_encode_value (0, p, &p);
481 case MONO_TYPE_GENERICINST:
482 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
486 mono_metadata_encode_value (type->type, p, &p);
487 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
491 g_error ("need to encode type %x", type->type);
497 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
500 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
504 encode_type (assembly, type->type, p, endbuf);
508 g_assert_not_reached ();
513 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
518 for (i = 0; i < mono_array_length (modreq); ++i) {
519 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
520 *p = MONO_TYPE_CMOD_REQD;
522 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
526 for (i = 0; i < mono_array_length (modopt); ++i) {
527 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
528 *p = MONO_TYPE_CMOD_OPT;
530 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
537 generic_inst_get_signature_size (MonoGenericInst *ginst)
543 g_assert_not_reached ();
546 size += 1 + type_get_signature_size (ginst->generic_type);
548 for (i = 0; i < ginst->type_argc; ++i)
549 size += type_get_signature_size (ginst->type_argv [i]);
555 type_get_signature_size (MonoType *type)
560 g_assert_not_reached ();
568 case MONO_TYPE_BOOLEAN:
582 case MONO_TYPE_STRING:
583 case MONO_TYPE_OBJECT:
584 case MONO_TYPE_TYPEDBYREF:
587 return size + 1 + type_get_signature_size (type->data.type);
588 case MONO_TYPE_SZARRAY:
589 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
591 case MONO_TYPE_VALUETYPE:
592 case MONO_TYPE_CLASS:
595 case MONO_TYPE_ARRAY:
596 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
597 case MONO_TYPE_GENERICINST:
598 return size + generic_inst_get_signature_size (type->data.generic_inst);
604 g_error ("need to encode type %x", type->type);
610 method_get_signature_size (MonoMethodSignature *sig)
615 size = type_get_signature_size (sig->ret);
616 for (i = 0; i < sig->param_count; i++)
617 size += type_get_signature_size (sig->params [i]);
619 if (sig->generic_param_count)
626 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
631 guint32 nparams = sig->param_count;
632 guint32 size = 11 + method_get_signature_size (sig);
640 p = buf = g_malloc (size);
642 * FIXME: vararg, explicit_this, differenc call_conv values...
644 *p = sig->call_convention;
646 *p |= 0x20; /* hasthis */
647 if (sig->generic_param_count)
648 *p |= 0x10; /* generic */
650 if (sig->generic_param_count)
651 mono_metadata_encode_value (sig->generic_param_count, p, &p);
652 mono_metadata_encode_value (nparams, p, &p);
653 encode_type (assembly, sig->ret, p, &p);
654 for (i = 0; i < nparams; ++i)
655 encode_type (assembly, sig->params [i], p, &p);
657 g_assert (p - buf < size);
658 mono_metadata_encode_value (p-buf, b, &b);
659 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
665 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
668 * FIXME: reuse code from method_encode_signature().
673 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
674 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
675 guint32 size = 21 + nparams * 20;
680 p = buf = g_malloc (size);
681 /* LAMESPEC: all the call conv spec is foobared */
682 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
683 if (mb->call_conv & 2)
684 *p |= 0x5; /* vararg */
685 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
686 *p |= 0x20; /* hasthis */
688 *p |= 0x10; /* generic */
691 mono_metadata_encode_value (ngparams, p, &p);
692 mono_metadata_encode_value (nparams, p, &p);
693 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
694 encode_reflection_type (assembly, mb->rtype, p, &p);
695 for (i = 0; i < nparams; ++i) {
696 MonoArray *modreq = NULL;
697 MonoArray *modopt = NULL;
698 MonoReflectionType *pt;
700 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
701 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
702 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
703 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
704 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
705 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
706 encode_reflection_type (assembly, pt, p, &p);
709 g_assert (p - buf < size);
710 mono_metadata_encode_value (p-buf, b, &b);
711 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
717 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
719 MonoDynamicTable *table;
722 guint32 idx, sig_idx, size;
723 guint nl = mono_array_length (ilgen->locals);
730 p = buf = g_malloc (size);
731 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
732 idx = table->next_idx ++;
734 alloc_table (table, table->rows);
735 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
737 mono_metadata_encode_value (0x07, p, &p);
738 mono_metadata_encode_value (nl, p, &p);
739 for (i = 0; i < nl; ++i) {
740 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
743 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
745 encode_reflection_type (assembly, lb->type, p, &p);
747 g_assert (p - buf < size);
748 mono_metadata_encode_value (p-buf, b, &b);
749 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
752 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
758 method_count_clauses (MonoReflectionILGen *ilgen)
760 guint32 num_clauses = 0;
763 MonoILExceptionInfo *ex_info;
764 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
765 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
766 if (ex_info->handlers)
767 num_clauses += mono_array_length (ex_info->handlers);
775 static MonoExceptionClause*
776 method_encode_clauses (MonoDynamicImage *assembly,
777 MonoReflectionILGen *ilgen, guint32 num_clauses)
779 MonoExceptionClause *clauses;
780 MonoExceptionClause *clause;
781 MonoILExceptionInfo *ex_info;
782 MonoILExceptionBlock *ex_block;
783 guint32 finally_start;
784 int i, j, clause_index;;
786 clauses = g_new0 (MonoExceptionClause, num_clauses);
789 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
790 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
791 finally_start = ex_info->start + ex_info->len;
792 g_assert (ex_info->handlers);
793 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
794 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
795 clause = &(clauses [clause_index]);
797 clause->flags = ex_block->type;
798 clause->try_offset = ex_info->start;
800 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
801 clause->try_len = finally_start - ex_info->start;
803 clause->try_len = ex_info->len;
804 clause->handler_offset = ex_block->start;
805 clause->handler_len = ex_block->len;
806 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
807 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
808 if (ex_block->extype) {
809 mono_g_hash_table_insert (assembly->tokens,
810 GUINT_TO_POINTER (clause->token_or_filter),
813 finally_start = ex_block->start + ex_block->len;
823 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
829 gint32 num_locals = 0;
830 gint32 num_exception = 0;
833 char fat_header [12];
836 guint32 local_sig = 0;
837 guint32 header_size = 12;
840 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
841 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
842 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
843 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
847 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
849 code = mb->ilgen->code;
850 code_size = mb->ilgen->code_len;
851 max_stack = mb->ilgen->max_stack;
852 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
853 if (mb->ilgen->ex_handlers)
854 num_exception = method_count_clauses (mb->ilgen);
858 char *name = mono_string_to_utf8 (mb->name);
859 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
860 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
863 mono_raise_exception (exception);
866 code_size = mono_array_length (code);
867 max_stack = 8; /* we probably need to run a verifier on the code... */
870 /* check for exceptions, maxstack, locals */
871 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
873 if (code_size < 64 && !(code_size & 1)) {
874 flags = (code_size << 2) | 0x2;
875 } else if (code_size < 32 && (code_size & 1)) {
876 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
880 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
881 /* add to the fixup todo list */
882 if (mb->ilgen && mb->ilgen->num_token_fixups)
883 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
884 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
885 return assembly->text_rva + idx;
889 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
891 * FIXME: need to set also the header size in fat_flags.
892 * (and more sects and init locals flags)
896 fat_flags |= METHOD_HEADER_MORE_SECTS;
898 fat_flags |= METHOD_HEADER_INIT_LOCALS;
899 fat_header [0] = fat_flags;
900 fat_header [1] = (header_size / 4 ) << 4;
901 shortp = (guint16*)(fat_header + 2);
902 *shortp = GUINT16_TO_LE (max_stack);
903 intp = (guint32*)(fat_header + 4);
904 *intp = GUINT32_TO_LE (code_size);
905 intp = (guint32*)(fat_header + 8);
906 *intp = GUINT32_TO_LE (local_sig);
907 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
908 /* add to the fixup todo list */
909 if (mb->ilgen && mb->ilgen->num_token_fixups)
910 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
912 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
914 unsigned char sheader [4];
915 MonoExceptionClause clause;
916 MonoILExceptionInfo * ex_info;
917 MonoILExceptionBlock * ex_block;
920 stream_data_align (&assembly->code);
921 /* always use fat format for now */
922 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
923 num_exception *= sizeof (MonoExceptionClause);
924 num_exception += 4; /* include the size of the header */
925 sheader [1] = num_exception & 0xff;
926 sheader [2] = (num_exception >> 8) & 0xff;
927 sheader [3] = (num_exception >> 16) & 0xff;
928 mono_image_add_stream_data (&assembly->code, sheader, 4);
929 /* fat header, so we are already aligned */
931 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
932 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
933 if (ex_info->handlers) {
934 int finally_start = ex_info->start + ex_info->len;
935 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
936 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
937 clause.flags = GUINT32_TO_LE (ex_block->type);
938 clause.try_offset = GUINT32_TO_LE (ex_info->start);
939 /* need fault, too, probably */
940 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
941 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
943 clause.try_len = GUINT32_TO_LE (ex_info->len);
944 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
945 clause.handler_len = GUINT32_TO_LE (ex_block->len);
946 finally_start = ex_block->start + ex_block->len;
947 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
948 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
949 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
950 /*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",
951 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);*/
952 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
955 g_error ("No clauses for ex info block %d", i);
959 return assembly->text_rva + idx;
963 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
966 MonoDynamicTable *table;
969 table = &assembly->tables [table_idx];
971 g_assert (col < table->columns);
973 values = table->values + table->columns;
974 for (i = 1; i <= table->rows; ++i) {
975 if (values [col] == token)
977 values += table->columns;
982 static GHashTable *dynamic_custom_attrs = NULL;
984 static MonoCustomAttrInfo*
985 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
988 MonoCustomAttrInfo *ainfo;
989 MonoReflectionCustomAttr *cattr;
993 /* FIXME: check in assembly the Run flag is set */
995 count = mono_array_length (cattrs);
997 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
999 ainfo->image = image;
1000 ainfo->num_attrs = count;
1001 for (i = 0; i < count; ++i) {
1002 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1003 ainfo->attrs [i].ctor = cattr->ctor->method;
1004 /* FIXME: might want to memdup the data here */
1005 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1006 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1013 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1015 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1020 if (!dynamic_custom_attrs)
1021 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1023 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1027 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1029 /* they are cached, so we don't free them */
1030 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1036 * idx is the table index of the object
1037 * type is one of CUSTOM_ATTR_*
1040 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1042 MonoDynamicTable *table;
1043 MonoReflectionCustomAttr *cattr;
1045 guint32 count, i, token;
1047 char *p = blob_size;
1049 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1052 count = mono_array_length (cattrs);
1053 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1054 table->rows += count;
1055 alloc_table (table, table->rows);
1056 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1057 idx <<= CUSTOM_ATTR_BITS;
1059 for (i = 0; i < count; ++i) {
1060 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1061 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1062 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1063 type = mono_metadata_token_index (token);
1064 type <<= CUSTOM_ATTR_TYPE_BITS;
1065 switch (mono_metadata_token_table (token)) {
1066 case MONO_TABLE_METHOD:
1067 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1069 case MONO_TABLE_MEMBERREF:
1070 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1073 g_warning ("got wrong token in custom attr");
1076 values [MONO_CUSTOM_ATTR_TYPE] = type;
1078 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1079 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1080 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1081 values += MONO_CUSTOM_ATTR_SIZE;
1087 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1088 MonoArray *permissions)
1090 MonoDynamicTable *table;
1092 guint32 count, i, idx;
1093 MonoReflectionPermissionSet *perm;
1098 count = mono_array_length (permissions);
1099 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1100 table->rows += count;
1101 alloc_table (table, table->rows);
1103 for (i = 0; i < mono_array_length (permissions); ++i) {
1104 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1106 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1108 idx = mono_metadata_token_index (parent_token);
1109 idx <<= HAS_DECL_SECURITY_BITS;
1110 switch (mono_metadata_token_table (parent_token)) {
1111 case MONO_TABLE_TYPEDEF:
1112 idx |= HAS_DECL_SECURITY_TYPEDEF;
1114 case MONO_TABLE_METHOD:
1115 idx |= HAS_DECL_SECURITY_METHODDEF;
1117 case MONO_TABLE_ASSEMBLY:
1118 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1121 g_assert_not_reached ();
1124 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1125 values [MONO_DECL_SECURITY_PARENT] = idx;
1126 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1133 * Fill in the MethodDef and ParamDef tables for a method.
1134 * This is used for both normal methods and constructors.
1137 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1139 MonoDynamicTable *table;
1144 /* room in this table is already allocated */
1145 table = &assembly->tables [MONO_TABLE_METHOD];
1146 *mb->table_idx = table->next_idx ++;
1147 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1148 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1149 name = mono_string_to_utf8 (mb->name);
1150 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1152 values [MONO_METHOD_FLAGS] = mb->attrs;
1153 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1154 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1155 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1157 table = &assembly->tables [MONO_TABLE_PARAM];
1158 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1160 mono_image_add_decl_security (assembly,
1161 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1165 MonoDynamicTable *mtable;
1168 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1169 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1172 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1173 if (mono_array_get (mb->pinfo, gpointer, i))
1176 table->rows += count;
1177 alloc_table (table, table->rows);
1178 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1179 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1180 MonoReflectionParamBuilder *pb;
1181 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1182 values [MONO_PARAM_FLAGS] = pb->attrs;
1183 values [MONO_PARAM_SEQUENCE] = i;
1184 if (pb->name != NULL) {
1185 name = mono_string_to_utf8 (pb->name);
1186 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1190 values [MONO_PARAM_NAME] = 0;
1191 values += MONO_PARAM_SIZE;
1192 if (pb->marshal_info) {
1194 alloc_table (mtable, mtable->rows);
1195 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1196 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1197 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1199 pb->table_idx = table->next_idx++;
1206 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1207 MonoReflectionMethodBuilder *mb)
1209 rmb->ilgen = mb->ilgen;
1210 rmb->rtype = mb->rtype;
1211 rmb->parameters = mb->parameters;
1212 rmb->generic_params = mb->generic_params;
1213 rmb->pinfo = mb->pinfo;
1214 rmb->attrs = mb->attrs;
1215 rmb->iattrs = mb->iattrs;
1216 rmb->call_conv = mb->call_conv;
1217 rmb->code = mb->code;
1218 rmb->type = mb->type;
1219 rmb->name = mb->name;
1220 rmb->table_idx = &mb->table_idx;
1221 rmb->init_locals = mb->init_locals;
1222 rmb->return_modreq = mb->return_modreq;
1223 rmb->return_modopt = mb->return_modopt;
1224 rmb->param_modreq = mb->param_modreq;
1225 rmb->param_modopt = mb->param_modopt;
1226 rmb->permissions = mb->permissions;
1227 rmb->mhandle = mb->mhandle;
1233 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1234 MonoReflectionCtorBuilder *mb)
1236 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1238 rmb->ilgen = mb->ilgen;
1239 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1240 rmb->parameters = mb->parameters;
1241 rmb->generic_params = NULL;
1242 rmb->pinfo = mb->pinfo;
1243 rmb->attrs = mb->attrs;
1244 rmb->iattrs = mb->iattrs;
1245 rmb->call_conv = mb->call_conv;
1247 rmb->type = mb->type;
1248 rmb->name = mono_string_new (mono_domain_get (), name);
1249 rmb->table_idx = &mb->table_idx;
1250 rmb->init_locals = mb->init_locals;
1251 rmb->return_modreq = NULL;
1252 rmb->return_modopt = NULL;
1253 rmb->param_modreq = mb->param_modreq;
1254 rmb->param_modopt = mb->param_modopt;
1255 rmb->permissions = mb->permissions;
1256 rmb->mhandle = mb->mhandle;
1262 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1263 MonoReflectionDynamicMethod *mb)
1265 rmb->ilgen = mb->ilgen;
1266 rmb->rtype = mb->rtype;
1267 rmb->parameters = mb->parameters;
1268 rmb->generic_params = NULL;
1270 rmb->attrs = mb->attrs;
1272 rmb->call_conv = mb->call_conv;
1275 rmb->name = mb->name;
1276 rmb->table_idx = NULL;
1277 rmb->init_locals = mb->init_locals;
1278 rmb->return_modreq = NULL;
1279 rmb->return_modopt = NULL;
1280 rmb->param_modreq = NULL;
1281 rmb->param_modopt = NULL;
1282 rmb->permissions = NULL;
1283 rmb->mhandle = mb->mhandle;
1289 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1291 MonoDynamicTable *table;
1294 ReflectionMethodBuilder rmb;
1297 reflection_methodbuilder_from_method_builder (&rmb, mb);
1299 mono_image_basic_method (&rmb, assembly);
1301 if (mb->dll) { /* It's a P/Invoke method */
1303 int charset = mb->charset & 0xf;
1304 int lasterr = mb->charset & 0x40;
1305 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1307 alloc_table (table, table->rows);
1308 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1309 /* map CharSet values to on-disk values */
1311 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1312 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1313 name = mono_string_to_utf8 (mb->dllentry);
1314 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1316 name = mono_string_to_utf8 (mb->dll);
1317 moduleref = string_heap_insert (&assembly->sheap, name);
1319 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1320 table = &assembly->tables [MONO_TABLE_MODULEREF];
1322 alloc_table (table, table->rows);
1323 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1324 values [MONO_IMPLMAP_SCOPE] = table->rows;
1328 if (mb->override_method) {
1329 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1331 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1333 alloc_table (table, table->rows);
1334 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1335 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1336 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1337 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1338 switch (mono_metadata_token_table (tok)) {
1339 case MONO_TABLE_MEMBERREF:
1340 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1342 case MONO_TABLE_METHOD:
1343 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1346 g_assert_not_reached ();
1348 values [MONO_METHODIMPL_DECLARATION] = tok;
1351 if (mb->generic_params) {
1352 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1353 table->rows += mono_array_length (mb->generic_params);
1354 alloc_table (table, table->rows);
1355 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1356 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1358 mono_image_get_generic_param_info (
1359 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1366 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1368 ReflectionMethodBuilder rmb;
1370 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1372 mono_image_basic_method (&rmb, assembly);
1376 type_get_fully_qualified_name (MonoType *type) {
1377 char *name, *result;
1381 name = mono_type_get_name (type);
1382 klass = my_mono_class_from_mono_type (type);
1383 ta = klass->image->assembly;
1385 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1386 name, ta->aname.name,
1387 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1388 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1389 ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
1395 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1399 klass = my_mono_class_from_mono_type (type);
1400 ta = klass->image->assembly;
1401 if (ta == ass || klass->image == mono_defaults.corlib)
1402 return mono_type_get_name (type);
1404 return type_get_fully_qualified_name (type);
1408 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1410 char blob_size [64];
1411 char *b = blob_size;
1416 if (!assembly->save)
1419 p = buf = g_malloc (64);
1421 mono_metadata_encode_value (0x06, p, &p);
1422 /* encode custom attributes before the type */
1423 encode_type (assembly, type, p, &p);
1424 g_assert (p-buf < 64);
1425 mono_metadata_encode_value (p-buf, b, &b);
1426 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1432 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1434 char blob_size [64];
1435 char *b = blob_size;
1440 p = buf = g_malloc (64);
1442 mono_metadata_encode_value (0x06, p, &p);
1443 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1444 /* encode custom attributes before the type */
1445 encode_reflection_type (assembly, fb->type, p, &p);
1446 g_assert (p-buf < 64);
1447 mono_metadata_encode_value (p-buf, b, &b);
1448 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1454 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1455 char blob_size [64];
1456 char *b = blob_size;
1459 guint32 idx = 0, len = 0, dummy = 0;
1461 p = buf = g_malloc (64);
1463 *ret_type = MONO_TYPE_CLASS;
1465 box_val = (char*)&dummy;
1467 box_val = ((char*)val) + sizeof (MonoObject);
1468 *ret_type = val->vtable->klass->byval_arg.type;
1471 switch (*ret_type) {
1472 case MONO_TYPE_BOOLEAN:
1477 case MONO_TYPE_CHAR:
1492 case MONO_TYPE_VALUETYPE:
1493 if (val->vtable->klass->enumtype) {
1494 *ret_type = val->vtable->klass->enum_basetype->type;
1497 g_error ("we can't encode valuetypes");
1498 case MONO_TYPE_CLASS:
1500 case MONO_TYPE_STRING: {
1501 MonoString *str = (MonoString*)val;
1502 /* there is no signature */
1503 len = str->length * 2;
1504 mono_metadata_encode_value (len, b, &b);
1505 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1507 char *swapped = g_malloc (2 * mono_string_length (str));
1508 const char *p = (const char*)mono_string_chars (str);
1510 swap_with_size (swapped, p, 2, mono_string_length (str));
1511 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1515 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1522 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1525 /* there is no signature */
1526 mono_metadata_encode_value (len, b, &b);
1527 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1528 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1529 swap_with_size (blob_size, box_val, len, 1);
1530 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1532 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1540 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1541 char blob_size [64];
1542 char *b = blob_size;
1543 char *p, *buf, *str;
1544 guint32 idx, len, bufsize = 256;
1546 p = buf = g_malloc (bufsize);
1548 switch (minfo->type) {
1549 case MONO_NATIVE_BYVALTSTR:
1550 case MONO_NATIVE_BYVALARRAY:
1551 mono_metadata_encode_value (minfo->type, p, &p);
1552 mono_metadata_encode_value (minfo->count, p, &p);
1554 case MONO_NATIVE_LPARRAY:
1555 mono_metadata_encode_value (minfo->type, p, &p);
1556 if (minfo->eltype || (minfo->count > 0)) {
1557 mono_metadata_encode_value (minfo->eltype, p, &p);
1558 if (minfo->count > 0) {
1559 mono_metadata_encode_value (0, p, &p);
1560 mono_metadata_encode_value (minfo->count, p, &p);
1564 case MONO_NATIVE_CUSTOM:
1565 mono_metadata_encode_value (minfo->type, p, &p);
1567 str = mono_string_to_utf8 (minfo->guid);
1569 mono_metadata_encode_value (len, p, &p);
1570 memcpy (p, str, len);
1574 mono_metadata_encode_value (0, p, &p);
1576 if (minfo->marshaltype) {
1577 str = mono_string_to_utf8 (minfo->marshaltype);
1579 mono_metadata_encode_value (len, p, &p);
1580 if (p + len >= buf + bufsize) {
1583 buf = g_realloc (buf, bufsize);
1586 memcpy (p, str, len);
1590 mono_metadata_encode_value (0, p, &p);
1592 if (minfo->marshaltyperef) {
1593 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1595 mono_metadata_encode_value (len, p, &p);
1596 if (p + len >= buf + bufsize) {
1599 buf = g_realloc (buf, bufsize);
1602 memcpy (p, str, len);
1606 mono_metadata_encode_value (0, p, &p);
1608 if (minfo->mcookie) {
1609 str = mono_string_to_utf8 (minfo->mcookie);
1611 mono_metadata_encode_value (len, p, &p);
1612 if (p + len >= buf + bufsize) {
1615 buf = g_realloc (buf, bufsize);
1618 memcpy (p, str, len);
1622 mono_metadata_encode_value (0, p, &p);
1626 mono_metadata_encode_value (minfo->type, p, &p);
1630 mono_metadata_encode_value (len, b, &b);
1631 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1637 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1639 MonoDynamicTable *table;
1643 /* maybe this fixup should be done in the C# code */
1644 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1645 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1646 table = &assembly->tables [MONO_TABLE_FIELD];
1647 fb->table_idx = table->next_idx ++;
1648 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1649 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1650 name = mono_string_to_utf8 (fb->name);
1651 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1653 values [MONO_FIELD_FLAGS] = fb->attrs;
1654 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1656 if (fb->offset != -1) {
1657 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1659 alloc_table (table, table->rows);
1660 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1661 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1662 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1664 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1665 guint32 field_type = 0;
1666 table = &assembly->tables [MONO_TABLE_CONSTANT];
1668 alloc_table (table, table->rows);
1669 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1670 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1671 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1672 values [MONO_CONSTANT_TYPE] = field_type;
1673 values [MONO_CONSTANT_PADDING] = 0;
1675 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1677 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1679 alloc_table (table, table->rows);
1680 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1681 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1683 * We store it in the code section because it's simpler for now.
1686 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1688 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1689 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1691 if (fb->marshal_info) {
1692 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1694 alloc_table (table, table->rows);
1695 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1696 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1697 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1702 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1706 char *b = blob_size;
1707 guint32 nparams = 0;
1708 MonoReflectionMethodBuilder *mb = fb->get_method;
1709 MonoReflectionMethodBuilder *smb = fb->set_method;
1710 guint32 idx, i, size;
1712 if (mb && mb->parameters)
1713 nparams = mono_array_length (mb->parameters);
1714 if (!mb && smb && smb->parameters)
1715 nparams = mono_array_length (smb->parameters) - 1;
1716 size = 24 + nparams * 10;
1717 buf = p = g_malloc (size);
1720 mono_metadata_encode_value (nparams, p, &p);
1722 encode_reflection_type (assembly, mb->rtype, p, &p);
1723 for (i = 0; i < nparams; ++i) {
1724 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1725 encode_reflection_type (assembly, pt, p, &p);
1728 /* the property type is the last param */
1729 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1730 for (i = 0; i < nparams; ++i) {
1731 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1732 encode_reflection_type (assembly, pt, p, &p);
1736 g_assert (p - buf < size);
1737 mono_metadata_encode_value (p-buf, b, &b);
1738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1744 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1746 MonoDynamicTable *table;
1749 guint num_methods = 0;
1753 * we need to set things in the following tables:
1754 * PROPERTYMAP (info already filled in _get_type_info ())
1755 * PROPERTY (rows already preallocated in _get_type_info ())
1756 * METHOD (method info already done with the generic method code)
1759 table = &assembly->tables [MONO_TABLE_PROPERTY];
1760 pb->table_idx = table->next_idx ++;
1761 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1762 name = mono_string_to_utf8 (pb->name);
1763 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1765 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1766 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1768 /* FIXME: we still don't handle 'other' methods */
1769 if (pb->get_method) num_methods ++;
1770 if (pb->set_method) num_methods ++;
1772 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1773 table->rows += num_methods;
1774 alloc_table (table, table->rows);
1776 if (pb->get_method) {
1777 semaidx = table->next_idx ++;
1778 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1779 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1780 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1781 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1783 if (pb->set_method) {
1784 semaidx = table->next_idx ++;
1785 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1786 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1787 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1788 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1793 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1795 MonoDynamicTable *table;
1798 guint num_methods = 0;
1802 * we need to set things in the following tables:
1803 * EVENTMAP (info already filled in _get_type_info ())
1804 * EVENT (rows already preallocated in _get_type_info ())
1805 * METHOD (method info already done with the generic method code)
1808 table = &assembly->tables [MONO_TABLE_EVENT];
1809 eb->table_idx = table->next_idx ++;
1810 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1811 name = mono_string_to_utf8 (eb->name);
1812 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1814 values [MONO_EVENT_FLAGS] = eb->attrs;
1815 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1818 * FIXME: we still don't handle 'other' methods
1820 if (eb->add_method) num_methods ++;
1821 if (eb->remove_method) num_methods ++;
1822 if (eb->raise_method) num_methods ++;
1824 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1825 table->rows += num_methods;
1826 alloc_table (table, table->rows);
1828 if (eb->add_method) {
1829 semaidx = table->next_idx ++;
1830 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1831 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1832 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1833 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1835 if (eb->remove_method) {
1836 semaidx = table->next_idx ++;
1837 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1838 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1839 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1840 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1842 if (eb->raise_method) {
1843 semaidx = table->next_idx ++;
1844 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1845 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1846 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1847 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1852 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1854 static MonoClass *NewConstraintAttr;
1855 static MonoMethod *NewConstraintAttr_ctor;
1856 MonoDynamicTable *table;
1858 guint32 token, type;
1859 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1862 if (!NewConstraintAttr)
1863 NewConstraintAttr = mono_class_from_name (
1864 mono_defaults.corlib, "System.Runtime.CompilerServices",
1865 "NewConstraintAttribute");
1866 g_assert (NewConstraintAttr);
1868 if (!NewConstraintAttr_ctor) {
1871 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1872 MonoMethod *m = NewConstraintAttr->methods [i];
1874 if (strcmp (m->name, ".ctor"))
1877 NewConstraintAttr_ctor = m;
1881 g_assert (NewConstraintAttr_ctor);
1884 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1886 alloc_table (table, table->rows);
1888 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1889 owner <<= CUSTOM_ATTR_BITS;
1890 owner |= CUSTOM_ATTR_GENERICPAR;
1891 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1893 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1895 type = mono_metadata_token_index (token);
1896 type <<= CUSTOM_ATTR_TYPE_BITS;
1897 switch (mono_metadata_token_table (token)) {
1898 case MONO_TABLE_METHOD:
1899 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1901 case MONO_TABLE_MEMBERREF:
1902 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1905 g_warning ("got wrong token in custom attr");
1908 values [MONO_CUSTOM_ATTR_TYPE] = type;
1910 buf = p = g_malloc (1);
1911 mono_metadata_encode_value (4, p, &p);
1912 g_assert (p-buf == 1);
1914 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1916 values += MONO_CUSTOM_ATTR_SIZE;
1921 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1923 MonoDynamicTable *table;
1924 guint32 num_constraints, i;
1928 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1929 num_constraints = gparam->iface_constraints ?
1930 mono_array_length (gparam->iface_constraints) : 0;
1931 table->rows += num_constraints;
1932 if (gparam->base_type)
1934 alloc_table (table, table->rows);
1936 if (gparam->base_type) {
1937 table_idx = table->next_idx ++;
1938 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1940 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1941 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1942 assembly, gparam->base_type->type);
1945 for (i = 0; i < num_constraints; i++) {
1946 MonoReflectionType *constraint = mono_array_get (
1947 gparam->iface_constraints, gpointer, i);
1949 table_idx = table->next_idx ++;
1950 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1952 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1953 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1954 assembly, constraint->type);
1957 if (gparam->has_ctor_constraint)
1958 encode_new_constraint (assembly, owner);
1962 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1964 MonoDynamicTable *table;
1965 MonoGenericParam *param;
1969 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1970 table_idx = table->next_idx ++;
1971 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1973 param = gparam->type.type->data.generic_param;
1975 values [MONO_GENERICPARAM_OWNER] = owner;
1976 if (gparam->has_value_type)
1977 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1978 else if (gparam->has_reference_type)
1979 values [MONO_GENERICPARAM_FLAGS] = 0x04;
1981 values [MONO_GENERICPARAM_FLAGS] = 0x00;
1982 values [MONO_GENERICPARAM_NUMBER] = param->num;
1983 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1984 values [MONO_GENERICPARAM_KIND] = 0;
1986 encode_constraints (gparam, table_idx, assembly);
1990 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1992 MonoDynamicTable *table;
1995 guint32 cols [MONO_ASSEMBLY_SIZE];
1999 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2002 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2003 table = &assembly->tables [MONO_TABLE_MODULEREF];
2004 token = table->next_idx ++;
2006 alloc_table (table, table->rows);
2007 values = table->values + token * MONO_MODULEREF_SIZE;
2008 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2010 token <<= RESOLTION_SCOPE_BITS;
2011 token |= RESOLTION_SCOPE_MODULEREF;
2012 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2017 if (image->assembly->dynamic)
2019 memset (cols, 0, sizeof (cols));
2021 /* image->assembly->image is the manifest module */
2022 image = image->assembly->image;
2023 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2026 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2027 token = table->next_idx ++;
2029 alloc_table (table, table->rows);
2030 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2031 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2032 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2033 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2034 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2035 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2036 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2037 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2038 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2040 if (strcmp ("", image->assembly->aname.culture)) {
2041 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2042 image->assembly->aname.culture);
2045 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2046 guchar pubtoken [9];
2048 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2049 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2052 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2053 * This is currently only a problem with references to System.Xml (see bug#27706),
2054 * but there may be other cases that makes this necessary. Note, we need to set
2055 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
2056 * recognized by ms, yuck!
2057 * FIXME: need to add more assembly names, as needed.
2059 if (strcmp (image->assembly_name, "mscorlib") == 0 ||
2060 strcmp (image->assembly_name, "System") == 0 ||
2061 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2062 strcmp (image->assembly_name, "System.Xml") == 0 ||
2063 strcmp (image->assembly_name, "System.Data") == 0 ||
2064 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2065 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2066 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2067 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2068 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2069 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2070 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2071 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2072 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2073 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2074 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2075 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2076 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2077 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2078 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2079 strcmp (image->assembly_name, "System.Design") == 0 ||
2080 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2081 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2082 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2083 strcmp (image->assembly_name, "System.Management") == 0 ||
2084 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2085 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2086 strcmp (image->assembly_name, "System.Security") == 0 ||
2087 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2088 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2089 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2090 strcmp (image->assembly_name, "System.Web") == 0) {
2091 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2092 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2093 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2094 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2096 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2099 token <<= RESOLTION_SCOPE_BITS;
2100 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2101 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2106 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2108 MonoDynamicTable *table;
2114 char *b = blob_size;
2116 switch (type->type) {
2117 case MONO_TYPE_FNPTR:
2119 case MONO_TYPE_SZARRAY:
2120 case MONO_TYPE_ARRAY:
2122 case MONO_TYPE_MVAR:
2123 case MONO_TYPE_GENERICINST:
2124 encode_type (assembly, type, p, &p);
2126 case MONO_TYPE_CLASS:
2127 case MONO_TYPE_VALUETYPE: {
2128 MonoClass *k = mono_class_from_mono_type (type);
2129 if (!k || !k->generic_inst)
2131 encode_generic_inst (assembly, k->generic_inst, p, &p);
2138 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2139 if (assembly->save) {
2140 g_assert (p-sig < 128);
2141 mono_metadata_encode_value (p-sig, b, &b);
2142 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2143 alloc_table (table, table->rows + 1);
2144 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2145 values [MONO_TYPESPEC_SIGNATURE] = token;
2148 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2149 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2155 * Despite the name, we handle also TypeSpec (with the above helper).
2158 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2160 MonoDynamicTable *table;
2162 guint32 token, scope, enclosing;
2165 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2168 token = create_typespec (assembly, type);
2171 klass = my_mono_class_from_mono_type (type);
2173 klass = mono_class_from_mono_type (type);
2176 * If it's in the same module and not a generic type parameter:
2178 if ((klass->image == &assembly->image) &&
2179 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2180 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2181 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2182 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2186 if (klass->nested_in) {
2187 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2188 /* get the typeref idx of the enclosing type */
2189 enclosing >>= TYPEDEFORREF_BITS;
2190 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2192 scope = resolution_scope_from_image (assembly, klass->image);
2194 table = &assembly->tables [MONO_TABLE_TYPEREF];
2195 if (assembly->save) {
2196 alloc_table (table, table->rows + 1);
2197 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2198 values [MONO_TYPEREF_SCOPE] = scope;
2199 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2200 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2202 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2203 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2205 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2210 * Insert a memberef row into the metadata: the token that point to the memberref
2211 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2212 * mono_image_get_fieldref_token()).
2213 * The sig param is an index to an already built signature.
2216 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2218 MonoDynamicTable *table;
2220 guint32 token, pclass;
2223 parent = mono_image_typedef_or_ref (assembly, type);
2224 switch (parent & TYPEDEFORREF_MASK) {
2225 case TYPEDEFORREF_TYPEREF:
2226 pclass = MEMBERREF_PARENT_TYPEREF;
2228 case TYPEDEFORREF_TYPESPEC:
2229 pclass = MEMBERREF_PARENT_TYPESPEC;
2231 case TYPEDEFORREF_TYPEDEF:
2232 pclass = MEMBERREF_PARENT_TYPEDEF;
2235 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2238 /* extract the index */
2239 parent >>= TYPEDEFORREF_BITS;
2241 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2243 if (assembly->save) {
2244 alloc_table (table, table->rows + 1);
2245 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2246 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2247 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2248 values [MONO_MEMBERREF_SIGNATURE] = sig;
2251 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2258 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2262 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2265 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2266 method->name, method_encode_signature (assembly, method->signature));
2267 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2272 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2275 ReflectionMethodBuilder rmb;
2277 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2281 reflection_methodbuilder_from_method_builder (&rmb, mb);
2283 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2284 mono_string_to_utf8 (rmb.name),
2285 method_builder_encode_signature (assembly, &rmb));
2286 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2291 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2294 ReflectionMethodBuilder rmb;
2296 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2300 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2302 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2303 mono_string_to_utf8 (rmb.name),
2304 method_builder_encode_signature (assembly, &rmb));
2305 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2310 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2315 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2318 g_assert (f->field->parent);
2319 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2320 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2321 f->field->name, fieldref_encode_signature (assembly, type));
2322 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2327 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2332 guint32 nparams = gmethod->mtype_argc;
2333 guint32 size = 10 + nparams * 10;
2336 char *b = blob_size;
2338 if (!assembly->save)
2341 p = buf = g_malloc (size);
2343 * FIXME: vararg, explicit_this, differenc call_conv values...
2345 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2346 mono_metadata_encode_value (nparams, p, &p);
2348 for (i = 0; i < nparams; i++)
2349 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2352 g_assert (p - buf < size);
2353 mono_metadata_encode_value (p-buf, b, &b);
2354 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2360 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2362 MonoDynamicTable *table;
2364 guint32 token, mtoken = 0, sig;
2365 MonoMethodInflated *imethod;
2366 MonoMethod *declaring;
2368 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2370 g_assert (method->signature->is_inflated);
2371 imethod = (MonoMethodInflated *) method;
2372 declaring = imethod->declaring;
2374 sig = method_encode_signature (assembly, declaring->signature);
2375 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2376 declaring->name, sig);
2378 if (!declaring->signature->generic_param_count)
2381 switch (mono_metadata_token_table (mtoken)) {
2382 case MONO_TABLE_MEMBERREF:
2383 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2385 case MONO_TABLE_METHOD:
2386 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2389 g_assert_not_reached ();
2392 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2394 if (assembly->save) {
2395 alloc_table (table, table->rows + 1);
2396 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2397 values [MONO_METHODSPEC_METHOD] = mtoken;
2398 values [MONO_METHODSPEC_SIGNATURE] = sig;
2401 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2408 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2410 MonoMethodInflated *imethod;
2413 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2417 g_assert (m->signature->is_inflated);
2418 imethod = (MonoMethodInflated *) m;
2420 if (imethod->declaring->signature->generic_param_count)
2421 token = method_encode_methodspec (assembly, m);
2423 guint32 sig = method_encode_signature (
2424 assembly, imethod->declaring->signature);
2425 token = mono_image_get_memberref_token (
2426 assembly, &m->klass->byval_arg, m->name, sig);
2429 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2434 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2436 MonoDynamicTable *table;
2443 char *b = blob_size;
2447 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2448 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2449 * Because of this, we must not insert it into the `typeref' hash table.
2452 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2456 g_assert (tb->generic_params);
2457 klass = mono_class_from_mono_type (tb->type.type);
2459 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2460 encode_type (assembly, &klass->byval_arg, p, &p);
2462 count = mono_array_length (tb->generic_params);
2463 mono_metadata_encode_value (count, p, &p);
2464 for (i = 0; i < count; i++) {
2465 MonoReflectionGenericParam *gparam;
2467 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2469 encode_type (assembly, gparam->type.type, p, &p);
2472 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2473 if (assembly->save) {
2474 g_assert (p-sig < 128);
2475 mono_metadata_encode_value (p-sig, b, &b);
2476 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2477 alloc_table (table, table->rows + 1);
2478 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2479 values [MONO_TYPESPEC_SIGNATURE] = token;
2482 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2483 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2489 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2491 MonoDynamicTable *table;
2494 guint32 token, pclass, parent, sig;
2497 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2501 klass = mono_class_from_mono_type (fb->typeb->type);
2502 name = mono_string_to_utf8 (fb->name);
2504 sig = fieldref_encode_signature (assembly, fb->type->type);
2506 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2507 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2509 pclass = MEMBERREF_PARENT_TYPESPEC;
2510 parent >>= TYPEDEFORREF_BITS;
2512 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2514 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2517 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2518 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2519 values [MONO_MEMBERREF_SIGNATURE] = sig;
2522 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2524 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2529 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2537 char *b = blob_size;
2539 if (!assembly->save)
2543 g_assert (helper->type == 2);
2545 if (helper->arguments)
2546 nargs = mono_array_length (helper->arguments);
2550 size = 10 + (nargs * 10);
2552 p = buf = g_malloc (size);
2554 /* Encode calling convention */
2555 /* Change Any to Standard */
2556 if ((helper->call_conv & 0x03) == 0x03)
2557 helper->call_conv = 0x01;
2558 /* explicit_this implies has_this */
2559 if (helper->call_conv & 0x40)
2560 helper->call_conv &= 0x20;
2562 if (helper->call_conv == 0) /* Unmanaged */
2563 *p = helper->unmanaged_call_conv - 1;
2566 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2567 if (helper->call_conv & 0x02) /* varargs */
2572 mono_metadata_encode_value (nargs, p, &p);
2573 encode_reflection_type (assembly, helper->return_type, p, &p);
2574 for (i = 0; i < nargs; ++i) {
2575 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2576 encode_reflection_type (assembly, pt, p, &p);
2579 g_assert (p - buf < size);
2580 mono_metadata_encode_value (p-buf, b, &b);
2581 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2588 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2591 MonoDynamicTable *table;
2594 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2595 idx = table->next_idx ++;
2597 alloc_table (table, table->rows);
2598 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2600 values [MONO_STAND_ALONE_SIGNATURE] =
2601 mono_reflection_encode_sighelper (assembly, helper);
2607 reflection_cc_to_file (int call_conv) {
2608 switch (call_conv & 0x3) {
2610 case 1: return MONO_CALL_DEFAULT;
2611 case 2: return MONO_CALL_VARARG;
2613 g_assert_not_reached ();
2620 MonoMethodSignature *sig;
2626 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2631 MonoMethodSignature *sig;
2634 name = mono_string_to_utf8 (m->name);
2635 nparams = mono_array_length (m->parameters);
2636 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
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_type);
3405 g_assert_not_reached ();
3408 case MONO_TABLE_METHODSPEC:
3409 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3410 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3411 g_assert (m->signature->generic_param_count);
3414 g_assert_not_reached ();
3418 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3420 target [0] = idx & 0xff;
3421 target [1] = (idx >> 8) & 0xff;
3422 target [2] = (idx >> 16) & 0xff;
3429 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3430 * value is not known when the table is emitted.
3433 fixup_cattrs (MonoDynamicImage *assembly)
3435 MonoDynamicTable *table;
3437 guint32 type, i, idx, token;
3440 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3442 for (i = 0; i < table->rows; ++i) {
3443 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3445 type = values [MONO_CUSTOM_ATTR_TYPE];
3446 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3447 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3448 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3449 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3452 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3453 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3454 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3455 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3462 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3464 MonoDynamicTable *table;
3468 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3470 alloc_table (table, table->rows);
3471 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3472 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3473 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3474 name = mono_string_to_utf8 (rsrc->name);
3475 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3477 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3482 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3484 MonoDynamicTable *table;
3488 char *b = blob_size;
3490 guint32 idx, offset;
3492 if (rsrc->filename) {
3493 name = mono_string_to_utf8 (rsrc->filename);
3494 sname = g_path_get_basename (name);
3496 table = &assembly->tables [MONO_TABLE_FILE];
3498 alloc_table (table, table->rows);
3499 values = table->values + table->next_idx * MONO_FILE_SIZE;
3500 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3501 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3504 mono_sha1_get_digest_from_file (name, hash);
3505 mono_metadata_encode_value (20, b, &b);
3506 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3507 mono_image_add_stream_data (&assembly->blob, hash, 20);
3509 idx = table->next_idx++;
3511 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3514 offset = mono_array_length (rsrc->data);
3515 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3516 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3517 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3518 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3522 * The entry should be emitted into the MANIFESTRESOURCE table of
3523 * the main module, but that needs to reference the FILE table
3524 * which isn't emitted yet.
3531 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3535 set_version_from_string (MonoString *version, guint32 *values)
3537 gchar *ver, *p, *str;
3540 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3541 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3542 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3543 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3546 ver = str = mono_string_to_utf8 (version);
3547 for (i = 0; i < 4; ++i) {
3548 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3554 /* handle Revision and Build */
3564 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3568 char *b = blob_size;
3573 len = mono_array_length (pkey);
3574 mono_metadata_encode_value (len, b, &b);
3575 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3576 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3578 /* need to get the actual value from the key type... */
3579 assembly->strong_name_size = 128;
3580 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3586 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3588 MonoDynamicTable *table;
3589 MonoDynamicImage *assembly;
3590 MonoReflectionAssemblyBuilder *assemblyb;
3595 guint32 module_index;
3597 assemblyb = moduleb->assemblyb;
3598 assembly = moduleb->dynamic_image;
3599 domain = mono_object_domain (assemblyb);
3601 /* Emit ASSEMBLY table */
3602 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3603 alloc_table (table, 1);
3604 values = table->values + MONO_ASSEMBLY_SIZE;
3605 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3606 name = mono_string_to_utf8 (assemblyb->name);
3607 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3609 if (assemblyb->culture) {
3610 name = mono_string_to_utf8 (assemblyb->culture);
3611 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3614 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3616 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3617 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3618 set_version_from_string (assemblyb->version, values);
3620 /* Emit FILE + EXPORTED_TYPE table */
3622 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3624 MonoReflectionModuleBuilder *file_module =
3625 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3626 if (file_module != moduleb) {
3627 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3629 if (file_module->types) {
3630 for (j = 0; j < file_module->num_types; ++j) {
3631 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3632 mono_image_fill_export_table (domain, tb, module_index, 0,
3638 if (assemblyb->loaded_modules) {
3639 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3640 MonoReflectionModule *file_module =
3641 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3642 mono_image_fill_file_table (domain, file_module, assembly);
3644 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3648 /* Emit MANIFESTRESOURCE table */
3650 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3652 MonoReflectionModuleBuilder *file_module =
3653 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3654 /* The table for the main module is emitted later */
3655 if (file_module != moduleb) {
3657 if (file_module->resources) {
3658 int len = mono_array_length (file_module->resources);
3659 for (j = 0; j < len; ++j) {
3660 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3661 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3669 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3670 * for the modulebuilder @moduleb.
3671 * At the end of the process, method and field tokens are fixed up and the
3672 * on-disk compressed metadata representation is created.
3675 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3677 MonoDynamicTable *table;
3678 MonoDynamicImage *assembly;
3679 MonoReflectionAssemblyBuilder *assemblyb;
3684 assemblyb = moduleb->assemblyb;
3685 assembly = moduleb->dynamic_image;
3686 domain = mono_object_domain (assemblyb);
3688 if (assembly->text_rva)
3691 assembly->text_rva = START_TEXT_RVA;
3693 if (moduleb->is_main) {
3694 mono_image_emit_manifest (moduleb);
3697 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3698 table->rows = 1; /* .<Module> */
3700 alloc_table (table, table->rows);
3702 * Set the first entry.
3704 values = table->values + table->columns;
3705 values [MONO_TYPEDEF_FLAGS] = 0;
3706 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3707 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3708 values [MONO_TYPEDEF_EXTENDS] = 0;
3709 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3710 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3713 * handle global methods
3714 * FIXME: test what to do when global methods are defined in multiple modules.
3716 if (moduleb->global_methods) {
3717 table = &assembly->tables [MONO_TABLE_METHOD];
3718 table->rows += mono_array_length (moduleb->global_methods);
3719 alloc_table (table, table->rows);
3720 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3721 mono_image_get_method_info (
3722 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3724 if (moduleb->global_fields) {
3725 table = &assembly->tables [MONO_TABLE_FIELD];
3726 table->rows += mono_array_length (moduleb->global_fields);
3727 alloc_table (table, table->rows);
3728 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3729 mono_image_get_field_info (
3730 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3733 table = &assembly->tables [MONO_TABLE_MODULE];
3734 alloc_table (table, 1);
3735 mono_image_fill_module_table (domain, moduleb, assembly);
3739 /* Collect all types into a list sorted by their table_idx */
3740 GPtrArray *types = g_ptr_array_new ();
3743 for (i = 0; i < moduleb->num_types; ++i) {
3744 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3745 collect_types (types, type);
3748 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3749 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3750 table->rows += types->len;
3751 alloc_table (table, table->rows);
3753 for (i = 0; i < types->len; ++i) {
3754 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3755 mono_image_get_type_info (domain, type, assembly);
3757 g_ptr_array_free (types, TRUE);
3761 * table->rows is already set above and in mono_image_fill_module_table.
3763 /* add all the custom attributes at the end, once all the indexes are stable */
3764 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3766 module_add_cattrs (assembly, moduleb);
3769 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3770 fixup_cattrs (assembly);
3774 * mono_image_insert_string:
3775 * @module: module builder object
3778 * Insert @str into the user string stream of @module.
3781 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3783 MonoDynamicImage *assembly;
3788 MONO_ARCH_SAVE_REGS;
3790 if (!module->dynamic_image)
3791 mono_image_module_basic_init (module);
3793 assembly = module->dynamic_image;
3795 if (assembly->save) {
3796 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3797 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3798 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3800 char *swapped = g_malloc (2 * mono_string_length (str));
3801 const char *p = (const char*)mono_string_chars (str);
3803 swap_with_size (swapped, p, 2, mono_string_length (str));
3804 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3808 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3810 mono_image_add_stream_data (&assembly->us, "", 1);
3813 idx = assembly->us.index ++;
3815 mono_g_hash_table_insert (assembly->tokens,
3816 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3818 return MONO_TOKEN_STRING | idx;
3822 * mono_image_create_token:
3823 * @assembly: a dynamic assembly
3826 * Get a token to insert in the IL code stream for the given MemberInfo.
3827 * @obj can be one of:
3828 * ConstructorBuilder
3838 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3843 klass = obj->vtable->klass;
3844 if (strcmp (klass->name, "MethodBuilder") == 0) {
3845 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3847 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3848 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3850 token = mono_image_get_methodbuilder_token (assembly, mb);
3851 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3853 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3854 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3856 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3857 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3859 token = mono_image_get_ctorbuilder_token (assembly, mb);
3860 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3862 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3863 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3864 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3865 if (tb->generic_params) {
3866 token = mono_image_get_generic_field_token (assembly, fb);
3868 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3871 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3872 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3873 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3875 else if (strcmp (klass->name, "MonoType") == 0 ||
3876 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3877 MonoReflectionType *tb = (MonoReflectionType *)obj;
3878 token = mono_metadata_token_from_dor (
3879 mono_image_typedef_or_ref (assembly, tb->type));
3881 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3882 MonoReflectionType *tb = (MonoReflectionType *)obj;
3883 token = mono_metadata_token_from_dor (
3884 mono_image_typedef_or_ref (assembly, tb->type));
3886 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3887 strcmp (klass->name, "MonoMethod") == 0) {
3888 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3889 if (m->method->signature->is_inflated) {
3890 token = mono_image_get_methodspec_token (assembly, m->method);
3891 } else if (m->method->signature->generic_param_count) {
3892 g_assert_not_reached ();
3893 } else if ((m->method->klass->image == &assembly->image) &&
3894 !m->method->klass->generic_inst) {
3895 static guint32 method_table_idx = 0xffffff;
3897 * Each token should have a unique index, but the indexes are
3898 * assigned by managed code, so we don't know about them. An
3899 * easy solution is to count backwards...
3901 method_table_idx --;
3902 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3904 token = mono_image_get_methodref_token (assembly, m->method);
3905 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3907 else if (strcmp (klass->name, "MonoField") == 0) {
3908 MonoReflectionField *f = (MonoReflectionField *)obj;
3909 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3910 static guint32 field_table_idx = 0xffffff;
3912 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3914 token = mono_image_get_fieldref_token (assembly, f);
3915 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3917 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3918 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3919 token = mono_image_get_array_token (assembly, m);
3921 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3922 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3923 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3926 g_error ("requested token for %s\n", klass->name);
3928 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3935 guint32 import_lookup_table;
3939 guint32 import_address_table_rva;
3947 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3949 static MonoDynamicImage*
3950 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3951 char *assembly_name, char *module_name)
3953 static const guchar entrycode [16] = {0xff, 0x25, 0};
3954 MonoDynamicImage *image;
3958 * We need to use the current ms version or the ms runtime it won't find
3959 * the support dlls. D'oh!
3960 * const char *version = "mono-" VERSION;
3962 const char *version = "v1.0.3705";
3965 image = GC_MALLOC (sizeof (MonoDynamicImage));
3967 image = g_new0 (MonoDynamicImage, 1);
3970 /* keep in sync with image.c */
3971 image->image.name = assembly_name;
3972 image->image.assembly_name = image->image.name; /* they may be different */
3973 image->image.module_name = module_name;
3974 image->image.version = g_strdup (version);
3975 image->image.dynamic = TRUE;
3977 image->image.references = g_new0 (MonoAssembly*, 1);
3978 image->image.references [0] = NULL;
3980 mono_image_init (&image->image);
3982 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3983 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3984 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3985 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3986 image->handleref = g_hash_table_new (NULL, NULL);
3987 image->tokens = mono_g_hash_table_new (NULL, NULL);
3988 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3989 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3990 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3992 string_heap_init (&image->sheap);
3993 mono_image_add_stream_data (&image->us, "", 1);
3994 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3995 /* import tables... */
3996 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3997 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3998 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3999 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4000 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4001 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4002 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4003 stream_data_align (&image->code);
4005 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4007 for (i=0; i < 64; ++i) {
4008 image->tables [i].next_idx = 1;
4009 image->tables [i].columns = table_sizes [i];
4012 image->image.assembly = (MonoAssembly*)assembly;
4013 image->run = assembly->run;
4014 image->save = assembly->save;
4020 * mono_image_basic_init:
4021 * @assembly: an assembly builder object
4023 * Create the MonoImage that represents the assembly builder and setup some
4024 * of the helper hash table and the basic metadata streams.
4027 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4029 MonoDynamicAssembly *assembly;
4030 MonoDynamicImage *image;
4032 MONO_ARCH_SAVE_REGS;
4034 if (assemblyb->dynamic_assembly)
4038 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4040 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4043 assembly->assembly.dynamic = TRUE;
4044 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4045 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4046 if (assemblyb->culture)
4047 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4049 assembly->assembly.aname.culture = g_strdup ("");
4051 assembly->run = assemblyb->access != 2;
4052 assembly->save = assemblyb->access != 1;
4054 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4055 assembly->assembly.aname.name = image->image.name;
4056 assembly->assembly.image = &image->image;
4058 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4059 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4063 calc_section_size (MonoDynamicImage *assembly)
4067 /* alignment constraints */
4068 assembly->code.index += 3;
4069 assembly->code.index &= ~3;
4070 assembly->meta_size += 3;
4071 assembly->meta_size &= ~3;
4072 assembly->resources.index += 3;
4073 assembly->resources.index &= ~3;
4075 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4076 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4079 if (assembly->win32_res) {
4080 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4082 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4083 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4087 assembly->sections [MONO_SECTION_RELOC].size = 12;
4088 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4098 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4102 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4104 ResTreeNode *t1 = (ResTreeNode*)a;
4105 ResTreeNode *t2 = (ResTreeNode*)b;
4107 return t1->id - t2->id;
4111 * resource_tree_create:
4113 * Organize the resources into a resource tree.
4115 static ResTreeNode *
4116 resource_tree_create (MonoArray *win32_resources)
4118 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4122 tree = g_new0 (ResTreeNode, 1);
4124 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4125 MonoReflectionWin32Resource *win32_res =
4126 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4130 lang_node = g_new0 (ResTreeNode, 1);
4131 lang_node->id = win32_res->lang_id;
4132 lang_node->win32_res = win32_res;
4134 /* Create type node if neccesary */
4136 for (l = tree->children; l; l = l->next)
4137 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4138 type_node = (ResTreeNode*)l->data;
4143 type_node = g_new0 (ResTreeNode, 1);
4144 type_node->id = win32_res->res_type;
4147 * The resource types have to be sorted otherwise
4148 * Windows Explorer can't display the version information.
4150 tree->children = g_slist_insert_sorted (tree->children, type_node,
4151 resource_tree_compare_by_id);
4154 /* Create res node if neccesary */
4156 for (l = type_node->children; l; l = l->next)
4157 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4158 res_node = (ResTreeNode*)l->data;
4163 res_node = g_new0 (ResTreeNode, 1);
4164 res_node->id = win32_res->res_id;
4165 type_node->children = g_slist_append (type_node->children, res_node);
4168 res_node->children = g_slist_append (res_node->children, lang_node);
4175 * resource_tree_encode:
4177 * Encode the resource tree into the format used in the PE file.
4180 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4183 MonoPEResourceDir dir;
4184 MonoPEResourceDirEntry dir_entry;
4185 MonoPEResourceDataEntry data_entry;
4189 * For the format of the resource directory, see the article
4190 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4194 memset (&dir, 0, sizeof (dir));
4195 memset (&dir_entry, 0, sizeof (dir_entry));
4196 memset (&data_entry, 0, sizeof (data_entry));
4198 g_assert (sizeof (dir) == 16);
4199 g_assert (sizeof (dir_entry) == 8);
4200 g_assert (sizeof (data_entry) == 16);
4202 node->offset = p - begin;
4204 /* IMAGE_RESOURCE_DIRECTORY */
4205 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4207 memcpy (p, &dir, sizeof (dir));
4210 /* Reserve space for entries */
4212 p += sizeof (dir_entry) * dir.res_id_entries;
4214 /* Write children */
4215 for (l = node->children; l; l = l->next) {
4216 ResTreeNode *child = (ResTreeNode*)l->data;
4218 if (child->win32_res) {
4220 child->offset = p - begin;
4222 /* IMAGE_RESOURCE_DATA_ENTRY */
4223 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4224 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4226 memcpy (p, &data_entry, sizeof (data_entry));
4227 p += sizeof (data_entry);
4229 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4230 p += data_entry.rde_size;
4233 resource_tree_encode (child, begin, p, &p);
4236 /* IMAGE_RESOURCE_ENTRY */
4237 for (l = node->children; l; l = l->next) {
4238 ResTreeNode *child = (ResTreeNode*)l->data;
4239 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4241 dir_entry.is_dir = child->win32_res ? 0 : 1;
4242 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4244 memcpy (entries, &dir_entry, sizeof (dir_entry));
4245 entries += sizeof (dir_entry);
4252 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4257 MonoReflectionWin32Resource *win32_res;
4260 if (!assemblyb->win32_resources)
4264 * Resources are stored in a three level tree inside the PE file.
4265 * - level one contains a node for each type of resource
4266 * - level two contains a node for each resource
4267 * - level three contains a node for each instance of a resource for a
4268 * specific language.
4271 tree = resource_tree_create (assemblyb->win32_resources);
4273 /* Estimate the size of the encoded tree */
4275 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4276 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4277 size += mono_array_length (win32_res->res_data);
4279 /* Directory structure */
4280 size += mono_array_length (assemblyb->win32_resources) * 256;
4281 p = buf = g_malloc (size);
4283 resource_tree_encode (tree, p, p, &p);
4285 g_assert (p - buf < size);
4287 assembly->win32_res = g_malloc (p - buf);
4288 assembly->win32_res_size = p - buf;
4289 memcpy (assembly->win32_res, buf, p - buf);
4295 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4297 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4300 p += sizeof (MonoPEResourceDir);
4301 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4302 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4303 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4304 if (dir_entry->is_dir)
4305 fixup_resource_directory (res_section, child, rva);
4307 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4308 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4311 p += sizeof (MonoPEResourceDirEntry);
4316 * mono_image_create_pefile:
4317 * @mb: a module builder object
4319 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4320 * assembly->pefile where it can be easily retrieved later in chunks.
4323 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4324 MonoMSDOSHeader *msdos;
4325 MonoDotNetHeader *header;
4326 MonoSectionTable *section;
4327 MonoCLIHeader *cli_header;
4328 guint32 size, image_size, virtual_base, text_offset;
4329 guint32 header_start, section_start, file_offset, virtual_offset;
4330 MonoDynamicImage *assembly;
4331 MonoReflectionAssemblyBuilder *assemblyb;
4332 MonoDynamicStream *pefile;
4334 guint32 *rva, value;
4337 static const unsigned char msheader[] = {
4338 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4339 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4342 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4343 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4344 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4345 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4348 assemblyb = mb->assemblyb;
4350 mono_image_basic_init (assemblyb);
4351 assembly = mb->dynamic_image;
4353 /* already created */
4354 if (assembly->pefile.index)
4357 mono_image_build_metadata (mb);
4359 if (mb->is_main && assemblyb->resources) {
4360 int len = mono_array_length (assemblyb->resources);
4361 for (i = 0; i < len; ++i)
4362 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4365 if (mb->resources) {
4366 int len = mono_array_length (mb->resources);
4367 for (i = 0; i < len; ++i)
4368 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4371 build_compressed_metadata (assembly);
4374 assembly_add_win32_resources (assembly, assemblyb);
4376 nsections = calc_section_size (assembly);
4378 pefile = &assembly->pefile;
4380 /* The DOS header and stub */
4381 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4382 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4384 /* the dotnet header */
4385 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4387 /* the section tables */
4388 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4390 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4391 virtual_offset = VIRT_ALIGN;
4394 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4395 if (!assembly->sections [i].size)
4398 file_offset += FILE_ALIGN - 1;
4399 file_offset &= ~(FILE_ALIGN - 1);
4400 virtual_offset += VIRT_ALIGN - 1;
4401 virtual_offset &= ~(VIRT_ALIGN - 1);
4403 assembly->sections [i].offset = file_offset;
4404 assembly->sections [i].rva = virtual_offset;
4406 file_offset += assembly->sections [i].size;
4407 virtual_offset += assembly->sections [i].size;
4408 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4411 file_offset += FILE_ALIGN - 1;
4412 file_offset &= ~(FILE_ALIGN - 1);
4413 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4415 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4417 /* back-patch info */
4418 msdos = (MonoMSDOSHeader*)pefile->data;
4419 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4420 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4421 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4423 header = (MonoDotNetHeader*)(pefile->data + header_start);
4424 header->pesig [0] = 'P';
4425 header->pesig [1] = 'E';
4427 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4428 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4429 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4430 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4431 if (assemblyb->pekind == 1) {
4433 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4436 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4439 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4441 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4442 header->pe.pe_major = 6;
4443 header->pe.pe_minor = 0;
4444 size = assembly->sections [MONO_SECTION_TEXT].size;
4445 size += FILE_ALIGN - 1;
4446 size &= ~(FILE_ALIGN - 1);
4447 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4448 size = assembly->sections [MONO_SECTION_RSRC].size;
4449 size += FILE_ALIGN - 1;
4450 size &= ~(FILE_ALIGN - 1);
4451 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4452 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4453 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4454 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4455 /* pe_rva_entry_point always at the beginning of the text section */
4456 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4458 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4459 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4460 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4461 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4462 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4463 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4464 size = section_start;
4465 size += FILE_ALIGN - 1;
4466 size &= ~(FILE_ALIGN - 1);
4467 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4469 size += VIRT_ALIGN - 1;
4470 size &= ~(VIRT_ALIGN - 1);
4471 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4474 // Translate the PEFileKind value to the value expected by the Windows loader
4477 short kind = assemblyb->pekind;
4480 // PEFileKinds.ConsoleApplication == 2
4481 // PEFileKinds.WindowApplication == 3
4484 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4485 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4491 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4493 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4494 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4495 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4496 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4497 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4498 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4500 /* fill data directory entries */
4502 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4503 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4505 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4506 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4508 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4509 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4510 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4511 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4512 /* patch imported function RVA name */
4513 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4514 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4516 /* the import table */
4517 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4518 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4519 /* patch imported dll RVA name and other entries in the dir */
4520 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4521 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4522 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4523 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4524 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4525 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4527 p = (assembly->code.data + assembly->ilt_offset);
4528 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4529 *p++ = (value) & 0xff;
4530 *p++ = (value >> 8) & (0xff);
4531 *p++ = (value >> 16) & (0xff);
4532 *p++ = (value >> 24) & (0xff);
4534 /* the CLI header info */
4535 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4536 cli_header->ch_size = GUINT32_FROM_LE (72);
4537 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4538 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4539 if (assemblyb->entry_point) {
4540 guint32 table_idx = 0;
4541 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4542 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4543 table_idx = methodb->table_idx;
4546 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4547 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4550 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4551 /* The embedded managed resources */
4552 text_offset = assembly->text_rva + assembly->code.index;
4553 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4554 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4555 text_offset += assembly->resources.index;
4556 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4557 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4558 text_offset += assembly->meta_size;
4559 if (assembly->strong_name_size) {
4560 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4561 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4562 text_offset += assembly->strong_name_size;
4565 /* write the section tables and section content */
4566 section = (MonoSectionTable*)(pefile->data + section_start);
4567 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4568 static const char *section_names [] = {
4569 ".text", ".rsrc", ".reloc"
4571 if (!assembly->sections [i].size)
4573 strcpy (section->st_name, section_names [i]);
4574 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4575 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4576 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4577 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4578 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4579 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4580 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4582 case MONO_SECTION_TEXT:
4583 /* patch entry point */
4584 p = (assembly->code.data + 2);
4585 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4586 *p++ = (value) & 0xff;
4587 *p++ = (value >> 8) & 0xff;
4588 *p++ = (value >> 16) & 0xff;
4589 *p++ = (value >> 24) & 0xff;
4591 text_offset = assembly->sections [i].offset;
4592 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4593 text_offset += assembly->code.index;
4594 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4595 text_offset += assembly->resources.index;
4596 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4597 text_offset += assembly->meta_size;
4598 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4600 g_free (assembly->image.raw_metadata);
4602 case MONO_SECTION_RELOC:
4603 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4604 *rva = GUINT32_FROM_LE (assembly->text_rva);
4606 *rva = GUINT32_FROM_LE (12);
4608 data16 = (guint16*)rva;
4610 * the entrypoint is always at the start of the text section
4611 * 3 is IMAGE_REL_BASED_HIGHLOW
4612 * 2 is patch_size_rva - text_rva
4614 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4616 *data16 = 0; /* terminate */
4618 case MONO_SECTION_RSRC:
4619 if (assembly->win32_res) {
4620 text_offset = assembly->sections [i].offset;
4622 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4623 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4625 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4629 g_assert_not_reached ();
4634 /* check that the file is properly padded */
4637 FILE *f = fopen ("mypetest.exe", "w");
4638 fwrite (pefile->data, pefile->index, 1, f);
4644 MonoReflectionModule *
4645 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4649 MonoImageOpenStatus status;
4650 MonoDynamicAssembly *assembly;
4652 name = mono_string_to_utf8 (fileName);
4654 image = mono_image_open (name, &status);
4657 if (status == MONO_IMAGE_ERROR_ERRNO)
4658 exc = mono_get_exception_file_not_found (fileName);
4660 exc = mono_get_exception_bad_image_format (name);
4662 mono_raise_exception (exc);
4667 assembly = ab->dynamic_assembly;
4668 image->assembly = (MonoAssembly*)assembly;
4670 mono_assembly_load_references (image, &status);
4672 mono_image_close (image);
4673 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4676 return mono_module_get_object (mono_domain_get (), image);
4680 * We need to return always the same object for MethodInfo, FieldInfo etc..
4681 * but we need to consider the reflected type.
4682 * type uses a different hash, since it uses custom hash/equal functions.
4687 MonoClass *refclass;
4691 reflected_equal (gconstpointer a, gconstpointer b) {
4692 const ReflectedEntry *ea = a;
4693 const ReflectedEntry *eb = b;
4695 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4699 reflected_hash (gconstpointer a) {
4700 const ReflectedEntry *ea = a;
4701 return GPOINTER_TO_UINT (ea->item);
4704 #define CHECK_OBJECT(t,p,k) \
4710 mono_domain_lock (domain); \
4711 if (!domain->refobject_hash) \
4712 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4713 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4714 mono_domain_unlock (domain); \
4720 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4722 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4725 #define CACHE_OBJECT(p,o,k) \
4727 ReflectedEntry *e = ALLOC_REFENTRY; \
4729 e->refclass = (k); \
4730 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4731 mono_domain_unlock (domain); \
4735 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4737 /* this is done only once */
4738 mono_domain_lock (domain);
4739 CACHE_OBJECT (assembly, res, NULL);
4743 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4745 /* this is done only once */
4746 mono_domain_lock (domain);
4747 CACHE_OBJECT (module, res, NULL);
4751 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4753 MonoDynamicImage *image = moduleb->dynamic_image;
4754 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4757 * FIXME: we already created an image in mono_image_basic_init (), but
4758 * we don't know which module it belongs to, since that is only
4759 * determined at assembly save time.
4761 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4762 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4764 moduleb->module.image = &image->image;
4765 moduleb->dynamic_image = image;
4766 register_module (mono_object_domain (moduleb), moduleb, image);
4771 * mono_assembly_get_object:
4772 * @domain: an app domain
4773 * @assembly: an assembly
4775 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4777 MonoReflectionAssembly*
4778 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4780 static MonoClass *System_Reflection_Assembly;
4781 MonoReflectionAssembly *res;
4783 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4784 if (!System_Reflection_Assembly)
4785 System_Reflection_Assembly = mono_class_from_name (
4786 mono_defaults.corlib, "System.Reflection", "Assembly");
4787 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4788 res->assembly = assembly;
4789 CACHE_OBJECT (assembly, res, NULL);
4795 MonoReflectionModule*
4796 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4798 static MonoClass *System_Reflection_Module;
4799 MonoReflectionModule *res;
4801 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4802 if (!System_Reflection_Module)
4803 System_Reflection_Module = mono_class_from_name (
4804 mono_defaults.corlib, "System.Reflection", "Module");
4805 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4808 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4810 res->fqname = mono_string_new (domain, image->name);
4811 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4812 res->scopename = mono_string_new (domain, image->module_name);
4814 mono_image_addref (image);
4816 CACHE_OBJECT (image, res, NULL);
4820 MonoReflectionModule*
4821 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4823 static MonoClass *System_Reflection_Module;
4824 MonoReflectionModule *res;
4825 MonoTableInfo *table;
4826 guint32 cols [MONO_FILE_SIZE];
4828 guint32 i, name_idx;
4831 if (!System_Reflection_Module)
4832 System_Reflection_Module = mono_class_from_name (
4833 mono_defaults.corlib, "System.Reflection", "Module");
4834 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4836 table = &image->tables [MONO_TABLE_FILE];
4837 g_assert (table_index < table->rows);
4838 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4841 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4842 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4844 // Check whenever the row has a corresponding row in the moduleref table
4845 table = &image->tables [MONO_TABLE_MODULEREF];
4846 for (i = 0; i < table->rows; ++i) {
4847 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4848 val = mono_metadata_string_heap (image, name_idx);
4849 if (strcmp (val, name) == 0)
4850 res->image = image->modules [i];
4853 res->fqname = mono_string_new (domain, name);
4854 res->name = mono_string_new (domain, name);
4855 res->scopename = mono_string_new (domain, name);
4856 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4862 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4864 if ((t1->type != t2->type) ||
4865 (t1->byref != t2->byref))
4869 case MONO_TYPE_VOID:
4870 case MONO_TYPE_BOOLEAN:
4871 case MONO_TYPE_CHAR:
4882 case MONO_TYPE_STRING:
4885 case MONO_TYPE_OBJECT:
4886 case MONO_TYPE_TYPEDBYREF:
4888 case MONO_TYPE_VALUETYPE:
4889 case MONO_TYPE_CLASS:
4890 case MONO_TYPE_SZARRAY:
4891 return t1->data.klass == t2->data.klass;
4893 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4894 case MONO_TYPE_ARRAY:
4895 if (t1->data.array->rank != t2->data.array->rank)
4897 return t1->data.array->eklass == t2->data.array->eklass;
4898 case MONO_TYPE_GENERICINST: {
4900 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4902 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4904 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4905 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4911 case MONO_TYPE_MVAR:
4912 return t1->data.generic_param == t2->data.generic_param;
4914 g_error ("implement type compare for %0x!", t1->type);
4922 mymono_metadata_type_hash (MonoType *t1)
4928 hash |= t1->byref << 6; /* do not collide with t1->type values */
4930 case MONO_TYPE_VALUETYPE:
4931 case MONO_TYPE_CLASS:
4932 case MONO_TYPE_SZARRAY:
4933 /* check if the distribution is good enough */
4934 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4936 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4941 static MonoReflectionGenericInst*
4942 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4944 static MonoClass *System_Reflection_MonoGenericInst;
4945 MonoReflectionGenericInst *res;
4946 MonoGenericInst *ginst;
4949 if (!System_Reflection_MonoGenericInst) {
4950 System_Reflection_MonoGenericInst = mono_class_from_name (
4951 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4952 g_assert (System_Reflection_MonoGenericInst);
4955 ginst = geninst->data.generic_inst;
4956 gklass = mono_class_from_mono_type (ginst->generic_type);
4958 mono_class_init (ginst->klass);
4960 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4962 res->type.type = geninst;
4963 if (gklass->wastypebuilder && gklass->reflection_info)
4964 res->generic_type = gklass->reflection_info;
4966 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4972 * mono_type_get_object:
4973 * @domain: an app domain
4976 * Return an System.MonoType object representing the type @type.
4979 mono_type_get_object (MonoDomain *domain, MonoType *type)
4981 MonoReflectionType *res;
4982 MonoClass *klass = mono_class_from_mono_type (type);
4984 mono_domain_lock (domain);
4985 if (!domain->type_hash)
4986 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4987 (GCompareFunc)mymono_metadata_type_equal);
4988 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4989 mono_domain_unlock (domain);
4992 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4993 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4994 mono_g_hash_table_insert (domain->type_hash, type, res);
4995 mono_domain_unlock (domain);
4998 if (klass->reflection_info && !klass->wastypebuilder) {
4999 //g_assert_not_reached ();
5000 /* should this be considered an error condition? */
5002 mono_domain_unlock (domain);
5003 return klass->reflection_info;
5006 mono_class_init (klass);
5007 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5009 mono_g_hash_table_insert (domain->type_hash, type, res);
5010 mono_domain_unlock (domain);
5015 * mono_method_get_object:
5016 * @domain: an app domain
5018 * @refclass: the reflected type (can be NULL)
5020 * Return an System.Reflection.MonoMethod object representing the method @method.
5022 MonoReflectionMethod*
5023 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5026 * We use the same C representation for methods and constructors, but the type
5027 * name in C# is different.
5031 MonoReflectionMethod *ret;
5034 refclass = method->klass;
5036 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5037 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5038 cname = "MonoCMethod";
5040 cname = "MonoMethod";
5041 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5043 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5044 ret->method = method;
5045 ret->name = mono_string_new (domain, method->name);
5046 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5047 CACHE_OBJECT (method, ret, refclass);
5052 * mono_field_get_object:
5053 * @domain: an app domain
5057 * Return an System.Reflection.MonoField object representing the field @field
5060 MonoReflectionField*
5061 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5063 MonoReflectionField *res;
5066 CHECK_OBJECT (MonoReflectionField *, field, klass);
5067 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5068 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5071 res->name = mono_string_new (domain, field->name);
5072 res->attrs = field->type->attrs;
5073 res->type = mono_type_get_object (domain, field->type);
5074 CACHE_OBJECT (field, res, klass);
5079 * mono_property_get_object:
5080 * @domain: an app domain
5082 * @property: a property
5084 * Return an System.Reflection.MonoProperty object representing the property @property
5087 MonoReflectionProperty*
5088 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5090 MonoReflectionProperty *res;
5093 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5094 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5095 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5097 res->property = property;
5098 CACHE_OBJECT (property, res, klass);
5103 * mono_event_get_object:
5104 * @domain: an app domain
5108 * Return an System.Reflection.MonoEvent object representing the event @event
5111 MonoReflectionEvent*
5112 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5114 MonoReflectionEvent *res;
5117 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5118 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5119 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5122 CACHE_OBJECT (event, res, klass);
5127 * mono_param_get_objects:
5128 * @domain: an app domain
5131 * Return an System.Reflection.ParameterInfo array object representing the parameters
5132 * in the method @method.
5135 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5137 static MonoClass *System_Reflection_ParameterInfo;
5138 MonoArray *res = NULL;
5139 MonoReflectionMethod *member = NULL;
5140 MonoReflectionParameter *param = NULL;
5144 if (!System_Reflection_ParameterInfo)
5145 System_Reflection_ParameterInfo = mono_class_from_name (
5146 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5148 if (!method->signature->param_count)
5149 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5151 /* Note: the cache is based on the address of the signature into the method
5152 * since we already cache MethodInfos with the method as keys.
5154 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5156 member = mono_method_get_object (domain, method, NULL);
5157 names = g_new (char *, method->signature->param_count);
5158 mono_method_get_param_names (method, (const char **) names);
5160 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5161 for (i = 0; i < method->signature->param_count; ++i) {
5162 param = (MonoReflectionParameter *)mono_object_new (domain,
5163 System_Reflection_ParameterInfo);
5164 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5165 param->DefaultValueImpl = NULL; /* FIXME */
5166 param->MemberImpl = (MonoObject*)member;
5167 param->NameImpl = mono_string_new (domain, names [i]);
5168 param->PositionImpl = i;
5169 param->AttrsImpl = method->signature->params [i]->attrs;
5170 mono_array_set (res, gpointer, i, param);
5173 CACHE_OBJECT (&(method->signature), res, NULL);
5178 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5182 memset (assembly, 0, sizeof (MonoAssemblyName));
5184 assembly->culture = "";
5185 assembly->public_tok_value = NULL;
5187 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5190 while (*p == ' ' || *p == ',') {
5199 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5201 assembly->major = strtoul (p, &s, 10);
5202 if (s == p || *s != '.')
5205 assembly->minor = strtoul (p, &s, 10);
5206 if (s == p || *s != '.')
5209 assembly->build = strtoul (p, &s, 10);
5210 if (s == p || *s != '.')
5213 assembly->revision = strtoul (p, &s, 10);
5217 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5219 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5220 assembly->culture = g_strdup ("");
5223 assembly->culture = p;
5224 while (*p && *p != ',') {
5228 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5230 if (strncmp (p, "null", 4) == 0) {
5233 assembly->public_tok_value = p;
5234 while (*p && *p != ',') {
5239 while (*p && *p != ',')
5243 while (*p == ' ' || *p == ',') {
5257 * mono_reflection_parse_type:
5260 * Parse a type name as accepted by the GetType () method and output the info
5261 * extracted in the info structure.
5262 * the name param will be mangled, so, make a copy before passing it to this function.
5263 * The fields in info will be valid until the memory pointed to by name is valid.
5264 * Returns 0 on parse error.
5265 * See also mono_type_get_name () below.
5268 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5270 char *start, *p, *w, *last_point, *startn;
5271 int in_modifiers = 0;
5272 int isbyref = 0, rank;
5274 start = p = w = name;
5276 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5277 info->name = info->name_space = NULL;
5278 info->nested = NULL;
5279 info->modifiers = NULL;
5281 /* last_point separates the namespace from the name */
5287 *p = 0; /* NULL terminate the name */
5289 info->nested = g_list_append (info->nested, startn);
5290 /* we have parsed the nesting namespace + name */
5294 info->name_space = start;
5296 info->name = last_point + 1;
5298 info->name_space = (char *)"";
5324 info->name_space = start;
5326 info->name = last_point + 1;
5328 info->name_space = (char *)"";
5335 if (isbyref) /* only one level allowed by the spec */
5338 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5342 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5353 else if (*p != '*') /* '*' means unknown lower bound */
5359 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5371 return 0; /* missing assembly name */
5372 if (!assembly_name_to_aname (&info->assembly, p))
5379 if (info->assembly.name)
5382 *w = 0; /* terminate class name */
5383 if (!info->name || !*info->name)
5385 /* add other consistency checks */
5390 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5397 image = mono_defaults.corlib;
5400 klass = mono_class_from_name_case (image, info->name_space, info->name);
5402 klass = mono_class_from_name (image, info->name_space, info->name);
5405 for (mod = info->nested; mod; mod = mod->next) {
5408 mono_class_init (klass);
5409 nested = klass->nested_classes;
5412 klass = nested->data;
5414 if (g_strcasecmp (klass->name, mod->data) == 0)
5417 if (strcmp (klass->name, mod->data) == 0)
5421 nested = nested->next;
5428 mono_class_init (klass);
5429 for (mod = info->modifiers; mod; mod = mod->next) {
5430 modval = GPOINTER_TO_UINT (mod->data);
5431 if (!modval) { /* byref: must be last modifier */
5432 return &klass->this_arg;
5433 } else if (modval == -1) {
5434 klass = mono_ptr_class_get (&klass->byval_arg);
5435 } else { /* array rank */
5436 klass = mono_array_class_get (klass, modval);
5438 mono_class_init (klass);
5441 return &klass->byval_arg;
5445 * mono_reflection_get_type:
5446 * @image: a metadata context
5447 * @info: type description structure
5448 * @ignorecase: flag for case-insensitive string compares
5450 * Build a MonoType from the type description in @info.
5455 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5458 MonoReflectionAssembly *assembly;
5462 type = mono_reflection_get_type_internal (image, info, ignorecase);
5465 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5468 // Reconstruct the type name
5469 fullName = g_string_new ("");
5470 if (info->name_space && (info->name_space [0] != '\0'))
5471 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5473 g_string_printf (fullName, info->name);
5474 for (mod = info->nested; mod; mod = mod->next)
5475 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5478 mono_domain_try_type_resolve (
5479 mono_domain_get (), fullName->str, NULL);
5480 if (assembly && (!image || (assembly->assembly->image == image))) {
5482 if (assembly->assembly->dynamic) {
5483 /* Enumerate all modules */
5484 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5488 if (abuilder->modules) {
5489 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5490 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5491 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5497 if (!type && abuilder->loaded_modules) {
5498 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5499 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5500 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5507 type = mono_reflection_get_type_internal (assembly->assembly->image,
5510 g_string_free (fullName, TRUE);
5515 * mono_reflection_type_from_name:
5517 * @image: a metadata context (can be NULL).
5519 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5520 * it defaults to get the type from @image or, if @image is NULL or loading
5521 * from it fails, uses corlib.
5525 mono_reflection_type_from_name (char *name, MonoImage *image)
5528 MonoTypeNameParse info;
5529 MonoAssembly *assembly;
5531 /*g_print ("requested type %s\n", str);*/
5532 if (!mono_reflection_parse_type (name, &info)) {
5533 g_list_free (info.modifiers);
5534 g_list_free (info.nested);
5538 if (info.assembly.name) {
5539 assembly = mono_assembly_loaded (&info.assembly);
5540 /* do we need to load if it's not already loaded? */
5542 g_list_free (info.modifiers);
5543 g_list_free (info.nested);
5547 image = assembly->image;
5548 } else if (image == NULL) {
5549 image = mono_defaults.corlib;
5552 type = mono_reflection_get_type (image, &info, FALSE);
5553 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5554 image = mono_defaults.corlib;
5555 type = mono_reflection_get_type (image, &info, FALSE);
5558 g_list_free (info.modifiers);
5559 g_list_free (info.nested);
5564 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5566 int slen, type = t->type;
5571 case MONO_TYPE_BOOLEAN: {
5572 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5577 case MONO_TYPE_CHAR:
5579 case MONO_TYPE_I2: {
5580 guint16 *val = g_malloc (sizeof (guint16));
5585 #if SIZEOF_VOID_P == 4
5591 case MONO_TYPE_I4: {
5592 guint32 *val = g_malloc (sizeof (guint32));
5597 #if SIZEOF_VOID_P == 8
5598 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5603 case MONO_TYPE_I8: {
5604 guint64 *val = g_malloc (sizeof (guint64));
5609 case MONO_TYPE_VALUETYPE:
5610 if (t->data.klass->enumtype) {
5611 type = t->data.klass->enum_basetype->type;
5614 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5617 case MONO_TYPE_STRING:
5618 if (*p == (char)0xFF) {
5622 slen = mono_metadata_decode_value (p, &p);
5624 return mono_string_new_len (mono_domain_get (), p, slen);
5625 case MONO_TYPE_CLASS: {
5628 if (*p == (char)0xFF) {
5633 slen = mono_metadata_decode_value (p, &p);
5634 n = g_memdup (p, slen + 1);
5636 t = mono_reflection_type_from_name (n, image);
5638 g_warning ("Cannot load type '%s'", n);
5642 return mono_type_get_object (mono_domain_get (), t);
5646 case MONO_TYPE_OBJECT: {
5649 MonoClass *subc = NULL;
5654 } else if (subt == 0x0E) {
5655 type = MONO_TYPE_STRING;
5657 } else if (subt == 0x55) {
5660 slen = mono_metadata_decode_value (p, &p);
5661 n = g_memdup (p, slen + 1);
5663 t = mono_reflection_type_from_name (n, image);
5665 g_warning ("Cannot load type '%s'", n);
5668 subc = mono_class_from_mono_type (t);
5669 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5670 MonoType simple_type = {{0}};
5671 simple_type.type = subt;
5672 subc = mono_class_from_mono_type (&simple_type);
5674 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5676 val = load_cattr_value (image, &subc->byval_arg, p, end);
5677 obj = mono_object_new (mono_domain_get (), subc);
5678 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5682 case MONO_TYPE_SZARRAY:
5685 guint32 i, alen, basetype;
5688 if (alen == 0xffffffff) {
5692 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5693 basetype = t->data.klass->byval_arg.type;
5698 case MONO_TYPE_BOOLEAN:
5699 for (i=0;i<alen;i++)
5701 MonoBoolean val=*p++;
5702 mono_array_set(arr,MonoBoolean,i,val);
5705 case MONO_TYPE_CHAR:
5708 for (i=0;i<alen;i++)
5710 guint16 val=read16(p);
5711 mono_array_set(arr,guint16,i,val);
5718 for (i=0;i<alen;i++)
5720 guint32 val=read32(p);
5721 mono_array_set(arr,guint32,i,val);
5728 for (i=0;i<alen;i++)
5730 guint64 val=read64(p);
5731 mono_array_set(arr,guint64,i,val);
5735 case MONO_TYPE_CLASS:
5736 case MONO_TYPE_STRING:
5737 for (i = 0; i < alen; i++) {
5738 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5739 mono_array_set (arr, gpointer, i, item);
5743 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5749 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5755 type_is_reference (MonoType *type)
5757 switch (type->type) {
5758 case MONO_TYPE_BOOLEAN:
5759 case MONO_TYPE_CHAR:
5772 case MONO_TYPE_VALUETYPE:
5780 free_param_data (MonoMethodSignature *sig, void **params) {
5782 for (i = 0; i < sig->param_count; ++i) {
5783 if (!type_is_reference (sig->params [i]))
5784 g_free (params [i]);
5789 * Find the method index in the metadata methodDef table.
5790 * Later put these three helper methods in metadata and export them.
5793 find_method_index (MonoMethod *method) {
5794 MonoClass *klass = method->klass;
5797 for (i = 0; i < klass->method.count; ++i) {
5798 if (method == klass->methods [i])
5799 return klass->method.first + 1 + i;
5805 * Find the field index in the metadata FieldDef table.
5808 find_field_index (MonoClass *klass, MonoClassField *field) {
5811 for (i = 0; i < klass->field.count; ++i) {
5812 if (field == &klass->fields [i])
5813 return klass->field.first + 1 + i;
5819 * Find the property index in the metadata Property table.
5822 find_property_index (MonoClass *klass, MonoProperty *property) {
5825 for (i = 0; i < klass->property.count; ++i) {
5826 if (property == &klass->properties [i])
5827 return klass->property.first + 1 + i;
5833 * Find the event index in the metadata Event table.
5836 find_event_index (MonoClass *klass, MonoEvent *event) {
5839 for (i = 0; i < klass->event.count; ++i) {
5840 if (event == &klass->events [i])
5841 return klass->event.first + 1 + i;
5847 create_custom_attr (MonoImage *image, MonoMethod *method,
5848 const char *data, guint32 len)
5850 const char *p = data;
5852 guint32 i, j, num_named;
5856 mono_class_init (method->klass);
5859 attr = mono_object_new (mono_domain_get (), method->klass);
5860 mono_runtime_invoke (method, attr, NULL, NULL);
5864 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5867 /*g_print ("got attr %s\n", method->klass->name);*/
5869 params = g_new (void*, method->signature->param_count);
5873 for (i = 0; i < method->signature->param_count; ++i) {
5874 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5878 attr = mono_object_new (mono_domain_get (), method->klass);
5879 mono_runtime_invoke (method, attr, params, NULL);
5880 free_param_data (method->signature, params);
5882 num_named = read16 (named);
5884 for (j = 0; j < num_named; j++) {
5886 char *name, named_type, data_type;
5887 named_type = *named++;
5888 data_type = *named++; /* type of data */
5889 if (data_type == 0x55) {
5892 type_len = mono_metadata_decode_blob_size (named, &named);
5893 type_name = g_malloc (type_len + 1);
5894 memcpy (type_name, named, type_len);
5895 type_name [type_len] = 0;
5897 /* FIXME: lookup the type and check type consistency */
5900 if (data_type == MONO_TYPE_SZARRAY)
5901 /* The spec does not mention this */
5903 name_len = mono_metadata_decode_blob_size (named, &named);
5904 name = g_malloc (name_len + 1);
5905 memcpy (name, named, name_len);
5906 name [name_len] = 0;
5908 if (named_type == 0x53) {
5909 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5910 void *val = load_cattr_value (image, field->type, named, &named);
5911 mono_field_set_value (attr, field, val);
5912 if (!type_is_reference (field->type))
5914 } else if (named_type == 0x54) {
5917 MonoType *prop_type;
5919 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5920 /* can we have more that 1 arg in a custom attr named property? */
5921 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5922 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5923 mono_property_set_value (prop, attr, pparams, NULL);
5924 if (!type_is_reference (prop_type))
5925 g_free (pparams [0]);
5934 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5941 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5942 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5943 for (i = 0; i < cinfo->num_attrs; ++i) {
5944 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5945 mono_array_set (result, gpointer, i, attr);
5951 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5953 guint32 mtoken, i, len;
5954 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5956 MonoCustomAttrInfo *ainfo;
5957 GList *tmp, *list = NULL;
5960 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5962 i = mono_metadata_custom_attrs_from_index (image, idx);
5966 while (i < ca->rows) {
5967 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5969 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5972 len = g_list_length (list);
5975 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5976 ainfo->num_attrs = len;
5977 ainfo->image = image;
5978 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5979 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5980 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5981 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5982 case CUSTOM_ATTR_TYPE_METHODDEF:
5983 mtoken |= MONO_TOKEN_METHOD_DEF;
5985 case CUSTOM_ATTR_TYPE_MEMBERREF:
5986 mtoken |= MONO_TOKEN_MEMBER_REF;
5989 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5992 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5993 if (!ainfo->attrs [i].ctor)
5994 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5995 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5996 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5997 ainfo->attrs [i].data = data;
6005 mono_custom_attrs_from_method (MonoMethod *method)
6007 MonoCustomAttrInfo *cinfo;
6010 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6012 idx = find_method_index (method);
6013 idx <<= CUSTOM_ATTR_BITS;
6014 idx |= CUSTOM_ATTR_METHODDEF;
6015 return mono_custom_attrs_from_index (method->klass->image, idx);
6019 mono_custom_attrs_from_class (MonoClass *klass)
6021 MonoCustomAttrInfo *cinfo;
6024 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6026 idx = mono_metadata_token_index (klass->type_token);
6027 idx <<= CUSTOM_ATTR_BITS;
6028 idx |= CUSTOM_ATTR_TYPEDEF;
6029 return mono_custom_attrs_from_index (klass->image, idx);
6033 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6035 MonoCustomAttrInfo *cinfo;
6038 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6040 idx = 1; /* there is only one assembly */
6041 idx <<= CUSTOM_ATTR_BITS;
6042 idx |= CUSTOM_ATTR_ASSEMBLY;
6043 return mono_custom_attrs_from_index (assembly->image, idx);
6046 static MonoCustomAttrInfo*
6047 mono_custom_attrs_from_module (MonoImage *image)
6049 MonoCustomAttrInfo *cinfo;
6052 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6054 idx = 1; /* there is only one module */
6055 idx <<= CUSTOM_ATTR_BITS;
6056 idx |= CUSTOM_ATTR_MODULE;
6057 return mono_custom_attrs_from_index (image, idx);
6061 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6063 MonoCustomAttrInfo *cinfo;
6066 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6068 idx = find_property_index (klass, property);
6069 idx <<= CUSTOM_ATTR_BITS;
6070 idx |= CUSTOM_ATTR_PROPERTY;
6071 return mono_custom_attrs_from_index (klass->image, idx);
6075 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6077 MonoCustomAttrInfo *cinfo;
6080 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6082 idx = find_event_index (klass, event);
6083 idx <<= CUSTOM_ATTR_BITS;
6084 idx |= CUSTOM_ATTR_EVENT;
6085 return mono_custom_attrs_from_index (klass->image, idx);
6089 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6091 MonoCustomAttrInfo *cinfo;
6094 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6096 idx = find_field_index (klass, field);
6097 idx <<= CUSTOM_ATTR_BITS;
6098 idx |= CUSTOM_ATTR_FIELDDEF;
6099 return mono_custom_attrs_from_index (klass->image, idx);
6103 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6106 guint32 i, idx, method_index;
6107 guint32 param_list, param_last, param_pos, found;
6109 MonoReflectionMethodAux *aux;
6111 if (method->klass->image->dynamic) {
6112 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6113 if (!aux || !aux->param_cattr)
6115 return aux->param_cattr [param];
6118 image = method->klass->image;
6119 method_index = find_method_index (method);
6120 ca = &image->tables [MONO_TABLE_METHOD];
6122 if (method->klass->generic_inst || method->klass->gen_params ||
6123 method->signature->generic_param_count) {
6124 // FIXME FIXME FIXME
6128 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6129 if (method_index == ca->rows) {
6130 ca = &image->tables [MONO_TABLE_PARAM];
6131 param_last = ca->rows + 1;
6133 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6134 ca = &image->tables [MONO_TABLE_PARAM];
6137 for (i = param_list; i < param_last; ++i) {
6138 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6139 if (param_pos == param) {
6147 idx <<= CUSTOM_ATTR_BITS;
6148 idx |= CUSTOM_ATTR_PARAMDEF;
6149 return mono_custom_attrs_from_index (image, idx);
6153 * mono_reflection_get_custom_attrs:
6154 * @obj: a reflection object handle
6156 * Return an array with all the custom attributes defined of the
6157 * reflection handle @obj. The objects are fully build.
6160 mono_reflection_get_custom_attrs (MonoObject *obj)
6164 MonoCustomAttrInfo *cinfo = NULL;
6166 MONO_ARCH_SAVE_REGS;
6168 klass = obj->vtable->klass;
6169 /* FIXME: need to handle: Module */
6170 if (klass == mono_defaults.monotype_class) {
6171 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6172 klass = mono_class_from_mono_type (rtype->type);
6173 cinfo = mono_custom_attrs_from_class (klass);
6174 } else if (strcmp ("Assembly", klass->name) == 0) {
6175 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6176 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6177 } else if (strcmp ("Module", klass->name) == 0) {
6178 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6179 cinfo = mono_custom_attrs_from_module (module->image);
6180 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6181 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6182 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6183 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6184 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6185 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6186 } else if (strcmp ("MonoField", klass->name) == 0) {
6187 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6188 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6189 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6190 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6191 cinfo = mono_custom_attrs_from_method (rmethod->method);
6192 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6193 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6194 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6195 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6196 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6197 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6198 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6199 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6200 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6201 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6202 } else { /* handle other types here... */
6203 g_error ("get custom attrs not yet supported for %s", klass->name);
6207 result = mono_custom_attrs_construct (cinfo);
6209 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6210 result = mono_array_new (mono_domain_get (), klass, 0);
6216 static MonoMethodSignature*
6217 parameters_to_signature (MonoArray *parameters) {
6218 MonoMethodSignature *sig;
6221 count = parameters? mono_array_length (parameters): 0;
6223 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6224 sig->param_count = count;
6225 sig->sentinelpos = -1; /* FIXME */
6226 for (i = 0; i < count; ++i) {
6227 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6228 sig->params [i] = pt->type;
6233 static MonoMethodSignature*
6234 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6235 MonoMethodSignature *sig;
6237 sig = parameters_to_signature (ctor->parameters);
6238 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6239 sig->ret = &mono_defaults.void_class->byval_arg;
6243 static MonoMethodSignature*
6244 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6245 MonoMethodSignature *sig;
6247 sig = parameters_to_signature (method->parameters);
6248 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6249 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6250 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6254 static MonoMethodSignature*
6255 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6256 MonoMethodSignature *sig;
6258 sig = parameters_to_signature (method->parameters);
6259 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6260 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6261 sig->generic_param_count = 0;
6266 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6268 MonoClass *klass = mono_object_class (prop);
6269 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6270 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6271 *name = mono_string_to_utf8 (pb->name);
6272 *type = pb->type->type;
6274 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6275 *name = g_strdup (p->property->name);
6276 if (p->property->get)
6277 *type = p->property->get->signature->ret;
6279 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6284 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6286 MonoClass *klass = mono_object_class (field);
6287 if (strcmp (klass->name, "FieldBuilder") == 0) {
6288 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6289 *name = mono_string_to_utf8 (fb->name);
6290 *type = fb->type->type;
6292 MonoReflectionField *f = (MonoReflectionField *)field;
6293 *name = g_strdup (f->field->name);
6294 *type = f->field->type;
6299 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6302 MonoTypeEnum simple_type;
6304 if ((p-buffer) + 10 >= *buflen) {
6307 newbuf = g_realloc (buffer, *buflen);
6308 p = newbuf + (p-buffer);
6311 argval = ((char*)arg + sizeof (MonoObject));
6312 simple_type = type->type;
6314 switch (simple_type) {
6315 case MONO_TYPE_BOOLEAN:
6320 case MONO_TYPE_CHAR:
6323 swap_with_size (p, argval, 2, 1);
6329 swap_with_size (p, argval, 4, 1);
6335 swap_with_size (p, argval, 8, 1);
6338 case MONO_TYPE_VALUETYPE:
6339 if (type->data.klass->enumtype) {
6340 simple_type = type->data.klass->enum_basetype->type;
6343 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6346 case MONO_TYPE_STRING: {
6353 str = mono_string_to_utf8 ((MonoString*)arg);
6354 slen = strlen (str);
6355 if ((p-buffer) + 10 + slen >= *buflen) {
6359 newbuf = g_realloc (buffer, *buflen);
6360 p = newbuf + (p-buffer);
6363 mono_metadata_encode_value (slen, p, &p);
6364 memcpy (p, str, slen);
6369 case MONO_TYPE_CLASS: {
6377 k = mono_object_class (arg);
6378 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6379 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6380 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6382 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6383 slen = strlen (str);
6384 if ((p-buffer) + 10 + slen >= *buflen) {
6388 newbuf = g_realloc (buffer, *buflen);
6389 p = newbuf + (p-buffer);
6392 mono_metadata_encode_value (slen, p, &p);
6393 memcpy (p, str, slen);
6398 case MONO_TYPE_SZARRAY: {
6403 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6406 len = mono_array_length ((MonoArray*)arg);
6408 *p++ = (len >> 8) & 0xff;
6409 *p++ = (len >> 16) & 0xff;
6410 *p++ = (len >> 24) & 0xff;
6412 *retbuffer = buffer;
6413 eclass = type->data.klass;
6414 for (i = 0; i < len; ++i) {
6415 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6419 /* it may be a boxed value or a Type */
6420 case MONO_TYPE_OBJECT: {
6421 MonoClass *klass = mono_object_class (arg);
6425 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6428 } else if (klass->enumtype) {
6430 } else if (klass == mono_defaults.string_class) {
6431 simple_type = MONO_TYPE_STRING;
6434 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6435 *p++ = simple_type = klass->byval_arg.type;
6438 g_error ("unhandled type in custom attr");
6440 str = type_get_qualified_name (klass->enum_basetype, NULL);
6441 slen = strlen (str);
6442 if ((p-buffer) + 10 + slen >= *buflen) {
6446 newbuf = g_realloc (buffer, *buflen);
6447 p = newbuf + (p-buffer);
6450 mono_metadata_encode_value (slen, p, &p);
6451 memcpy (p, str, slen);
6454 simple_type = klass->enum_basetype->type;
6458 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6461 *retbuffer = buffer;
6465 * mono_reflection_get_custom_attrs_blob:
6466 * @ctor: custom attribute constructor
6467 * @ctorArgs: arguments o the constructor
6473 * Creates the blob of data that needs to be saved in the metadata and that represents
6474 * the custom attributed described by @ctor, @ctorArgs etc.
6475 * Returns: a Byte array representing the blob of data.
6478 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6481 MonoMethodSignature *sig;
6486 MONO_ARCH_SAVE_REGS;
6488 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6489 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6491 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6493 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6495 p = buffer = g_malloc (buflen);
6496 /* write the prolog */
6499 for (i = 0; i < sig->param_count; ++i) {
6500 arg = mono_array_get (ctorArgs, MonoObject*, i);
6501 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6505 i += mono_array_length (properties);
6507 i += mono_array_length (fields);
6509 *p++ = (i >> 8) & 0xff;
6512 for (i = 0; i < mono_array_length (properties); ++i) {
6517 prop = mono_array_get (properties, gpointer, i);
6518 get_prop_name_and_type (prop, &pname, &ptype);
6519 *p++ = 0x54; /* PROPERTY signature */
6521 /* Preallocate a large enough buffer */
6522 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6523 char *str = type_get_qualified_name (ptype, NULL);
6529 len += strlen (pname);
6531 if ((p-buffer) + 20 + len >= buflen) {
6535 newbuf = g_realloc (buffer, buflen);
6536 p = newbuf + (p-buffer);
6540 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6541 char *str = type_get_qualified_name (ptype, NULL);
6542 int slen = strlen (str);
6546 * This seems to be optional...
6549 mono_metadata_encode_value (slen, p, &p);
6550 memcpy (p, str, slen);
6554 mono_metadata_encode_value (ptype->type, p, &p);
6555 if (ptype->type == MONO_TYPE_SZARRAY)
6556 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6558 len = strlen (pname);
6559 mono_metadata_encode_value (len, p, &p);
6560 memcpy (p, pname, len);
6562 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6569 for (i = 0; i < mono_array_length (fields); ++i) {
6574 field = mono_array_get (fields, gpointer, i);
6575 get_field_name_and_type (field, &fname, &ftype);
6576 *p++ = 0x53; /* FIELD signature */
6577 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6578 char *str = type_get_qualified_name (ftype, NULL);
6579 int slen = strlen (str);
6580 if ((p-buffer) + 10 + slen >= buflen) {
6584 newbuf = g_realloc (buffer, buflen);
6585 p = newbuf + (p-buffer);
6590 * This seems to be optional...
6593 mono_metadata_encode_value (slen, p, &p);
6594 memcpy (p, str, slen);
6598 mono_metadata_encode_value (ftype->type, p, &p);
6600 len = strlen (fname);
6601 mono_metadata_encode_value (len, p, &p);
6602 memcpy (p, fname, len);
6604 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6609 g_assert (p - buffer <= buflen);
6610 buflen = p - buffer;
6611 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6612 p = mono_array_addr (result, char, 0);
6613 memcpy (p, buffer, buflen);
6615 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6621 * mono_reflection_setup_internal_class:
6622 * @tb: a TypeBuilder object
6624 * Creates a MonoClass that represents the TypeBuilder.
6625 * This is a trick that lets us simplify a lot of reflection code
6626 * (and will allow us to support Build and Run assemblies easier).
6629 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6631 MonoClass *klass, *parent;
6633 MONO_ARCH_SAVE_REGS;
6635 klass = g_new0 (MonoClass, 1);
6637 klass->image = &tb->module->dynamic_image->image;
6640 /* check so we can compile corlib correctly */
6641 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6642 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6643 parent = tb->parent->type->data.klass;
6645 parent = my_mono_class_from_mono_type (tb->parent->type);
6649 klass->inited = 1; /* we lie to the runtime */
6650 klass->name = mono_string_to_utf8 (tb->name);
6651 klass->name_space = mono_string_to_utf8 (tb->nspace);
6652 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6653 klass->flags = tb->attrs;
6655 klass->element_class = klass;
6656 klass->reflection_info = tb; /* need to pin. */
6658 /* Put into cache so mono_class_get () will find it */
6659 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6662 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6663 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6667 mono_class_setup_parent (klass, parent);
6668 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6669 const char *old_n = klass->name;
6670 /* trick to get relative numbering right when compiling corlib */
6671 klass->name = "BuildingObject";
6672 mono_class_setup_parent (klass, mono_defaults.object_class);
6673 klass->name = old_n;
6675 mono_class_setup_mono_type (klass);
6677 mono_class_setup_supertypes (klass);
6680 * FIXME: handle interfaces.
6683 tb->type.type = &klass->byval_arg;
6685 if (tb->nesting_type) {
6686 g_assert (tb->nesting_type->type);
6687 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6690 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6694 * mono_reflection_setup_generic_class:
6695 * @tb: a TypeBuilder object
6697 * Setup the generic class after all generic parameters have been added.
6700 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6705 MONO_ARCH_SAVE_REGS;
6707 klass = my_mono_class_from_mono_type (tb->type.type);
6709 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6711 if (klass->gen_params || (count == 0))
6714 klass->num_gen_params = count;
6715 klass->gen_params = g_new0 (MonoGenericParam, count);
6717 for (i = 0; i < count; i++) {
6718 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6719 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6724 * mono_reflection_create_internal_class:
6725 * @tb: a TypeBuilder object
6727 * Actually create the MonoClass that is associated with the TypeBuilder.
6730 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6734 MONO_ARCH_SAVE_REGS;
6736 klass = my_mono_class_from_mono_type (tb->type.type);
6738 if (klass->enumtype && klass->enum_basetype == NULL) {
6739 MonoReflectionFieldBuilder *fb;
6741 g_assert (tb->fields != NULL);
6742 g_assert (mono_array_length (tb->fields) >= 1);
6744 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6746 klass->enum_basetype = fb->type->type;
6747 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6748 if (!klass->element_class)
6749 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6750 klass->instance_size = klass->element_class->instance_size;
6751 klass->size_inited = 1;
6753 * this is almost safe to do with enums and it's needed to be able
6754 * to create objects of the enum type (for use in SetConstant).
6756 /* FIXME: Does this mean enums can't have method overrides ? */
6757 mono_class_setup_vtable (klass, NULL, 0);
6761 static MonoMarshalSpec*
6762 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6763 MonoReflectionMarshal *minfo)
6765 MonoMarshalSpec *res;
6767 res = g_new0 (MonoMarshalSpec, 1);
6768 res->native = minfo->type;
6770 switch (minfo->type) {
6771 case MONO_NATIVE_LPARRAY:
6772 res->data.array_data.elem_type = minfo->eltype;
6773 res->data.array_data.param_num = 0; /* Not yet */
6774 res->data.array_data.num_elem = minfo->count;
6777 case MONO_NATIVE_BYVALTSTR:
6778 case MONO_NATIVE_BYVALARRAY:
6779 res->data.array_data.num_elem = minfo->count;
6782 case MONO_NATIVE_CUSTOM:
6783 if (minfo->marshaltyperef)
6784 res->data.custom_data.custom_name =
6785 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6787 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6798 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6799 ReflectionMethodBuilder *rmb,
6800 MonoMethodSignature *sig)
6803 MonoMethodNormal *pm;
6804 MonoMarshalSpec **specs;
6805 MonoReflectionMethodAux *method_aux;
6808 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6809 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6810 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6813 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6815 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6817 pm = (MonoMethodNormal*)m;
6820 m->flags = rmb->attrs;
6821 m->iflags = rmb->iattrs;
6822 m->name = mono_string_to_utf8 (rmb->name);
6826 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6828 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6829 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6832 m->signature->pinvoke = 1;
6833 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6835 m->signature->pinvoke = 1;
6837 } else if (!m->klass->dummy &&
6838 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6839 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6840 MonoMethodHeader *header;
6842 gint32 max_stack, i;
6843 gint32 num_locals = 0;
6844 gint32 num_clauses = 0;
6848 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6849 code_size = rmb->ilgen->code_len;
6850 max_stack = rmb->ilgen->max_stack;
6851 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6852 if (rmb->ilgen->ex_handlers)
6853 num_clauses = method_count_clauses (rmb->ilgen);
6856 code = mono_array_addr (rmb->code, guint8, 0);
6857 code_size = mono_array_length (rmb->code);
6858 /* we probably need to run a verifier on the code... */
6868 header = g_malloc0 (sizeof (MonoMethodHeader) +
6869 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6870 header->code_size = code_size;
6871 header->code = g_malloc (code_size);
6872 memcpy ((char*)header->code, code, code_size);
6873 header->max_stack = max_stack;
6874 header->init_locals = rmb->init_locals;
6875 header->num_locals = num_locals;
6877 for (i = 0; i < num_locals; ++i) {
6878 MonoReflectionLocalBuilder *lb =
6879 mono_array_get (rmb->ilgen->locals,
6880 MonoReflectionLocalBuilder*, i);
6882 header->locals [i] = g_new0 (MonoType, 1);
6883 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6886 header->num_clauses = num_clauses;
6888 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6893 if (rmb->generic_params) {
6894 int count = mono_array_length (rmb->generic_params);
6895 header->gen_params = g_new0 (MonoGenericParam, count);
6896 for (i = 0; i < count; i++) {
6897 MonoReflectionGenericParam *gp =
6898 mono_array_get (rmb->generic_params,
6899 MonoReflectionGenericParam*, i);
6901 header->gen_params [i] = *gp->type.type->data.generic_param;
6905 pm->header = header;
6909 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6912 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6914 for (i = 0; i < rmb->nrefs; ++i)
6915 mw->data = g_list_append (mw->data, rmb->refs [i]);
6920 /* Parameter names */
6923 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6924 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6925 for (i = 0; i <= m->signature->param_count; ++i) {
6926 MonoReflectionParamBuilder *pb;
6927 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6929 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6931 if (!method_aux->param_cattr)
6932 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6933 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6939 /* Parameter marshalling */
6942 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6943 MonoReflectionParamBuilder *pb;
6944 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6945 if (pb->marshal_info) {
6947 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6948 specs [pb->position] =
6949 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6953 if (specs != NULL) {
6955 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6956 method_aux->param_marshall = specs;
6959 if (klass->image->dynamic && method_aux)
6960 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6966 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6968 ReflectionMethodBuilder rmb;
6969 MonoMethodSignature *sig;
6971 sig = ctor_builder_to_signature (mb);
6973 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6975 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6976 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6978 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6979 /* ilgen is no longer needed */
6987 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6989 ReflectionMethodBuilder rmb;
6990 MonoMethodSignature *sig;
6992 sig = method_builder_to_signature (mb);
6994 reflection_methodbuilder_from_method_builder (&rmb, mb);
6996 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6997 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6999 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7000 /* ilgen is no longer needed */
7006 static MonoClassField*
7007 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7009 MonoClassField *field;
7016 field = g_new0 (MonoClassField, 1);
7018 field->name = mono_string_to_utf8 (fb->name);
7020 /* FIXME: handle type modifiers */
7021 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7022 field->type->attrs = fb->attrs;
7024 field->type = fb->type->type;
7026 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7027 field->data = mono_array_addr (fb->rva_data, char, 0);
7028 if (fb->offset != -1)
7029 field->offset = fb->offset;
7030 field->parent = klass;
7032 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7034 if (fb->def_value) {
7035 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7036 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7037 field->def_value = g_new0 (MonoConstant, 1);
7038 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7039 /* Copy the data from the blob since it might get realloc-ed */
7040 p = assembly->blob.data + idx;
7041 len = mono_metadata_decode_blob_size (p, &p2);
7043 field->def_value->value = g_malloc (len);
7044 memcpy (field->def_value->value, p, len);
7051 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7055 MonoReflectionTypeBuilder *tb = NULL;
7056 MonoGenericInst *ginst;
7061 klass = mono_class_from_mono_type (type->type);
7062 if (!klass->gen_params && !klass->generic_inst &&
7063 !(klass->nested_in && klass->nested_in->gen_params))
7066 mono_loader_lock ();
7068 domain = mono_object_domain (type);
7070 ginst = g_new0 (MonoGenericInst, 1);
7072 if (!klass->generic_inst) {
7073 ginst->type_argc = type_argc;
7074 ginst->type_argv = types;
7076 for (i = 0; i < ginst->type_argc; ++i) {
7077 if (!ginst->is_open)
7078 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7081 ginst->generic_type = &klass->byval_arg;
7083 MonoGenericInst *kginst = klass->generic_inst;
7085 ginst->type_argc = kginst->type_argc;
7086 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7088 for (i = 0; i < ginst->type_argc; i++) {
7089 MonoType *t = kginst->type_argv [i];
7091 if (t->type == MONO_TYPE_VAR)
7092 t = types [t->data.generic_param->num];
7094 if (!ginst->is_open)
7095 ginst->is_open = mono_class_is_open_constructed_type (t);
7097 ginst->type_argv [i] = t;
7100 ginst->generic_type = kginst->generic_type;
7103 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7106 mono_loader_unlock ();
7110 ginst->context = g_new0 (MonoGenericContext, 1);
7111 ginst->context->ginst = ginst;
7113 geninst = g_new0 (MonoType, 1);
7114 geninst->type = MONO_TYPE_GENERICINST;
7115 geninst->data.generic_inst = ginst;
7117 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7118 tb = (MonoReflectionTypeBuilder *) type;
7120 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7121 ginst->is_dynamic = TRUE;
7122 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7123 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7124 MonoReflectionType *rgt = rgi->generic_type;
7126 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7127 tb = (MonoReflectionTypeBuilder *) rgt;
7129 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7130 ginst->is_dynamic = TRUE;
7132 icount = klass->interface_count;
7134 ginst->ifaces = g_new0 (MonoType *, icount);
7135 ginst->count_ifaces = icount;
7137 for (i = 0; i < icount; i++) {
7138 MonoReflectionType *itype;
7141 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7143 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7144 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7145 if (!ginst->ifaces [i])
7146 ginst->ifaces [i] = itype->type;
7149 mono_class_create_generic (ginst);
7151 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7153 mono_loader_unlock ();
7159 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7161 MonoClass *klass, *pklass = NULL;
7162 MonoReflectionType *parent = NULL;
7164 MonoReflectionTypeBuilder *tb = NULL;
7165 MonoGenericInst *ginst;
7168 domain = mono_object_domain (type);
7169 klass = mono_class_from_mono_type (type->type);
7171 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7172 tb = (MonoReflectionTypeBuilder *) type;
7175 parent = tb->parent;
7176 pklass = mono_class_from_mono_type (parent->type);
7179 pklass = klass->parent;
7181 parent = mono_type_get_object (domain, &pklass->byval_arg);
7184 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7188 ginst = geninst->data.generic_inst;
7190 if (pklass && pklass->generic_inst)
7191 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7196 MonoReflectionMethod*
7197 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7199 MonoMethod *method, *inflated;
7200 MonoReflectionMethodBuilder *mb = NULL;
7201 MonoGenericMethod *gmethod;
7202 MonoGenericContext *context;
7205 MONO_ARCH_SAVE_REGS;
7206 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7207 MonoReflectionTypeBuilder *tb;
7210 mb = (MonoReflectionMethodBuilder *) rmethod;
7211 tb = (MonoReflectionTypeBuilder *) mb->type;
7212 klass = mono_class_from_mono_type (tb->type.type);
7214 method = methodbuilder_to_mono_method (klass, mb);
7216 method = rmethod->method;
7218 count = method->signature->generic_param_count;
7219 if (count != mono_array_length (types))
7222 gmethod = g_new0 (MonoGenericMethod, 1);
7223 gmethod->mtype_argc = count;
7224 gmethod->mtype_argv = g_new0 (MonoType *, count);
7225 for (i = 0; i < count; i++) {
7226 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7227 gmethod->mtype_argv [i] = garg->type;
7230 context = g_new0 (MonoGenericContext, 1);
7231 context->ginst = method->klass->generic_inst;
7232 context->gmethod = gmethod;
7234 inflated = mono_class_inflate_generic_method (method, context, NULL);
7236 return mono_method_get_object (
7237 mono_object_domain (rmethod), inflated, NULL);
7241 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7243 MonoGenericMethod *gmethod;
7244 MonoGenericInst *ginst;
7245 MonoGenericContext *context;
7248 ginst = type->type.type->data.generic_inst;
7250 gmethod = g_new0 (MonoGenericMethod, 1);
7251 gmethod->reflection_info = obj;
7253 gmethod->mtype_argc = method->signature->generic_param_count;
7254 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7256 for (i = 0; i < gmethod->mtype_argc; i++) {
7257 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7258 MonoGenericParam *gparam = &mn->header->gen_params [i];
7260 g_assert (gparam->pklass);
7261 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7264 context = g_new0 (MonoGenericContext, 1);
7265 context->ginst = ginst;
7266 context->gmethod = gmethod;
7268 return mono_class_inflate_generic_method (method, context, ginst->klass);
7272 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7277 klass = mono_class_from_mono_type (type->type.type);
7279 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7280 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7281 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7282 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7283 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7284 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7285 method = ((MonoReflectionMethod *) obj)->method;
7287 method = NULL; /* prevent compiler warning */
7288 g_assert_not_reached ();
7291 return inflate_mono_method (type, method, obj);
7295 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7296 MonoArray *methods, MonoArray *ctors,
7297 MonoArray *fields, MonoArray *properties,
7300 MonoGenericInst *ginst;
7301 MonoDynamicGenericInst *dginst;
7302 MonoClass *klass, *gklass, *pklass;
7305 MONO_ARCH_SAVE_REGS;
7307 klass = mono_class_from_mono_type (type->type.type);
7308 ginst = type->type.type->data.generic_inst;
7310 if (ginst->initialized)
7313 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7315 gklass = mono_class_from_mono_type (ginst->generic_type);
7316 mono_class_init (gklass);
7319 pklass = mono_class_from_mono_type (ginst->parent);
7321 pklass = gklass->parent;
7323 mono_class_setup_parent (klass, pklass);
7325 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7326 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7327 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7328 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7329 dginst->count_events = events ? mono_array_length (events) : 0;
7331 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7332 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7333 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7334 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7335 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7337 for (i = 0; i < dginst->count_methods; i++) {
7338 MonoObject *obj = mono_array_get (methods, gpointer, i);
7340 dginst->methods [i] = inflate_method (type, obj);
7343 for (i = 0; i < dginst->count_ctors; i++) {
7344 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7346 dginst->ctors [i] = inflate_method (type, obj);
7349 for (i = 0; i < dginst->count_fields; i++) {
7350 MonoObject *obj = mono_array_get (fields, gpointer, i);
7351 MonoClassField *field;
7353 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7354 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7355 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7356 field = ((MonoReflectionField *) obj)->field;
7358 field = NULL; /* prevent compiler warning */
7359 g_assert_not_reached ();
7362 dginst->fields [i] = *field;
7363 dginst->fields [i].generic_type = field->type;
7364 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7367 for (i = 0; i < dginst->count_properties; i++) {
7368 MonoObject *obj = mono_array_get (properties, gpointer, i);
7369 MonoProperty *property = &dginst->properties [i];
7371 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7372 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7374 property->parent = klass;
7375 property->attrs = pb->attrs;
7376 property->name = mono_string_to_utf8 (pb->name);
7378 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7380 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7381 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7382 *property = *((MonoReflectionProperty *) obj)->property;
7385 property->get = inflate_mono_method (type, property->get, NULL);
7387 property->set = inflate_mono_method (type, property->set, NULL);
7389 g_assert_not_reached ();
7392 for (i = 0; i < dginst->count_events; i++) {
7393 MonoObject *obj = mono_array_get (events, gpointer, i);
7394 MonoEvent *event = &dginst->events [i];
7396 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7397 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7399 event->parent = klass;
7400 event->attrs = eb->attrs;
7401 event->name = mono_string_to_utf8 (eb->name);
7403 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7404 if (eb->remove_method)
7405 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7406 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7407 *event = *((MonoReflectionEvent *) obj)->event;
7410 event->add = inflate_mono_method (type, event->add, NULL);
7412 event->remove = inflate_mono_method (type, event->remove, NULL);
7414 g_assert_not_reached ();
7417 ginst->initialized = TRUE;
7421 ensure_runtime_vtable (MonoClass *klass)
7423 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7424 int i, num, j, onum;
7425 MonoMethod **overrides;
7427 if (!tb || klass->wastypebuilder)
7430 ensure_runtime_vtable (klass->parent);
7432 num = tb->ctors? mono_array_length (tb->ctors): 0;
7433 num += tb->num_methods;
7434 klass->method.count = num;
7435 klass->methods = g_new (MonoMethod*, num);
7436 num = tb->ctors? mono_array_length (tb->ctors): 0;
7437 for (i = 0; i < num; ++i)
7438 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7439 num = tb->num_methods;
7441 for (i = 0; i < num; ++i)
7442 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7444 klass->wastypebuilder = TRUE;
7445 if (tb->interfaces) {
7446 klass->interface_count = mono_array_length (tb->interfaces);
7447 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7448 for (i = 0; i < klass->interface_count; ++i) {
7449 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7450 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7454 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7455 for (i = 0; i < klass->method.count; ++i)
7456 klass->methods [i]->slot = i;
7461 for (i = 0; i < tb->num_methods; ++i) {
7462 MonoReflectionMethodBuilder *mb =
7463 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7464 if (mb->override_method)
7469 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7473 for (i = 0; i < tb->num_methods; ++i) {
7474 MonoReflectionMethodBuilder *mb =
7475 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7476 if (mb->override_method) {
7477 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7478 overrides [onum * 2] =
7479 mb->override_method->method;
7480 overrides [onum * 2 + 1] =
7483 g_assert (mb->mhandle);
7490 mono_class_setup_vtable (klass, overrides, onum);
7494 typebuilder_setup_fields (MonoClass *klass)
7496 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7497 MonoReflectionFieldBuilder *fb;
7498 MonoClassField *field;
7503 klass->field.count = tb->num_fields;
7504 klass->field.first = 0;
7505 klass->field.last = klass->field.count;
7507 if (!klass->field.count)
7510 klass->fields = g_new0 (MonoClassField, klass->field.count);
7512 for (i = 0; i < klass->field.count; ++i) {
7513 fb = mono_array_get (tb->fields, gpointer, i);
7514 field = &klass->fields [i];
7515 field->name = mono_string_to_utf8 (fb->name);
7517 /* FIXME: handle type modifiers */
7518 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7519 field->type->attrs = fb->attrs;
7521 field->type = fb->type->type;
7523 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7524 field->data = mono_array_addr (fb->rva_data, char, 0);
7525 if (fb->offset != -1)
7526 field->offset = fb->offset;
7527 field->parent = klass;
7529 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7531 if (fb->def_value) {
7532 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7533 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7534 field->def_value = g_new0 (MonoConstant, 1);
7535 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7536 /* Copy the data from the blob since it might get realloc-ed */
7537 p = assembly->blob.data + idx;
7538 len = mono_metadata_decode_blob_size (p, &p2);
7540 field->def_value->value = g_malloc (len);
7541 memcpy (field->def_value->value, p, len);
7544 mono_class_layout_fields (klass);
7548 typebuilder_setup_properties (MonoClass *klass)
7550 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7551 MonoReflectionPropertyBuilder *pb;
7554 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7555 klass->property.first = 0;
7556 klass->property.last = klass->property.count;
7558 klass->properties = g_new0 (MonoProperty, klass->property.count);
7559 for (i = 0; i < klass->property.count; ++i) {
7560 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7561 klass->properties [i].parent = klass;
7562 klass->properties [i].attrs = pb->attrs;
7563 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7565 klass->properties [i].get = pb->get_method->mhandle;
7567 klass->properties [i].set = pb->set_method->mhandle;
7571 MonoReflectionEvent *
7572 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7574 MonoEvent *event = g_new0 (MonoEvent, 1);
7578 klass = my_mono_class_from_mono_type (tb->type.type);
7580 event->parent = klass;
7581 event->attrs = eb->attrs;
7582 event->name = mono_string_to_utf8 (eb->name);
7584 event->add = eb->add_method->mhandle;
7585 if (eb->remove_method)
7586 event->remove = eb->remove_method->mhandle;
7587 if (eb->raise_method)
7588 event->raise = eb->raise_method->mhandle;
7590 if (eb->other_methods) {
7591 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7592 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7593 MonoReflectionMethodBuilder *mb =
7594 mono_array_get (eb->other_methods,
7595 MonoReflectionMethodBuilder*, j);
7596 event->other [j] = mb->mhandle;
7600 return mono_event_get_object (mono_object_domain (tb), klass, event);
7604 typebuilder_setup_events (MonoClass *klass)
7606 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7607 MonoReflectionEventBuilder *eb;
7610 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7611 klass->event.first = 0;
7612 klass->event.last = klass->event.count;
7614 klass->events = g_new0 (MonoEvent, klass->event.count);
7615 for (i = 0; i < klass->event.count; ++i) {
7616 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7617 klass->events [i].parent = klass;
7618 klass->events [i].attrs = eb->attrs;
7619 klass->events [i].name = mono_string_to_utf8 (eb->name);
7621 klass->events [i].add = eb->add_method->mhandle;
7622 if (eb->remove_method)
7623 klass->events [i].remove = eb->remove_method->mhandle;
7624 if (eb->raise_method)
7625 klass->events [i].raise = eb->raise_method->mhandle;
7627 if (eb->other_methods) {
7628 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7629 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7630 MonoReflectionMethodBuilder *mb =
7631 mono_array_get (eb->other_methods,
7632 MonoReflectionMethodBuilder*, j);
7633 klass->events [i].other [j] = mb->mhandle;
7640 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7643 MonoReflectionType* res;
7645 MONO_ARCH_SAVE_REGS;
7647 klass = my_mono_class_from_mono_type (tb->type.type);
7649 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7652 * Fields to set in klass:
7653 * the various flags: delegate/unicode/contextbound etc.
7656 klass->flags = tb->attrs;
7658 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7659 /* No need to fully construct the type */
7660 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7662 /* enums are done right away */
7663 if (!klass->enumtype)
7664 ensure_runtime_vtable (klass);
7666 /* fields and object layout */
7667 if (klass->parent) {
7668 if (!klass->parent->size_inited)
7669 mono_class_init (klass->parent);
7670 klass->instance_size += klass->parent->instance_size;
7671 klass->class_size += klass->parent->class_size;
7672 klass->min_align = klass->parent->min_align;
7674 klass->instance_size = sizeof (MonoObject);
7675 klass->min_align = 1;
7678 /* FIXME: handle packing_size and instance_size */
7679 typebuilder_setup_fields (klass);
7681 typebuilder_setup_properties (klass);
7683 typebuilder_setup_events (klass);
7685 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7686 /* with enums res == tb: need to fix that. */
7687 if (!klass->enumtype)
7688 g_assert (res != (MonoReflectionType*)tb);
7693 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7695 MonoGenericParam *param;
7698 MONO_ARCH_SAVE_REGS;
7700 param = g_new0 (MonoGenericParam, 1);
7702 param->method = NULL;
7703 param->name = mono_string_to_utf8 (gparam->name);
7704 param->num = gparam->index;
7706 image = &gparam->tbuilder->module->dynamic_image->image;
7707 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7709 param->pklass->reflection_info = gparam;
7711 gparam->type.type = g_new0 (MonoType, 1);
7712 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7713 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7714 gparam->type.type->data.generic_param = param;
7718 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7720 MonoDynamicImage *assembly = sig->module->dynamic_image;
7721 guint32 na = mono_array_length (sig->arguments);
7726 MONO_ARCH_SAVE_REGS;
7728 p = buf = g_malloc (10 + na * 10);
7730 mono_metadata_encode_value (0x07, p, &p);
7731 mono_metadata_encode_value (na, p, &p);
7732 for (i = 0; i < na; ++i) {
7733 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7734 encode_reflection_type (assembly, type, p, &p);
7738 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7739 p = mono_array_addr (result, char, 0);
7740 memcpy (p, buf, buflen);
7747 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7749 MonoDynamicImage *assembly = sig->module->dynamic_image;
7750 guint32 na = mono_array_length (sig->arguments);
7755 MONO_ARCH_SAVE_REGS;
7757 p = buf = g_malloc (10 + na * 10);
7759 mono_metadata_encode_value (0x06, p, &p);
7760 for (i = 0; i < na; ++i) {
7761 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7762 encode_reflection_type (assembly, type, p, &p);
7766 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7767 p = mono_array_addr (result, char, 0);
7768 memcpy (p, buf, buflen);
7775 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7777 ReflectionMethodBuilder rmb;
7778 MonoMethodSignature *sig;
7781 sig = dynamic_method_to_signature (mb);
7783 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7786 * Resolve references.
7788 rmb.nrefs = mb->nrefs;
7789 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7790 for (i = 0; i < mb->nrefs; ++i) {
7791 gpointer ref = resolve_object (mb->module->image,
7792 mono_array_get (mb->refs, MonoObject*, i));
7795 mono_raise_exception (mono_get_exception_type_load (NULL));
7802 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7806 /* ilgen is no longer needed */
7811 * mono_reflection_lookup_dynamic_token:
7813 * Finish the Builder object pointed to by TOKEN and return the corresponding
7814 * runtime structure.
7817 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7819 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7822 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7825 return resolve_object (image, obj);
7829 resolve_object (MonoImage *image, MonoObject *obj)
7831 gpointer result = NULL;
7833 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7834 result = mono_string_intern ((MonoString*)obj);
7837 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7838 MonoReflectionType *tb = (MonoReflectionType*)obj;
7839 result = mono_class_from_mono_type (tb->type);
7842 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7843 result = ((MonoReflectionMethod*)obj)->method;
7846 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7847 result = ((MonoReflectionMethod*)obj)->method;
7850 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7851 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7852 result = mb->mhandle;
7854 /* Type is not yet created */
7855 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7857 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7860 * Hopefully this has been filled in by calling CreateType() on the
7864 * TODO: This won't work if the application finishes another
7865 * TypeBuilder instance instead of this one.
7867 result = mb->mhandle;
7870 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7871 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7873 result = cb->mhandle;
7875 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7877 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7878 result = cb->mhandle;
7881 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7882 result = ((MonoReflectionField*)obj)->field;
7885 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7886 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7887 result = fb->handle;
7890 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7892 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7893 result = fb->handle;
7896 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7897 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7900 klass = tb->type.type->data.klass;
7901 if (klass->wastypebuilder) {
7902 /* Already created */
7906 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7907 result = tb->type.type->data.klass;
7911 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7912 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7913 MonoMethodSignature *sig;
7916 if (helper->arguments)
7917 nargs = mono_array_length (helper->arguments);
7921 sig = mono_metadata_signature_alloc (image, nargs);
7922 sig->explicit_this = helper->call_conv & 64;
7923 sig->hasthis = helper->call_conv & 32;
7925 if (helper->call_conv == 0) /* unmanaged */
7926 sig->call_convention = helper->unmanaged_call_conv - 1;
7928 if (helper->call_conv & 0x02)
7929 sig->call_convention = MONO_CALL_VARARG;
7931 sig->call_convention = MONO_CALL_DEFAULT;
7933 sig->param_count = nargs;
7934 /* TODO: Copy type ? */
7935 sig->ret = helper->return_type->type;
7936 for (i = 0; i < nargs; ++i) {
7937 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7938 sig->params [i] = rt->type;
7944 g_print (obj->vtable->klass->name);
7945 g_assert_not_reached ();