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 /* missing public key */
1386 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1387 name, ta->aname.name,
1388 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1389 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
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 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1555 case MONO_NATIVE_CUSTOM:
1556 mono_metadata_encode_value (minfo->type, p, &p);
1558 str = mono_string_to_utf8 (minfo->guid);
1560 mono_metadata_encode_value (len, p, &p);
1561 memcpy (p, str, len);
1565 mono_metadata_encode_value (0, p, &p);
1567 if (minfo->marshaltype) {
1568 str = mono_string_to_utf8 (minfo->marshaltype);
1570 mono_metadata_encode_value (len, p, &p);
1571 if (p + len >= buf + bufsize) {
1574 buf = g_realloc (buf, bufsize);
1577 memcpy (p, str, len);
1581 mono_metadata_encode_value (0, p, &p);
1583 if (minfo->marshaltyperef) {
1584 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1586 mono_metadata_encode_value (len, p, &p);
1587 if (p + len >= buf + bufsize) {
1590 buf = g_realloc (buf, bufsize);
1593 memcpy (p, str, len);
1597 mono_metadata_encode_value (0, p, &p);
1599 if (minfo->mcookie) {
1600 str = mono_string_to_utf8 (minfo->mcookie);
1602 mono_metadata_encode_value (len, p, &p);
1603 if (p + len >= buf + bufsize) {
1606 buf = g_realloc (buf, bufsize);
1609 memcpy (p, str, len);
1613 mono_metadata_encode_value (0, p, &p);
1617 mono_metadata_encode_value (minfo->type, p, &p);
1621 mono_metadata_encode_value (len, b, &b);
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1628 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1630 MonoDynamicTable *table;
1634 /* maybe this fixup should be done in the C# code */
1635 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1636 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1637 table = &assembly->tables [MONO_TABLE_FIELD];
1638 fb->table_idx = table->next_idx ++;
1639 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1640 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1641 name = mono_string_to_utf8 (fb->name);
1642 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1644 values [MONO_FIELD_FLAGS] = fb->attrs;
1645 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1647 if (fb->offset != -1) {
1648 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1650 alloc_table (table, table->rows);
1651 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1652 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1653 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1655 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1656 guint32 field_type = 0;
1657 table = &assembly->tables [MONO_TABLE_CONSTANT];
1659 alloc_table (table, table->rows);
1660 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1661 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1662 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1663 values [MONO_CONSTANT_TYPE] = field_type;
1664 values [MONO_CONSTANT_PADDING] = 0;
1666 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1668 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1670 alloc_table (table, table->rows);
1671 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1672 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1674 * We store it in the code section because it's simpler for now.
1677 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1679 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1680 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1682 if (fb->marshal_info) {
1683 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1685 alloc_table (table, table->rows);
1686 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1687 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1688 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1693 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1697 char *b = blob_size;
1698 guint32 nparams = 0;
1699 MonoReflectionMethodBuilder *mb = fb->get_method;
1700 MonoReflectionMethodBuilder *smb = fb->set_method;
1701 guint32 idx, i, size;
1703 if (mb && mb->parameters)
1704 nparams = mono_array_length (mb->parameters);
1705 if (!mb && smb && smb->parameters)
1706 nparams = mono_array_length (smb->parameters) - 1;
1707 size = 24 + nparams * 10;
1708 buf = p = g_malloc (size);
1711 mono_metadata_encode_value (nparams, p, &p);
1713 encode_reflection_type (assembly, mb->rtype, p, &p);
1714 for (i = 0; i < nparams; ++i) {
1715 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1716 encode_reflection_type (assembly, pt, p, &p);
1719 /* the property type is the last param */
1720 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1721 for (i = 0; i < nparams; ++i) {
1722 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1723 encode_reflection_type (assembly, pt, p, &p);
1727 g_assert (p - buf < size);
1728 mono_metadata_encode_value (p-buf, b, &b);
1729 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1735 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1737 MonoDynamicTable *table;
1740 guint num_methods = 0;
1744 * we need to set things in the following tables:
1745 * PROPERTYMAP (info already filled in _get_type_info ())
1746 * PROPERTY (rows already preallocated in _get_type_info ())
1747 * METHOD (method info already done with the generic method code)
1750 table = &assembly->tables [MONO_TABLE_PROPERTY];
1751 pb->table_idx = table->next_idx ++;
1752 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1753 name = mono_string_to_utf8 (pb->name);
1754 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1756 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1757 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1759 /* FIXME: we still don't handle 'other' methods */
1760 if (pb->get_method) num_methods ++;
1761 if (pb->set_method) num_methods ++;
1763 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1764 table->rows += num_methods;
1765 alloc_table (table, table->rows);
1767 if (pb->get_method) {
1768 semaidx = table->next_idx ++;
1769 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1770 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1771 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1772 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1774 if (pb->set_method) {
1775 semaidx = table->next_idx ++;
1776 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1777 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1778 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1779 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1784 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1786 MonoDynamicTable *table;
1789 guint num_methods = 0;
1793 * we need to set things in the following tables:
1794 * EVENTMAP (info already filled in _get_type_info ())
1795 * EVENT (rows already preallocated in _get_type_info ())
1796 * METHOD (method info already done with the generic method code)
1799 table = &assembly->tables [MONO_TABLE_EVENT];
1800 eb->table_idx = table->next_idx ++;
1801 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1802 name = mono_string_to_utf8 (eb->name);
1803 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1805 values [MONO_EVENT_FLAGS] = eb->attrs;
1806 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1809 * FIXME: we still don't handle 'other' methods
1811 if (eb->add_method) num_methods ++;
1812 if (eb->remove_method) num_methods ++;
1813 if (eb->raise_method) num_methods ++;
1815 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1816 table->rows += num_methods;
1817 alloc_table (table, table->rows);
1819 if (eb->add_method) {
1820 semaidx = table->next_idx ++;
1821 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1822 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1823 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1824 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1826 if (eb->remove_method) {
1827 semaidx = table->next_idx ++;
1828 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1829 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1830 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1831 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1833 if (eb->raise_method) {
1834 semaidx = table->next_idx ++;
1835 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1836 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1837 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1838 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1843 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1845 static MonoClass *NewConstraintAttr;
1846 static MonoMethod *NewConstraintAttr_ctor;
1847 MonoDynamicTable *table;
1849 guint32 token, type;
1850 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1853 if (!NewConstraintAttr)
1854 NewConstraintAttr = mono_class_from_name (
1855 mono_defaults.corlib, "System.Runtime.CompilerServices",
1856 "NewConstraintAttribute");
1857 g_assert (NewConstraintAttr);
1859 if (!NewConstraintAttr_ctor) {
1862 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1863 MonoMethod *m = NewConstraintAttr->methods [i];
1865 if (strcmp (m->name, ".ctor"))
1868 NewConstraintAttr_ctor = m;
1872 g_assert (NewConstraintAttr_ctor);
1875 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1877 alloc_table (table, table->rows);
1879 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1880 owner <<= CUSTOM_ATTR_BITS;
1881 owner |= CUSTOM_ATTR_GENERICPAR;
1882 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1884 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1886 type = mono_metadata_token_index (token);
1887 type <<= CUSTOM_ATTR_TYPE_BITS;
1888 switch (mono_metadata_token_table (token)) {
1889 case MONO_TABLE_METHOD:
1890 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1892 case MONO_TABLE_MEMBERREF:
1893 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1896 g_warning ("got wrong token in custom attr");
1899 values [MONO_CUSTOM_ATTR_TYPE] = type;
1901 buf = p = g_malloc (1);
1902 mono_metadata_encode_value (4, p, &p);
1903 g_assert (p-buf == 1);
1905 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1907 values += MONO_CUSTOM_ATTR_SIZE;
1912 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1914 MonoDynamicTable *table;
1915 guint32 num_constraints, i;
1919 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1920 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1921 table->rows += num_constraints;
1922 alloc_table (table, table->rows);
1924 for (i = 0; i < num_constraints; i++) {
1925 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1927 table_idx = table->next_idx ++;
1928 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1930 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1931 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1934 if (gparam->has_ctor_constraint)
1935 encode_new_constraint (assembly, owner);
1939 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1941 MonoDynamicTable *table;
1942 MonoGenericParam *param;
1946 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1947 table_idx = table->next_idx ++;
1948 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1950 param = gparam->type.type->data.generic_param;
1952 values [MONO_GENERICPARAM_OWNER] = owner;
1953 values [MONO_GENERICPARAM_FLAGS] = param->flags;
1954 values [MONO_GENERICPARAM_NUMBER] = param->num;
1955 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1956 values [MONO_GENERICPARAM_KIND] = 0;
1957 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1959 if (gparam->constraints)
1960 encode_constraints (gparam, table_idx, assembly);
1964 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1966 MonoDynamicTable *table;
1969 guint32 cols [MONO_ASSEMBLY_SIZE];
1973 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1976 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1977 table = &assembly->tables [MONO_TABLE_MODULEREF];
1978 token = table->next_idx ++;
1980 alloc_table (table, table->rows);
1981 values = table->values + token * MONO_MODULEREF_SIZE;
1982 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1984 token <<= RESOLTION_SCOPE_BITS;
1985 token |= RESOLTION_SCOPE_MODULEREF;
1986 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1991 if (image->assembly->dynamic)
1993 memset (cols, 0, sizeof (cols));
1995 /* image->assembly->image is the manifest module */
1996 image = image->assembly->image;
1997 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2000 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2001 token = table->next_idx ++;
2003 alloc_table (table, table->rows);
2004 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2005 if (strcmp ("corlib", image->assembly_name) == 0)
2006 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
2008 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2009 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2010 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2011 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2012 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2013 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2014 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2015 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2017 if (strcmp ("", image->assembly->aname.culture)) {
2018 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2019 image->assembly->aname.culture);
2022 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2023 guchar pubtoken [9];
2025 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2026 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2029 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2030 * This is currently only a problem with references to System.Xml (see bug#27706),
2031 * but there may be other cases that makes this necessary. Note, we need to set
2032 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
2033 * recognized by ms, yuck!
2034 * FIXME: need to add more assembly names, as needed.
2036 if (strcmp (image->assembly_name, "corlib") == 0 ||
2037 strcmp (image->assembly_name, "mscorlib") == 0 ||
2038 strcmp (image->assembly_name, "System") == 0 ||
2039 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2040 strcmp (image->assembly_name, "System.Xml") == 0 ||
2041 strcmp (image->assembly_name, "System.Data") == 0 ||
2042 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2043 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2044 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2045 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2046 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2047 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2048 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2049 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2050 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2051 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2052 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2053 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2054 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2055 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2056 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2057 strcmp (image->assembly_name, "System.Design") == 0 ||
2058 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2059 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2060 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2061 strcmp (image->assembly_name, "System.Management") == 0 ||
2062 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2063 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2064 strcmp (image->assembly_name, "System.Security") == 0 ||
2065 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2066 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2067 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2068 strcmp (image->assembly_name, "System.Web") == 0) {
2069 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2070 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2071 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2072 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2074 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2077 token <<= RESOLTION_SCOPE_BITS;
2078 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2079 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2084 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2086 MonoDynamicTable *table;
2092 char *b = blob_size;
2094 switch (type->type) {
2095 case MONO_TYPE_FNPTR:
2097 case MONO_TYPE_SZARRAY:
2098 case MONO_TYPE_ARRAY:
2100 case MONO_TYPE_MVAR:
2101 case MONO_TYPE_GENERICINST:
2102 encode_type (assembly, type, p, &p);
2104 case MONO_TYPE_CLASS:
2105 case MONO_TYPE_VALUETYPE: {
2106 MonoClass *k = mono_class_from_mono_type (type);
2107 if (!k || !k->generic_inst)
2109 encode_generic_inst (assembly, k->generic_inst, p, &p);
2116 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2117 if (assembly->save) {
2118 g_assert (p-sig < 128);
2119 mono_metadata_encode_value (p-sig, b, &b);
2120 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2121 alloc_table (table, table->rows + 1);
2122 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2123 values [MONO_TYPESPEC_SIGNATURE] = token;
2126 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2127 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2133 * Despite the name, we handle also TypeSpec (with the above helper).
2136 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2138 MonoDynamicTable *table;
2140 guint32 token, scope, enclosing;
2143 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2146 token = create_typespec (assembly, type);
2149 klass = my_mono_class_from_mono_type (type);
2151 klass = mono_class_from_mono_type (type);
2154 * If it's in the same module and not a generic type parameter:
2156 if ((klass->image == &assembly->image) &&
2157 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2158 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2159 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2160 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2164 if (klass->nested_in) {
2165 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2166 /* get the typeref idx of the enclosing type */
2167 enclosing >>= TYPEDEFORREF_BITS;
2168 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2170 scope = resolution_scope_from_image (assembly, klass->image);
2172 table = &assembly->tables [MONO_TABLE_TYPEREF];
2173 if (assembly->save) {
2174 alloc_table (table, table->rows + 1);
2175 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2176 values [MONO_TYPEREF_SCOPE] = scope;
2177 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2178 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2180 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2181 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2183 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2188 * Insert a memberef row into the metadata: the token that point to the memberref
2189 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2190 * mono_image_get_fieldref_token()).
2191 * The sig param is an index to an already built signature.
2194 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2196 MonoDynamicTable *table;
2198 guint32 token, pclass;
2201 parent = mono_image_typedef_or_ref (assembly, type);
2202 switch (parent & TYPEDEFORREF_MASK) {
2203 case TYPEDEFORREF_TYPEREF:
2204 pclass = MEMBERREF_PARENT_TYPEREF;
2206 case TYPEDEFORREF_TYPESPEC:
2207 pclass = MEMBERREF_PARENT_TYPESPEC;
2209 case TYPEDEFORREF_TYPEDEF:
2210 pclass = MEMBERREF_PARENT_TYPEDEF;
2213 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2216 /* extract the index */
2217 parent >>= TYPEDEFORREF_BITS;
2219 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2221 if (assembly->save) {
2222 alloc_table (table, table->rows + 1);
2223 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2224 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2225 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2226 values [MONO_MEMBERREF_SIGNATURE] = sig;
2229 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2236 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2240 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2243 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2244 method->name, method_encode_signature (assembly, method->signature));
2245 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2250 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2253 ReflectionMethodBuilder rmb;
2255 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2259 reflection_methodbuilder_from_method_builder (&rmb, mb);
2261 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2262 mono_string_to_utf8 (rmb.name),
2263 method_builder_encode_signature (assembly, &rmb));
2264 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2269 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2272 ReflectionMethodBuilder rmb;
2274 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2278 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2280 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2281 mono_string_to_utf8 (rmb.name),
2282 method_builder_encode_signature (assembly, &rmb));
2283 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2288 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2293 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2296 g_assert (f->field->parent);
2297 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2298 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2299 f->field->name, fieldref_encode_signature (assembly, type));
2300 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2305 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2310 guint32 nparams = gmethod->mtype_argc;
2311 guint32 size = 10 + nparams * 10;
2314 char *b = blob_size;
2316 if (!assembly->save)
2319 p = buf = g_malloc (size);
2321 * FIXME: vararg, explicit_this, differenc call_conv values...
2323 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2324 mono_metadata_encode_value (nparams, p, &p);
2326 for (i = 0; i < nparams; i++)
2327 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2330 g_assert (p - buf < size);
2331 mono_metadata_encode_value (p-buf, b, &b);
2332 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2338 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2340 MonoDynamicTable *table;
2342 guint32 token, mtoken = 0, sig;
2343 MonoMethodInflated *imethod;
2344 MonoMethod *declaring;
2346 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2348 g_assert (method->signature->is_inflated);
2349 imethod = (MonoMethodInflated *) method;
2350 declaring = imethod->declaring;
2352 sig = method_encode_signature (assembly, declaring->signature);
2353 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2354 declaring->name, sig);
2356 if (!declaring->signature->generic_param_count)
2359 switch (mono_metadata_token_table (mtoken)) {
2360 case MONO_TABLE_MEMBERREF:
2361 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2363 case MONO_TABLE_METHOD:
2364 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2367 g_assert_not_reached ();
2370 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2372 if (assembly->save) {
2373 alloc_table (table, table->rows + 1);
2374 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2375 values [MONO_METHODSPEC_METHOD] = mtoken;
2376 values [MONO_METHODSPEC_SIGNATURE] = sig;
2379 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2386 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2388 MonoMethodInflated *imethod;
2391 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2395 g_assert (m->signature->is_inflated);
2396 imethod = (MonoMethodInflated *) m;
2398 if (imethod->declaring->signature->generic_param_count)
2399 token = method_encode_methodspec (assembly, m);
2401 guint32 sig = method_encode_signature (
2402 assembly, imethod->declaring->signature);
2403 token = mono_image_get_memberref_token (
2404 assembly, &m->klass->byval_arg, m->name, sig);
2407 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2412 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2414 MonoDynamicTable *table;
2421 char *b = blob_size;
2424 g_assert (tb->generic_params);
2425 klass = mono_class_from_mono_type (tb->type.type);
2427 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2428 encode_type (assembly, &klass->byval_arg, p, &p);
2430 count = mono_array_length (tb->generic_params);
2431 mono_metadata_encode_value (count, p, &p);
2432 for (i = 0; i < count; i++) {
2433 MonoReflectionGenericParam *gparam;
2435 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2437 encode_type (assembly, gparam->type.type, p, &p);
2440 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2441 if (assembly->save) {
2442 g_assert (p-sig < 128);
2443 mono_metadata_encode_value (p-sig, b, &b);
2444 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2445 alloc_table (table, table->rows + 1);
2446 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2447 values [MONO_TYPESPEC_SIGNATURE] = token;
2450 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2451 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2457 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2459 MonoDynamicTable *table;
2462 guint32 token, pclass, parent, sig;
2465 klass = mono_class_from_mono_type (fb->typeb->type);
2466 name = mono_string_to_utf8 (fb->name);
2468 sig = fieldref_encode_signature (assembly, fb->type->type);
2470 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2471 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2473 pclass = MEMBERREF_PARENT_TYPESPEC;
2474 parent >>= TYPEDEFORREF_BITS;
2476 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2478 if (assembly->save) {
2479 alloc_table (table, table->rows + 1);
2480 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2481 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2482 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2483 values [MONO_MEMBERREF_SIGNATURE] = sig;
2486 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2493 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2501 char *b = blob_size;
2503 if (!assembly->save)
2507 g_assert (helper->type == 2);
2509 if (helper->arguments)
2510 nargs = mono_array_length (helper->arguments);
2514 size = 10 + (nargs * 10);
2516 p = buf = g_malloc (size);
2518 /* Encode calling convention */
2519 /* Change Any to Standard */
2520 if ((helper->call_conv & 0x03) == 0x03)
2521 helper->call_conv = 0x01;
2522 /* explicit_this implies has_this */
2523 if (helper->call_conv & 0x40)
2524 helper->call_conv &= 0x20;
2526 if (helper->call_conv == 0) /* Unmanaged */
2527 *p = helper->unmanaged_call_conv - 1;
2530 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2531 if (helper->call_conv & 0x02) /* varargs */
2536 mono_metadata_encode_value (nargs, p, &p);
2537 encode_reflection_type (assembly, helper->return_type, p, &p);
2538 for (i = 0; i < nargs; ++i) {
2539 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2540 encode_reflection_type (assembly, pt, p, &p);
2543 g_assert (p - buf < size);
2544 mono_metadata_encode_value (p-buf, b, &b);
2545 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2552 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2555 MonoDynamicTable *table;
2558 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2559 idx = table->next_idx ++;
2561 alloc_table (table, table->rows);
2562 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2564 values [MONO_STAND_ALONE_SIGNATURE] =
2565 mono_reflection_encode_sighelper (assembly, helper);
2571 reflection_cc_to_file (int call_conv) {
2572 switch (call_conv & 0x3) {
2574 case 1: return MONO_CALL_DEFAULT;
2575 case 2: return MONO_CALL_VARARG;
2577 g_assert_not_reached ();
2584 MonoMethodSignature *sig;
2590 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2595 MonoMethodSignature *sig;
2598 name = mono_string_to_utf8 (m->name);
2599 nparams = mono_array_length (m->parameters);
2600 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2602 sig->call_convention = reflection_cc_to_file (m->call_conv);
2603 sig->param_count = nparams;
2604 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2605 for (i = 0; i < nparams; ++i) {
2606 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2607 sig->params [i] = t->type;
2610 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2612 if (strcmp (name, am->name) == 0 &&
2613 mono_metadata_type_equal (am->parent, m->parent->type) &&
2614 mono_metadata_signature_equal (am->sig, sig)) {
2617 m->table_idx = am->token & 0xffffff;
2621 am = g_new0 (ArrayMethod, 1);
2624 am->parent = m->parent->type;
2625 am->token = mono_image_get_memberref_token (assembly, am->parent,
2626 name, method_encode_signature (assembly, sig));
2627 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2628 m->table_idx = am->token & 0xffffff;
2633 * Insert into the metadata tables all the info about the TypeBuilder tb.
2634 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2637 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2639 MonoDynamicTable *table;
2641 int i, is_object = 0, is_system = 0;
2644 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2645 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2646 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2647 n = mono_string_to_utf8 (tb->name);
2648 if (strcmp (n, "Object") == 0)
2650 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2652 n = mono_string_to_utf8 (tb->nspace);
2653 if (strcmp (n, "System") == 0)
2655 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2657 if (tb->parent && !(is_system && is_object) &&
2658 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2659 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2661 values [MONO_TYPEDEF_EXTENDS] = 0;
2662 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2663 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2666 * if we have explicitlayout or sequentiallayouts, output data in the
2667 * ClassLayout table.
2669 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2670 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2672 alloc_table (table, table->rows);
2673 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2674 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2675 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2676 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2679 /* handle interfaces */
2680 if (tb->interfaces) {
2681 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2683 table->rows += mono_array_length (tb->interfaces);
2684 alloc_table (table, table->rows);
2685 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2686 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2687 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2688 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2689 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2690 values += MONO_INTERFACEIMPL_SIZE;
2694 /* handle generic parameters */
2695 if (tb->generic_params) {
2696 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2697 table->rows += mono_array_length (tb->generic_params);
2698 alloc_table (table, table->rows);
2699 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2700 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2702 mono_image_get_generic_param_info (
2703 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2709 table = &assembly->tables [MONO_TABLE_FIELD];
2710 table->rows += tb->num_fields;
2711 alloc_table (table, table->rows);
2712 for (i = 0; i < tb->num_fields; ++i)
2713 mono_image_get_field_info (
2714 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2717 /* handle constructors */
2719 table = &assembly->tables [MONO_TABLE_METHOD];
2720 table->rows += mono_array_length (tb->ctors);
2721 alloc_table (table, table->rows);
2722 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2723 mono_image_get_ctor_info (domain,
2724 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2727 /* handle methods */
2729 table = &assembly->tables [MONO_TABLE_METHOD];
2730 table->rows += tb->num_methods;
2731 alloc_table (table, table->rows);
2732 for (i = 0; i < tb->num_methods; ++i)
2733 mono_image_get_method_info (
2734 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2737 /* Do the same with properties etc.. */
2738 if (tb->events && mono_array_length (tb->events)) {
2739 table = &assembly->tables [MONO_TABLE_EVENT];
2740 table->rows += mono_array_length (tb->events);
2741 alloc_table (table, table->rows);
2742 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2744 alloc_table (table, table->rows);
2745 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2746 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2747 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2748 for (i = 0; i < mono_array_length (tb->events); ++i)
2749 mono_image_get_event_info (
2750 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2752 if (tb->properties && mono_array_length (tb->properties)) {
2753 table = &assembly->tables [MONO_TABLE_PROPERTY];
2754 table->rows += mono_array_length (tb->properties);
2755 alloc_table (table, table->rows);
2756 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2758 alloc_table (table, table->rows);
2759 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2760 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2761 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2762 for (i = 0; i < mono_array_length (tb->properties); ++i)
2763 mono_image_get_property_info (
2764 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2767 mono_image_add_decl_security (assembly,
2768 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2772 MonoDynamicTable *ntable;
2774 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2775 ntable->rows += mono_array_length (tb->subtypes);
2776 alloc_table (ntable, ntable->rows);
2777 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2779 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2780 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2782 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2783 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2784 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2785 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2786 mono_string_to_utf8 (tb->name), tb->table_idx,
2787 ntable->next_idx, ntable->rows);*/
2788 values += MONO_NESTED_CLASS_SIZE;
2795 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2799 g_ptr_array_add (types, type);
2801 if (!type->subtypes)
2804 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2805 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2806 collect_types (types, subtype);
2811 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2812 MonoReflectionTypeBuilder **type2)
2814 if ((*type1)->table_idx < (*type2)->table_idx)
2817 if ((*type1)->table_idx > (*type2)->table_idx)
2824 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2829 for (i = 0; i < mono_array_length (pinfo); ++i) {
2830 MonoReflectionParamBuilder *pb;
2831 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2834 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2839 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2842 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2844 for (i = 0; i < tb->num_fields; ++i) {
2845 MonoReflectionFieldBuilder* fb;
2846 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2847 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2851 for (i = 0; i < mono_array_length (tb->events); ++i) {
2852 MonoReflectionEventBuilder* eb;
2853 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2854 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2857 if (tb->properties) {
2858 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2859 MonoReflectionPropertyBuilder* pb;
2860 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2861 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2865 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2866 MonoReflectionCtorBuilder* cb;
2867 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2868 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2869 params_add_cattrs (assembly, cb->pinfo);
2874 for (i = 0; i < tb->num_methods; ++i) {
2875 MonoReflectionMethodBuilder* mb;
2876 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2877 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2878 params_add_cattrs (assembly, mb->pinfo);
2883 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2884 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2889 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2892 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2894 /* no types in the module */
2898 for (i = 0; i < mb->num_types; ++i)
2899 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2903 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2904 MonoDynamicImage *assembly)
2906 MonoDynamicTable *table;
2910 char *b = blob_size;
2913 table = &assembly->tables [MONO_TABLE_FILE];
2915 alloc_table (table, table->rows);
2916 values = table->values + table->next_idx * MONO_FILE_SIZE;
2917 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2918 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2919 if (module->image->dynamic) {
2920 /* This depends on the fact that the main module is emitted last */
2921 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2922 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2926 path = g_strdup (module->image->name);
2928 mono_sha1_get_digest_from_file (path, hash);
2931 mono_metadata_encode_value (20, b, &b);
2932 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2933 mono_image_add_stream_data (&assembly->blob, hash, 20);
2938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2940 MonoDynamicTable *table;
2944 table = &assembly->tables [MONO_TABLE_MODULE];
2945 mb->table_idx = table->next_idx ++;
2946 name = mono_string_to_utf8 (mb->module.name);
2947 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2949 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2952 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2953 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2954 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2958 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2959 guint32 module_index, guint32 parent_index,
2960 MonoDynamicImage *assembly)
2962 MonoDynamicTable *table;
2966 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2967 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2970 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2972 alloc_table (table, table->rows);
2973 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2975 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2976 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2977 if (klass->nested_in)
2978 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2980 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2981 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2982 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2984 res = table->next_idx;
2988 /* Emit nested types */
2989 if (klass->nested_classes) {
2992 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2993 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3000 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3001 guint32 module_index, guint32 parent_index,
3002 MonoDynamicImage *assembly)
3007 klass = mono_class_from_mono_type (tb->type.type);
3009 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3011 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3012 parent_index, assembly);
3016 * We need to do this ourselves since klass->nested_classes is not set up.
3019 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3020 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3025 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3026 guint32 module_index,
3027 MonoDynamicImage *assembly)
3029 MonoImage *image = module->image;
3033 t = &image->tables [MONO_TABLE_TYPEDEF];
3035 for (i = 0; i < t->rows; ++i) {
3036 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3038 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3039 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3043 #define align_pointer(base,p)\
3045 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3047 (p) += 4 - (__diff & 3);\
3051 compare_semantics (const void *a, const void *b)
3053 const guint32 *a_values = a;
3054 const guint32 *b_values = b;
3055 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3058 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3062 compare_custom_attrs (const void *a, const void *b)
3064 const guint32 *a_values = a;
3065 const guint32 *b_values = b;
3067 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3071 compare_field_marshal (const void *a, const void *b)
3073 const guint32 *a_values = a;
3074 const guint32 *b_values = b;
3076 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3080 compare_nested (const void *a, const void *b)
3082 const guint32 *a_values = a;
3083 const guint32 *b_values = b;
3085 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3089 * build_compressed_metadata() fills in the blob of data that represents the
3090 * raw metadata as it will be saved in the PE file. The five streams are output
3091 * and the metadata tables are comnpressed from the guint32 array representation,
3092 * to the compressed on-disk format.
3095 build_compressed_metadata (MonoDynamicImage *assembly)
3097 MonoDynamicTable *table;
3099 guint64 valid_mask = 0;
3100 guint64 sorted_mask;
3101 guint32 heapt_size = 0;
3102 guint32 meta_size = 256; /* allow for header and other stuff */
3103 guint32 table_offset;
3104 guint32 ntables = 0;
3113 MonoDynamicStream *stream;
3116 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3117 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3118 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3119 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3120 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3122 /* tables that are sorted */
3123 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3124 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3125 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3126 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3127 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3128 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3130 /* Compute table sizes */
3131 /* the MonoImage has already been created in mono_image_basic_init() */
3132 meta = &assembly->image;
3134 /* Setup the info used by compute_sizes () */
3135 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3136 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3137 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3139 meta_size += assembly->blob.index;
3140 meta_size += assembly->guid.index;
3141 meta_size += assembly->sheap.index;
3142 meta_size += assembly->us.index;
3144 for (i=0; i < 64; ++i)
3145 meta->tables [i].rows = assembly->tables [i].rows;
3147 for (i = 0; i < 64; i++){
3148 if (meta->tables [i].rows == 0)
3150 valid_mask |= (guint64)1 << i;
3152 meta->tables [i].row_size = mono_metadata_compute_size (
3153 meta, i, &meta->tables [i].size_bitfield);
3154 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3156 heapt_size += 24; /* #~ header size */
3157 heapt_size += ntables * 4;
3158 meta_size += heapt_size;
3159 meta->raw_metadata = g_malloc0 (meta_size);
3160 p = meta->raw_metadata;
3161 /* the metadata signature */
3162 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3163 /* version numbers and 4 bytes reserved */
3164 int16val = (guint16*)p;
3165 *int16val++ = GUINT16_TO_LE (1);
3166 *int16val = GUINT16_TO_LE (1);
3168 /* version string */
3169 int32val = (guint32*)p;
3170 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3172 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3173 p += GUINT32_FROM_LE (*int32val);
3174 align_pointer (meta->raw_metadata, p);
3175 int16val = (guint16*)p;
3176 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3177 *int16val = GUINT16_TO_LE (5); /* number of streams */
3181 * write the stream info.
3183 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3184 table_offset += 3; table_offset &= ~3;
3186 assembly->tstream.index = heapt_size;
3187 for (i = 0; i < 5; ++i) {
3188 int32val = (guint32*)p;
3189 stream_desc [i].stream->offset = table_offset;
3190 *int32val++ = GUINT32_TO_LE (table_offset);
3191 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3192 table_offset += GUINT32_FROM_LE (*int32val);
3193 table_offset += 3; table_offset &= ~3;
3195 strcpy (p, stream_desc [i].name);
3196 p += strlen (stream_desc [i].name) + 1;
3197 align_pointer (meta->raw_metadata, p);
3200 * now copy the data, the table stream header and contents goes first.
3202 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3203 p = meta->raw_metadata + assembly->tstream.offset;
3204 int32val = (guint32*)p;
3205 *int32val = GUINT32_TO_LE (0); /* reserved */
3207 *p++ = 1; /* version */
3209 if (meta->idx_string_wide)
3211 if (meta->idx_guid_wide)
3213 if (meta->idx_blob_wide)
3216 *p++ = 0; /* reserved */
3217 int64val = (guint64*)p;
3218 *int64val++ = GUINT64_TO_LE (valid_mask);
3219 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3221 int32val = (guint32*)p;
3222 for (i = 0; i < 64; i++){
3223 if (meta->tables [i].rows == 0)
3225 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3227 p = (unsigned char*)int32val;
3229 /* sort the tables that still need sorting */
3230 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3232 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3233 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3235 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3236 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3238 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3239 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3241 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3243 /* compress the tables */
3244 for (i = 0; i < 64; i++){
3247 guint32 bitfield = meta->tables [i].size_bitfield;
3248 if (!meta->tables [i].rows)
3250 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3251 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3252 meta->tables [i].base = p;
3253 for (row = 1; row <= meta->tables [i].rows; ++row) {
3254 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3255 for (col = 0; col < assembly->tables [i].columns; ++col) {
3256 switch (mono_metadata_table_size (bitfield, col)) {
3258 *p++ = values [col];
3261 *p++ = values [col] & 0xff;
3262 *p++ = (values [col] >> 8) & 0xff;
3265 *p++ = values [col] & 0xff;
3266 *p++ = (values [col] >> 8) & 0xff;
3267 *p++ = (values [col] >> 16) & 0xff;
3268 *p++ = (values [col] >> 24) & 0xff;
3271 g_assert_not_reached ();
3275 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3278 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3279 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3280 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3281 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3282 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3284 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3288 * Some tables in metadata need to be sorted according to some criteria, but
3289 * when methods and fields are first created with reflection, they may be assigned a token
3290 * that doesn't correspond to the final token they will get assigned after the sorting.
3291 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3292 * with the reflection objects that represent them. Once all the tables are set up, the
3293 * reflection objects will contains the correct table index. fixup_method() will fixup the
3294 * tokens for the method with ILGenerator @ilgen.
3297 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3298 guint32 code_idx = GPOINTER_TO_UINT (value);
3299 MonoReflectionILTokenInfo *iltoken;
3300 MonoReflectionFieldBuilder *field;
3301 MonoReflectionCtorBuilder *ctor;
3302 MonoReflectionMethodBuilder *method;
3303 MonoReflectionTypeBuilder *tb;
3304 MonoReflectionArrayMethod *am;
3306 unsigned char *target;
3308 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3309 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3310 target = assembly->code.data + code_idx + iltoken->code_pos;
3311 switch (target [3]) {
3312 case MONO_TABLE_FIELD:
3313 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3314 field = (MonoReflectionFieldBuilder *)iltoken->member;
3315 idx = field->table_idx;
3316 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3317 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3318 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3320 g_assert_not_reached ();
3323 case MONO_TABLE_METHOD:
3324 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3325 method = (MonoReflectionMethodBuilder *)iltoken->member;
3326 idx = method->table_idx;
3327 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3328 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3329 idx = ctor->table_idx;
3330 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3331 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3332 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3333 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3335 g_assert_not_reached ();
3338 case MONO_TABLE_TYPEDEF:
3339 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3340 g_assert_not_reached ();
3341 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3342 idx = tb->table_idx;
3344 case MONO_TABLE_MEMBERREF:
3345 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3346 am = (MonoReflectionArrayMethod*)iltoken->member;
3347 idx = am->table_idx;
3348 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3349 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3350 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3351 g_assert (m->klass->generic_inst);
3353 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3355 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3356 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3357 g_assert (f->generic_type);
3360 g_assert_not_reached ();
3363 case MONO_TABLE_METHODSPEC:
3364 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3365 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3366 g_assert (m->signature->generic_param_count);
3369 g_assert_not_reached ();
3373 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3375 target [0] = idx & 0xff;
3376 target [1] = (idx >> 8) & 0xff;
3377 target [2] = (idx >> 16) & 0xff;
3384 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3385 * value is not known when the table is emitted.
3388 fixup_cattrs (MonoDynamicImage *assembly)
3390 MonoDynamicTable *table;
3392 guint32 type, i, idx, token;
3395 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3397 for (i = 0; i < table->rows; ++i) {
3398 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3400 type = values [MONO_CUSTOM_ATTR_TYPE];
3401 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3402 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3403 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3404 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3407 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3408 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3409 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3410 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3417 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3419 MonoDynamicTable *table;
3423 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3425 alloc_table (table, table->rows);
3426 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3427 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3428 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3429 name = mono_string_to_utf8 (rsrc->name);
3430 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3432 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3437 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3439 MonoDynamicTable *table;
3443 char *b = blob_size;
3445 guint32 idx, offset;
3447 if (rsrc->filename) {
3448 name = mono_string_to_utf8 (rsrc->filename);
3449 sname = g_path_get_basename (name);
3451 table = &assembly->tables [MONO_TABLE_FILE];
3453 alloc_table (table, table->rows);
3454 values = table->values + table->next_idx * MONO_FILE_SIZE;
3455 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3456 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3459 mono_sha1_get_digest_from_file (name, hash);
3460 mono_metadata_encode_value (20, b, &b);
3461 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3462 mono_image_add_stream_data (&assembly->blob, hash, 20);
3464 idx = table->next_idx++;
3466 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3469 offset = mono_array_length (rsrc->data);
3470 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3471 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3472 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3473 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3477 * The entry should be emitted into the MANIFESTRESOURCE table of
3478 * the main module, but that needs to reference the FILE table
3479 * which isn't emitted yet.
3486 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3490 set_version_from_string (MonoString *version, guint32 *values)
3492 gchar *ver, *p, *str;
3495 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3496 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3497 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3498 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3501 ver = str = mono_string_to_utf8 (version);
3502 for (i = 0; i < 4; ++i) {
3503 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3509 /* handle Revision and Build */
3519 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3523 char *b = blob_size;
3528 len = mono_array_length (pkey);
3529 mono_metadata_encode_value (len, b, &b);
3530 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3531 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3533 /* need to get the actual value from the key type... */
3534 assembly->strong_name_size = 128;
3535 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3541 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3543 MonoDynamicTable *table;
3544 MonoDynamicImage *assembly;
3545 MonoReflectionAssemblyBuilder *assemblyb;
3550 guint32 module_index;
3552 assemblyb = moduleb->assemblyb;
3553 assembly = moduleb->dynamic_image;
3554 domain = mono_object_domain (assemblyb);
3556 /* Emit ASSEMBLY table */
3557 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3558 alloc_table (table, 1);
3559 values = table->values + MONO_ASSEMBLY_SIZE;
3560 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3561 name = mono_string_to_utf8 (assemblyb->name);
3562 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3564 if (assemblyb->culture) {
3565 name = mono_string_to_utf8 (assemblyb->culture);
3566 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3569 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3571 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3572 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3573 set_version_from_string (assemblyb->version, values);
3575 /* Emit FILE + EXPORTED_TYPE table */
3577 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3579 MonoReflectionModuleBuilder *file_module =
3580 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3581 if (file_module != moduleb) {
3582 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3584 if (file_module->types) {
3585 for (j = 0; j < file_module->num_types; ++j) {
3586 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3587 mono_image_fill_export_table (domain, tb, module_index, 0,
3593 if (assemblyb->loaded_modules) {
3594 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3595 MonoReflectionModule *file_module =
3596 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3597 mono_image_fill_file_table (domain, file_module, assembly);
3599 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3603 /* Emit MANIFESTRESOURCE table */
3605 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3607 MonoReflectionModuleBuilder *file_module =
3608 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3609 /* The table for the main module is emitted later */
3610 if (file_module != moduleb) {
3612 if (file_module->resources) {
3613 int len = mono_array_length (file_module->resources);
3614 for (j = 0; j < len; ++j) {
3615 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3616 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3624 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3625 * for the modulebuilder @moduleb.
3626 * At the end of the process, method and field tokens are fixed up and the
3627 * on-disk compressed metadata representation is created.
3630 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3632 MonoDynamicTable *table;
3633 MonoDynamicImage *assembly;
3634 MonoReflectionAssemblyBuilder *assemblyb;
3639 assemblyb = moduleb->assemblyb;
3640 assembly = moduleb->dynamic_image;
3641 domain = mono_object_domain (assemblyb);
3643 if (assembly->text_rva)
3646 assembly->text_rva = START_TEXT_RVA;
3648 if (moduleb->is_main) {
3649 mono_image_emit_manifest (moduleb);
3652 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3653 table->rows = 1; /* .<Module> */
3655 alloc_table (table, table->rows);
3657 * Set the first entry.
3659 values = table->values + table->columns;
3660 values [MONO_TYPEDEF_FLAGS] = 0;
3661 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3662 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3663 values [MONO_TYPEDEF_EXTENDS] = 0;
3664 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3665 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3668 * handle global methods
3669 * FIXME: test what to do when global methods are defined in multiple modules.
3671 if (moduleb->global_methods) {
3672 table = &assembly->tables [MONO_TABLE_METHOD];
3673 table->rows += mono_array_length (moduleb->global_methods);
3674 alloc_table (table, table->rows);
3675 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3676 mono_image_get_method_info (
3677 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3679 if (moduleb->global_fields) {
3680 table = &assembly->tables [MONO_TABLE_FIELD];
3681 table->rows += mono_array_length (moduleb->global_fields);
3682 alloc_table (table, table->rows);
3683 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3684 mono_image_get_field_info (
3685 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3688 table = &assembly->tables [MONO_TABLE_MODULE];
3689 alloc_table (table, 1);
3690 mono_image_fill_module_table (domain, moduleb, assembly);
3694 /* Collect all types into a list sorted by their table_idx */
3695 GPtrArray *types = g_ptr_array_new ();
3698 for (i = 0; i < moduleb->num_types; ++i) {
3699 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3700 collect_types (types, type);
3703 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3704 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3705 table->rows += types->len;
3706 alloc_table (table, table->rows);
3708 for (i = 0; i < types->len; ++i) {
3709 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3710 mono_image_get_type_info (domain, type, assembly);
3712 g_ptr_array_free (types, TRUE);
3716 * table->rows is already set above and in mono_image_fill_module_table.
3718 /* add all the custom attributes at the end, once all the indexes are stable */
3719 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3721 module_add_cattrs (assembly, moduleb);
3724 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3725 fixup_cattrs (assembly);
3729 * mono_image_insert_string:
3730 * @module: module builder object
3733 * Insert @str into the user string stream of @module.
3736 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3738 MonoDynamicImage *assembly;
3743 MONO_ARCH_SAVE_REGS;
3745 if (!module->dynamic_image)
3746 mono_image_module_basic_init (module);
3748 assembly = module->dynamic_image;
3750 if (assembly->save) {
3751 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3752 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3753 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3755 char *swapped = g_malloc (2 * mono_string_length (str));
3756 const char *p = (const char*)mono_string_chars (str);
3758 swap_with_size (swapped, p, 2, mono_string_length (str));
3759 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3763 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3765 mono_image_add_stream_data (&assembly->us, "", 1);
3768 idx = assembly->us.index ++;
3770 mono_g_hash_table_insert (assembly->tokens,
3771 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3773 return MONO_TOKEN_STRING | idx;
3777 * mono_image_create_token:
3778 * @assembly: a dynamic assembly
3781 * Get a token to insert in the IL code stream for the given MemberInfo.
3782 * @obj can be one of:
3783 * ConstructorBuilder
3793 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3798 klass = obj->vtable->klass;
3799 if (strcmp (klass->name, "MethodBuilder") == 0) {
3800 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3802 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3803 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3805 token = mono_image_get_methodbuilder_token (assembly, mb);
3806 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3808 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3809 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3811 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3812 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3814 token = mono_image_get_ctorbuilder_token (assembly, mb);
3815 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3817 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3818 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3819 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3820 if (tb->generic_params) {
3821 token = mono_image_get_generic_field_token (assembly, fb);
3823 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3826 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3827 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3828 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3830 else if (strcmp (klass->name, "MonoType") == 0 ||
3831 strcmp (klass->name, "MonoGenericParam") == 0) {
3832 MonoReflectionType *tb = (MonoReflectionType *)obj;
3833 token = mono_metadata_token_from_dor (
3834 mono_image_typedef_or_ref (assembly, tb->type));
3836 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3837 MonoReflectionType *tb = (MonoReflectionType *)obj;
3838 token = mono_metadata_token_from_dor (
3839 mono_image_typedef_or_ref (assembly, tb->type));
3841 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3842 strcmp (klass->name, "MonoMethod") == 0) {
3843 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3844 if (m->method->signature->is_inflated) {
3845 token = mono_image_get_methodspec_token (assembly, m->method);
3846 } else if (m->method->signature->generic_param_count) {
3847 g_assert_not_reached ();
3848 } else if ((m->method->klass->image == &assembly->image) &&
3849 !m->method->klass->generic_inst) {
3850 static guint32 method_table_idx = 0xffffff;
3852 * Each token should have a unique index, but the indexes are
3853 * assigned by managed code, so we don't know about them. An
3854 * easy solution is to count backwards...
3856 method_table_idx --;
3857 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3859 token = mono_image_get_methodref_token (assembly, m->method);
3860 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3862 else if (strcmp (klass->name, "MonoField") == 0) {
3863 MonoReflectionField *f = (MonoReflectionField *)obj;
3864 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3865 static guint32 field_table_idx = 0xffffff;
3867 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3869 token = mono_image_get_fieldref_token (assembly, f);
3870 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3872 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3873 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3874 token = mono_image_get_array_token (assembly, m);
3876 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3877 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3878 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3881 g_error ("requested token for %s\n", klass->name);
3883 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3890 guint32 import_lookup_table;
3894 guint32 import_address_table_rva;
3902 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3904 static MonoDynamicImage*
3905 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3906 char *assembly_name, char *module_name)
3908 static const guchar entrycode [16] = {0xff, 0x25, 0};
3909 MonoDynamicImage *image;
3913 * We need to use the current ms version or the ms runtime it won't find
3914 * the support dlls. D'oh!
3915 * const char *version = "mono-" VERSION;
3917 const char *version = "v1.0.3705";
3920 image = GC_MALLOC (sizeof (MonoDynamicImage));
3922 image = g_new0 (MonoDynamicImage, 1);
3925 /* keep in sync with image.c */
3926 image->image.name = assembly_name;
3927 image->image.assembly_name = image->image.name; /* they may be different */
3928 image->image.module_name = module_name;
3929 image->image.version = g_strdup (version);
3930 image->image.dynamic = TRUE;
3932 image->image.references = g_new0 (MonoAssembly*, 1);
3933 image->image.references [0] = NULL;
3935 mono_image_init (&image->image);
3937 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3938 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3939 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3940 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3941 image->handleref = g_hash_table_new (NULL, NULL);
3942 image->tokens = mono_g_hash_table_new (NULL, NULL);
3943 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3944 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3946 string_heap_init (&image->sheap);
3947 mono_image_add_stream_data (&image->us, "", 1);
3948 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3949 /* import tables... */
3950 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3951 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3952 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3953 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3954 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3955 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3956 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3957 stream_data_align (&image->code);
3959 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3961 for (i=0; i < 64; ++i) {
3962 image->tables [i].next_idx = 1;
3963 image->tables [i].columns = table_sizes [i];
3966 image->image.assembly = (MonoAssembly*)assembly;
3967 image->run = assembly->run;
3968 image->save = assembly->save;
3974 * mono_image_basic_init:
3975 * @assembly: an assembly builder object
3977 * Create the MonoImage that represents the assembly builder and setup some
3978 * of the helper hash table and the basic metadata streams.
3981 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3983 MonoDynamicAssembly *assembly;
3984 MonoDynamicImage *image;
3986 MONO_ARCH_SAVE_REGS;
3988 if (assemblyb->dynamic_assembly)
3992 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3994 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3997 assembly->assembly.dynamic = TRUE;
3998 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3999 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4000 if (assemblyb->culture)
4001 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4003 assembly->assembly.aname.culture = g_strdup ("");
4005 assembly->run = assemblyb->access != 2;
4006 assembly->save = assemblyb->access != 1;
4008 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4009 assembly->assembly.aname.name = image->image.name;
4010 assembly->assembly.image = &image->image;
4012 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4013 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4017 calc_section_size (MonoDynamicImage *assembly)
4021 /* alignment constraints */
4022 assembly->code.index += 3;
4023 assembly->code.index &= ~3;
4024 assembly->meta_size += 3;
4025 assembly->meta_size &= ~3;
4026 assembly->resources.index += 3;
4027 assembly->resources.index &= ~3;
4029 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4030 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4033 if (assembly->win32_res) {
4034 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4036 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4037 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4041 assembly->sections [MONO_SECTION_RELOC].size = 12;
4042 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4052 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4056 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4058 ResTreeNode *t1 = (ResTreeNode*)a;
4059 ResTreeNode *t2 = (ResTreeNode*)b;
4061 return t1->id - t2->id;
4065 * resource_tree_create:
4067 * Organize the resources into a resource tree.
4069 static ResTreeNode *
4070 resource_tree_create (MonoArray *win32_resources)
4072 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4076 tree = g_new0 (ResTreeNode, 1);
4078 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4079 MonoReflectionWin32Resource *win32_res =
4080 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4084 lang_node = g_new0 (ResTreeNode, 1);
4085 lang_node->id = win32_res->lang_id;
4086 lang_node->win32_res = win32_res;
4088 /* Create type node if neccesary */
4090 for (l = tree->children; l; l = l->next)
4091 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4092 type_node = (ResTreeNode*)l->data;
4097 type_node = g_new0 (ResTreeNode, 1);
4098 type_node->id = win32_res->res_type;
4101 * The resource types have to be sorted otherwise
4102 * Windows Explorer can't display the version information.
4104 tree->children = g_slist_insert_sorted (tree->children, type_node,
4105 resource_tree_compare_by_id);
4108 /* Create res node if neccesary */
4110 for (l = type_node->children; l; l = l->next)
4111 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4112 res_node = (ResTreeNode*)l->data;
4117 res_node = g_new0 (ResTreeNode, 1);
4118 res_node->id = win32_res->res_id;
4119 type_node->children = g_slist_append (type_node->children, res_node);
4122 res_node->children = g_slist_append (res_node->children, lang_node);
4129 * resource_tree_encode:
4131 * Encode the resource tree into the format used in the PE file.
4134 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4137 MonoPEResourceDir dir;
4138 MonoPEResourceDirEntry dir_entry;
4139 MonoPEResourceDataEntry data_entry;
4143 * For the format of the resource directory, see the article
4144 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4148 memset (&dir, 0, sizeof (dir));
4149 memset (&dir_entry, 0, sizeof (dir_entry));
4150 memset (&data_entry, 0, sizeof (data_entry));
4152 g_assert (sizeof (dir) == 16);
4153 g_assert (sizeof (dir_entry) == 8);
4154 g_assert (sizeof (data_entry) == 16);
4156 node->offset = p - begin;
4158 /* IMAGE_RESOURCE_DIRECTORY */
4159 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4161 memcpy (p, &dir, sizeof (dir));
4164 /* Reserve space for entries */
4166 p += sizeof (dir_entry) * dir.res_id_entries;
4168 /* Write children */
4169 for (l = node->children; l; l = l->next) {
4170 ResTreeNode *child = (ResTreeNode*)l->data;
4172 if (child->win32_res) {
4174 child->offset = p - begin;
4176 /* IMAGE_RESOURCE_DATA_ENTRY */
4177 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4178 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4180 memcpy (p, &data_entry, sizeof (data_entry));
4181 p += sizeof (data_entry);
4183 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4184 p += data_entry.rde_size;
4187 resource_tree_encode (child, begin, p, &p);
4190 /* IMAGE_RESOURCE_ENTRY */
4191 for (l = node->children; l; l = l->next) {
4192 ResTreeNode *child = (ResTreeNode*)l->data;
4193 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4195 dir_entry.is_dir = child->win32_res ? 0 : 1;
4196 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4198 memcpy (entries, &dir_entry, sizeof (dir_entry));
4199 entries += sizeof (dir_entry);
4206 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4211 MonoReflectionWin32Resource *win32_res;
4214 if (!assemblyb->win32_resources)
4218 * Resources are stored in a three level tree inside the PE file.
4219 * - level one contains a node for each type of resource
4220 * - level two contains a node for each resource
4221 * - level three contains a node for each instance of a resource for a
4222 * specific language.
4225 tree = resource_tree_create (assemblyb->win32_resources);
4227 /* Estimate the size of the encoded tree */
4229 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4230 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4231 size += mono_array_length (win32_res->res_data);
4233 /* Directory structure */
4234 size += mono_array_length (assemblyb->win32_resources) * 256;
4235 p = buf = g_malloc (size);
4237 resource_tree_encode (tree, p, p, &p);
4239 g_assert (p - buf < size);
4241 assembly->win32_res = g_malloc (p - buf);
4242 assembly->win32_res_size = p - buf;
4243 memcpy (assembly->win32_res, buf, p - buf);
4249 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4251 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4254 p += sizeof (MonoPEResourceDir);
4255 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4256 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4257 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4258 if (dir_entry->is_dir)
4259 fixup_resource_directory (res_section, child, rva);
4261 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4262 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4265 p += sizeof (MonoPEResourceDirEntry);
4270 * mono_image_create_pefile:
4271 * @mb: a module builder object
4273 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4274 * assembly->pefile where it can be easily retrieved later in chunks.
4277 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4278 MonoMSDOSHeader *msdos;
4279 MonoDotNetHeader *header;
4280 MonoSectionTable *section;
4281 MonoCLIHeader *cli_header;
4282 guint32 size, image_size, virtual_base, text_offset;
4283 guint32 header_start, section_start, file_offset, virtual_offset;
4284 MonoDynamicImage *assembly;
4285 MonoReflectionAssemblyBuilder *assemblyb;
4286 MonoDynamicStream *pefile;
4288 guint32 *rva, value;
4291 static const unsigned char msheader[] = {
4292 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4293 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4296 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4297 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4298 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4299 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4302 assemblyb = mb->assemblyb;
4304 mono_image_basic_init (assemblyb);
4305 assembly = mb->dynamic_image;
4307 /* already created */
4308 if (assembly->pefile.index)
4311 mono_image_build_metadata (mb);
4313 if (mb->is_main && assemblyb->resources) {
4314 int len = mono_array_length (assemblyb->resources);
4315 for (i = 0; i < len; ++i)
4316 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4319 if (mb->resources) {
4320 int len = mono_array_length (mb->resources);
4321 for (i = 0; i < len; ++i)
4322 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4325 build_compressed_metadata (assembly);
4328 assembly_add_win32_resources (assembly, assemblyb);
4330 nsections = calc_section_size (assembly);
4332 pefile = &assembly->pefile;
4334 /* The DOS header and stub */
4335 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4336 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4338 /* the dotnet header */
4339 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4341 /* the section tables */
4342 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4344 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4345 virtual_offset = VIRT_ALIGN;
4348 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4349 if (!assembly->sections [i].size)
4352 file_offset += FILE_ALIGN - 1;
4353 file_offset &= ~(FILE_ALIGN - 1);
4354 virtual_offset += VIRT_ALIGN - 1;
4355 virtual_offset &= ~(VIRT_ALIGN - 1);
4357 assembly->sections [i].offset = file_offset;
4358 assembly->sections [i].rva = virtual_offset;
4360 file_offset += assembly->sections [i].size;
4361 virtual_offset += assembly->sections [i].size;
4362 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4365 file_offset += FILE_ALIGN - 1;
4366 file_offset &= ~(FILE_ALIGN - 1);
4367 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4369 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4371 /* back-patch info */
4372 msdos = (MonoMSDOSHeader*)pefile->data;
4373 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4374 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4375 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4377 header = (MonoDotNetHeader*)(pefile->data + header_start);
4378 header->pesig [0] = 'P';
4379 header->pesig [1] = 'E';
4381 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4382 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4383 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4384 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4385 if (assemblyb->pekind == 1) {
4387 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4390 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4393 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4395 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4396 header->pe.pe_major = 6;
4397 header->pe.pe_minor = 0;
4398 size = assembly->sections [MONO_SECTION_TEXT].size;
4399 size += FILE_ALIGN - 1;
4400 size &= ~(FILE_ALIGN - 1);
4401 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4402 size = assembly->sections [MONO_SECTION_RSRC].size;
4403 size += FILE_ALIGN - 1;
4404 size &= ~(FILE_ALIGN - 1);
4405 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4406 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4407 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4408 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4409 /* pe_rva_entry_point always at the beginning of the text section */
4410 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4412 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4413 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4414 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4415 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4416 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4417 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4418 size = section_start;
4419 size += FILE_ALIGN - 1;
4420 size &= ~(FILE_ALIGN - 1);
4421 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4423 size += VIRT_ALIGN - 1;
4424 size &= ~(VIRT_ALIGN - 1);
4425 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4428 // Translate the PEFileKind value to the value expected by the Windows loader
4431 short kind = assemblyb->pekind;
4434 // PEFileKinds.ConsoleApplication == 2
4435 // PEFileKinds.WindowApplication == 3
4438 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4439 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4445 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4447 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4448 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4449 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4450 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4451 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4452 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4454 /* fill data directory entries */
4456 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4457 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4459 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4460 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4462 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4463 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4464 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4465 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4466 /* patch imported function RVA name */
4467 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4468 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4470 /* the import table */
4471 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4472 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4473 /* patch imported dll RVA name and other entries in the dir */
4474 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4475 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4476 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4477 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4478 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4479 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4481 p = (assembly->code.data + assembly->ilt_offset);
4482 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4483 *p++ = (value) & 0xff;
4484 *p++ = (value >> 8) & (0xff);
4485 *p++ = (value >> 16) & (0xff);
4486 *p++ = (value >> 24) & (0xff);
4488 /* the CLI header info */
4489 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4490 cli_header->ch_size = GUINT32_FROM_LE (72);
4491 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4492 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4493 if (assemblyb->entry_point) {
4494 guint32 table_idx = 0;
4495 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4496 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4497 table_idx = methodb->table_idx;
4500 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4501 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4504 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4505 /* The embedded managed resources */
4506 text_offset = assembly->text_rva + assembly->code.index;
4507 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4508 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4509 text_offset += assembly->resources.index;
4510 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4511 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4512 text_offset += assembly->meta_size;
4513 if (assembly->strong_name_size) {
4514 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4515 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4516 text_offset += assembly->strong_name_size;
4519 /* write the section tables and section content */
4520 section = (MonoSectionTable*)(pefile->data + section_start);
4521 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4522 static const char *section_names [] = {
4523 ".text", ".rsrc", ".reloc"
4525 if (!assembly->sections [i].size)
4527 strcpy (section->st_name, section_names [i]);
4528 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4529 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4530 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4531 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4532 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4533 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4534 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4536 case MONO_SECTION_TEXT:
4537 /* patch entry point */
4538 p = (assembly->code.data + 2);
4539 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4540 *p++ = (value) & 0xff;
4541 *p++ = (value >> 8) & 0xff;
4542 *p++ = (value >> 16) & 0xff;
4543 *p++ = (value >> 24) & 0xff;
4545 text_offset = assembly->sections [i].offset;
4546 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4547 text_offset += assembly->code.index;
4548 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4549 text_offset += assembly->resources.index;
4550 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4551 text_offset += assembly->meta_size;
4552 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4554 g_free (assembly->image.raw_metadata);
4556 case MONO_SECTION_RELOC:
4557 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4558 *rva = GUINT32_FROM_LE (assembly->text_rva);
4560 *rva = GUINT32_FROM_LE (12);
4562 data16 = (guint16*)rva;
4564 * the entrypoint is always at the start of the text section
4565 * 3 is IMAGE_REL_BASED_HIGHLOW
4566 * 2 is patch_size_rva - text_rva
4568 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4570 *data16 = 0; /* terminate */
4572 case MONO_SECTION_RSRC:
4573 if (assembly->win32_res) {
4574 text_offset = assembly->sections [i].offset;
4576 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4577 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4579 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4583 g_assert_not_reached ();
4588 /* check that the file is properly padded */
4591 FILE *f = fopen ("mypetest.exe", "w");
4592 fwrite (pefile->data, pefile->index, 1, f);
4598 MonoReflectionModule *
4599 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4603 MonoImageOpenStatus status;
4604 MonoDynamicAssembly *assembly;
4606 name = mono_string_to_utf8 (fileName);
4608 image = mono_image_open (name, &status);
4611 if (status == MONO_IMAGE_ERROR_ERRNO)
4612 exc = mono_get_exception_file_not_found (fileName);
4614 exc = mono_get_exception_bad_image_format (name);
4616 mono_raise_exception (exc);
4621 assembly = ab->dynamic_assembly;
4622 image->assembly = (MonoAssembly*)assembly;
4624 mono_assembly_load_references (image, &status);
4626 mono_image_close (image);
4627 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4630 return mono_module_get_object (mono_domain_get (), image);
4634 * We need to return always the same object for MethodInfo, FieldInfo etc..
4635 * but we need to consider the reflected type.
4636 * type uses a different hash, since it uses custom hash/equal functions.
4641 MonoClass *refclass;
4645 reflected_equal (gconstpointer a, gconstpointer b) {
4646 const ReflectedEntry *ea = a;
4647 const ReflectedEntry *eb = b;
4649 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4653 reflected_hash (gconstpointer a) {
4654 const ReflectedEntry *ea = a;
4655 return GPOINTER_TO_UINT (ea->item);
4658 #define CHECK_OBJECT(t,p,k) \
4664 mono_domain_lock (domain); \
4665 if (!domain->refobject_hash) \
4666 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4667 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4668 mono_domain_unlock (domain); \
4674 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4676 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4679 #define CACHE_OBJECT(p,o,k) \
4681 ReflectedEntry *e = ALLOC_REFENTRY; \
4683 e->refclass = (k); \
4684 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4685 mono_domain_unlock (domain); \
4689 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4691 /* this is done only once */
4692 mono_domain_lock (domain);
4693 CACHE_OBJECT (assembly, res, NULL);
4697 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4699 /* this is done only once */
4700 mono_domain_lock (domain);
4701 CACHE_OBJECT (module, res, NULL);
4705 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4707 MonoDynamicImage *image = moduleb->dynamic_image;
4708 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4711 * FIXME: we already created an image in mono_image_basic_init (), but
4712 * we don't know which module it belongs to, since that is only
4713 * determined at assembly save time.
4715 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4716 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4718 moduleb->module.image = &image->image;
4719 moduleb->dynamic_image = image;
4720 register_module (mono_object_domain (moduleb), moduleb, image);
4725 * mono_assembly_get_object:
4726 * @domain: an app domain
4727 * @assembly: an assembly
4729 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4731 MonoReflectionAssembly*
4732 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4734 static MonoClass *System_Reflection_Assembly;
4735 MonoReflectionAssembly *res;
4737 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4738 if (!System_Reflection_Assembly)
4739 System_Reflection_Assembly = mono_class_from_name (
4740 mono_defaults.corlib, "System.Reflection", "Assembly");
4741 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4742 res->assembly = assembly;
4743 CACHE_OBJECT (assembly, res, NULL);
4749 MonoReflectionModule*
4750 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4752 static MonoClass *System_Reflection_Module;
4753 MonoReflectionModule *res;
4755 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4756 if (!System_Reflection_Module)
4757 System_Reflection_Module = mono_class_from_name (
4758 mono_defaults.corlib, "System.Reflection", "Module");
4759 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4762 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4764 res->fqname = mono_string_new (domain, image->name);
4765 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4766 res->scopename = mono_string_new (domain, image->module_name);
4768 mono_image_addref (image);
4770 CACHE_OBJECT (image, res, NULL);
4774 MonoReflectionModule*
4775 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4777 static MonoClass *System_Reflection_Module;
4778 MonoReflectionModule *res;
4779 MonoTableInfo *table;
4780 guint32 cols [MONO_FILE_SIZE];
4782 guint32 i, name_idx;
4785 if (!System_Reflection_Module)
4786 System_Reflection_Module = mono_class_from_name (
4787 mono_defaults.corlib, "System.Reflection", "Module");
4788 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4790 table = &image->tables [MONO_TABLE_FILE];
4791 g_assert (table_index < table->rows);
4792 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4795 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4796 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4798 // Check whenever the row has a corresponding row in the moduleref table
4799 table = &image->tables [MONO_TABLE_MODULEREF];
4800 for (i = 0; i < table->rows; ++i) {
4801 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4802 val = mono_metadata_string_heap (image, name_idx);
4803 if (strcmp (val, name) == 0)
4804 res->image = image->modules [i];
4807 res->fqname = mono_string_new (domain, name);
4808 res->name = mono_string_new (domain, name);
4809 res->scopename = mono_string_new (domain, name);
4810 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4816 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4818 if ((t1->type != t2->type) ||
4819 (t1->byref != t2->byref))
4823 case MONO_TYPE_VOID:
4824 case MONO_TYPE_BOOLEAN:
4825 case MONO_TYPE_CHAR:
4836 case MONO_TYPE_STRING:
4839 case MONO_TYPE_OBJECT:
4840 case MONO_TYPE_TYPEDBYREF:
4842 case MONO_TYPE_VALUETYPE:
4843 case MONO_TYPE_CLASS:
4844 case MONO_TYPE_SZARRAY:
4845 return t1->data.klass == t2->data.klass;
4847 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4848 case MONO_TYPE_ARRAY:
4849 if (t1->data.array->rank != t2->data.array->rank)
4851 return t1->data.array->eklass == t2->data.array->eklass;
4852 case MONO_TYPE_GENERICINST: {
4854 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4856 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4858 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4859 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4865 case MONO_TYPE_MVAR:
4866 return t1->data.generic_param == t2->data.generic_param;
4868 g_error ("implement type compare for %0x!", t1->type);
4876 mymono_metadata_type_hash (MonoType *t1)
4882 hash |= t1->byref << 6; /* do not collide with t1->type values */
4884 case MONO_TYPE_VALUETYPE:
4885 case MONO_TYPE_CLASS:
4886 case MONO_TYPE_SZARRAY:
4887 /* check if the distribution is good enough */
4888 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4890 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4895 static MonoReflectionGenericInst*
4896 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4898 static MonoClass *System_Reflection_MonoGenericInst;
4899 MonoReflectionGenericInst *res;
4900 MonoGenericInst *ginst;
4903 if (!System_Reflection_MonoGenericInst) {
4904 System_Reflection_MonoGenericInst = mono_class_from_name (
4905 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4906 g_assert (System_Reflection_MonoGenericInst);
4909 ginst = geninst->data.generic_inst;
4910 gklass = mono_class_from_mono_type (ginst->generic_type);
4912 mono_class_init (ginst->klass);
4914 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4916 res->type.type = geninst;
4917 if (gklass->wastypebuilder && gklass->reflection_info)
4918 res->generic_type = gklass->reflection_info;
4920 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4926 * mono_type_get_object:
4927 * @domain: an app domain
4930 * Return an System.MonoType object representing the type @type.
4933 mono_type_get_object (MonoDomain *domain, MonoType *type)
4935 MonoReflectionType *res;
4936 MonoClass *klass = mono_class_from_mono_type (type);
4938 mono_domain_lock (domain);
4939 if (!domain->type_hash)
4940 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4941 (GCompareFunc)mymono_metadata_type_equal);
4942 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4943 mono_domain_unlock (domain);
4946 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4947 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4948 mono_g_hash_table_insert (domain->type_hash, type, res);
4949 mono_domain_unlock (domain);
4952 if (klass->reflection_info && !klass->wastypebuilder) {
4953 //g_assert_not_reached ();
4954 /* should this be considered an error condition? */
4956 mono_domain_unlock (domain);
4957 return klass->reflection_info;
4960 mono_class_init (klass);
4961 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4963 mono_g_hash_table_insert (domain->type_hash, type, res);
4964 mono_domain_unlock (domain);
4969 * mono_method_get_object:
4970 * @domain: an app domain
4972 * @refclass: the reflected type (can be NULL)
4974 * Return an System.Reflection.MonoMethod object representing the method @method.
4976 MonoReflectionMethod*
4977 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4980 * We use the same C representation for methods and constructors, but the type
4981 * name in C# is different.
4985 MonoReflectionMethod *ret;
4988 refclass = method->klass;
4990 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4991 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4992 cname = "MonoCMethod";
4994 cname = "MonoMethod";
4995 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4997 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4998 ret->method = method;
4999 ret->name = mono_string_new (domain, method->name);
5000 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5001 CACHE_OBJECT (method, ret, refclass);
5006 * mono_field_get_object:
5007 * @domain: an app domain
5011 * Return an System.Reflection.MonoField object representing the field @field
5014 MonoReflectionField*
5015 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5017 MonoReflectionField *res;
5020 CHECK_OBJECT (MonoReflectionField *, field, klass);
5021 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5022 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5025 res->name = mono_string_new (domain, field->name);
5026 res->attrs = field->type->attrs;
5027 res->type = mono_type_get_object (domain, field->type);
5028 CACHE_OBJECT (field, res, klass);
5033 * mono_property_get_object:
5034 * @domain: an app domain
5036 * @property: a property
5038 * Return an System.Reflection.MonoProperty object representing the property @property
5041 MonoReflectionProperty*
5042 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5044 MonoReflectionProperty *res;
5047 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5048 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5049 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5051 res->property = property;
5052 CACHE_OBJECT (property, res, klass);
5057 * mono_event_get_object:
5058 * @domain: an app domain
5062 * Return an System.Reflection.MonoEvent object representing the event @event
5065 MonoReflectionEvent*
5066 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5068 MonoReflectionEvent *res;
5071 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5072 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5073 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5076 CACHE_OBJECT (event, res, klass);
5081 * mono_param_get_objects:
5082 * @domain: an app domain
5085 * Return an System.Reflection.ParameterInfo array object representing the parameters
5086 * in the method @method.
5089 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5091 static MonoClass *System_Reflection_ParameterInfo;
5092 MonoArray *res = NULL;
5093 MonoReflectionMethod *member = NULL;
5094 MonoReflectionParameter *param = NULL;
5098 if (!System_Reflection_ParameterInfo)
5099 System_Reflection_ParameterInfo = mono_class_from_name (
5100 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5102 if (!method->signature->param_count)
5103 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5105 /* Note: the cache is based on the address of the signature into the method
5106 * since we already cache MethodInfos with the method as keys.
5108 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5110 member = mono_method_get_object (domain, method, NULL);
5111 names = g_new (char *, method->signature->param_count);
5112 mono_method_get_param_names (method, (const char **) names);
5114 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5115 for (i = 0; i < method->signature->param_count; ++i) {
5116 param = (MonoReflectionParameter *)mono_object_new (domain,
5117 System_Reflection_ParameterInfo);
5118 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5119 param->DefaultValueImpl = NULL; /* FIXME */
5120 param->MemberImpl = (MonoObject*)member;
5121 param->NameImpl = mono_string_new (domain, names [i]);
5122 param->PositionImpl = i;
5123 param->AttrsImpl = method->signature->params [i]->attrs;
5124 mono_array_set (res, gpointer, i, param);
5127 CACHE_OBJECT (&(method->signature), res, NULL);
5132 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5136 memset (assembly, 0, sizeof (MonoAssemblyName));
5138 assembly->culture = "";
5140 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5143 while (*p == ' ' || *p == ',') {
5152 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5154 assembly->major = strtoul (p, &s, 10);
5155 if (s == p || *s != '.')
5158 assembly->minor = strtoul (p, &s, 10);
5159 if (s == p || *s != '.')
5162 assembly->build = strtoul (p, &s, 10);
5163 if (s == p || *s != '.')
5166 assembly->revision = strtoul (p, &s, 10);
5169 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5171 if (strncmp (p, "neutral", 7) == 0) {
5172 assembly->culture = "";
5175 assembly->culture = p;
5176 while (*p && *p != ',') {
5180 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5183 while (*s && isxdigit (*s)) {
5187 assembly->hash_len = s - p;
5188 if (!(s-p) || ((s-p) & 1))
5190 assembly->hash_value = s = p;
5191 while (*s && isxdigit (*s)) {
5193 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5196 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5201 while (*p && *p != ',')
5205 while (*p == ' ' || *p == ',') {
5219 * mono_reflection_parse_type:
5222 * Parse a type name as accepted by the GetType () method and output the info
5223 * extracted in the info structure.
5224 * the name param will be mangled, so, make a copy before passing it to this function.
5225 * The fields in info will be valid until the memory pointed to by name is valid.
5226 * Returns 0 on parse error.
5227 * See also mono_type_get_name () below.
5230 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5232 char *start, *p, *w, *last_point, *startn;
5233 int in_modifiers = 0;
5234 int isbyref = 0, rank;
5236 start = p = w = name;
5238 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5239 info->name = info->name_space = NULL;
5240 info->nested = NULL;
5241 info->modifiers = NULL;
5243 /* last_point separates the namespace from the name */
5249 *p = 0; /* NULL terminate the name */
5251 info->nested = g_list_append (info->nested, startn);
5252 /* we have parsed the nesting namespace + name */
5256 info->name_space = start;
5258 info->name = last_point + 1;
5260 info->name_space = (char *)"";
5286 info->name_space = start;
5288 info->name = last_point + 1;
5290 info->name_space = (char *)"";
5297 if (isbyref) /* only one level allowed by the spec */
5300 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5304 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5315 else if (*p != '*') /* '*' means unknown lower bound */
5321 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5333 return 0; /* missing assembly name */
5334 if (!assembly_name_to_aname (&info->assembly, p))
5341 if (info->assembly.name)
5344 *w = 0; /* terminate class name */
5345 if (!info->name || !*info->name)
5347 /* add other consistency checks */
5352 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5359 image = mono_defaults.corlib;
5362 klass = mono_class_from_name_case (image, info->name_space, info->name);
5364 klass = mono_class_from_name (image, info->name_space, info->name);
5367 for (mod = info->nested; mod; mod = mod->next) {
5370 mono_class_init (klass);
5371 nested = klass->nested_classes;
5374 klass = nested->data;
5376 if (g_strcasecmp (klass->name, mod->data) == 0)
5379 if (strcmp (klass->name, mod->data) == 0)
5383 nested = nested->next;
5390 mono_class_init (klass);
5391 for (mod = info->modifiers; mod; mod = mod->next) {
5392 modval = GPOINTER_TO_UINT (mod->data);
5393 if (!modval) { /* byref: must be last modifier */
5394 return &klass->this_arg;
5395 } else if (modval == -1) {
5396 klass = mono_ptr_class_get (&klass->byval_arg);
5397 } else { /* array rank */
5398 klass = mono_array_class_get (klass, modval);
5400 mono_class_init (klass);
5403 return &klass->byval_arg;
5407 * mono_reflection_get_type:
5408 * @image: a metadata context
5409 * @info: type description structure
5410 * @ignorecase: flag for case-insensitive string compares
5412 * Build a MonoType from the type description in @info.
5417 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5420 MonoReflectionAssembly *assembly;
5424 type = mono_reflection_get_type_internal (image, info, ignorecase);
5427 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5430 // Reconstruct the type name
5431 fullName = g_string_new ("");
5432 if (info->name_space && (info->name_space [0] != '\0'))
5433 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5435 g_string_printf (fullName, info->name);
5436 for (mod = info->nested; mod; mod = mod->next)
5437 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5440 mono_domain_try_type_resolve (
5441 mono_domain_get (), fullName->str, NULL);
5442 if (assembly && (!image || (assembly->assembly->image == image)))
5443 type = mono_reflection_get_type_internal (assembly->assembly->image,
5445 g_string_free (fullName, TRUE);
5450 * mono_reflection_type_from_name:
5452 * @image: a metadata context (can be NULL).
5454 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5455 * it defaults to get the type from @image or, if @image is NULL or loading
5456 * from it fails, uses corlib.
5460 mono_reflection_type_from_name (char *name, MonoImage *image)
5463 MonoTypeNameParse info;
5464 MonoAssembly *assembly;
5466 /*g_print ("requested type %s\n", str);*/
5467 if (!mono_reflection_parse_type (name, &info)) {
5468 g_list_free (info.modifiers);
5469 g_list_free (info.nested);
5473 if (info.assembly.name) {
5474 assembly = mono_assembly_loaded (&info.assembly);
5475 /* do we need to load if it's not already loaded? */
5477 g_list_free (info.modifiers);
5478 g_list_free (info.nested);
5482 image = assembly->image;
5483 } else if (image == NULL) {
5484 image = mono_defaults.corlib;
5487 type = mono_reflection_get_type (image, &info, FALSE);
5488 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5489 image = mono_defaults.corlib;
5490 type = mono_reflection_get_type (image, &info, FALSE);
5493 g_list_free (info.modifiers);
5494 g_list_free (info.nested);
5499 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5501 int slen, type = t->type;
5506 case MONO_TYPE_BOOLEAN: {
5507 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5512 case MONO_TYPE_CHAR:
5514 case MONO_TYPE_I2: {
5515 guint16 *val = g_malloc (sizeof (guint16));
5520 #if SIZEOF_VOID_P == 4
5526 case MONO_TYPE_I4: {
5527 guint32 *val = g_malloc (sizeof (guint32));
5532 #if SIZEOF_VOID_P == 8
5533 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5538 case MONO_TYPE_I8: {
5539 guint64 *val = g_malloc (sizeof (guint64));
5544 case MONO_TYPE_VALUETYPE:
5545 if (t->data.klass->enumtype) {
5546 type = t->data.klass->enum_basetype->type;
5549 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5552 case MONO_TYPE_STRING:
5553 if (*p == (char)0xFF) {
5557 slen = mono_metadata_decode_value (p, &p);
5559 return mono_string_new_len (mono_domain_get (), p, slen);
5560 case MONO_TYPE_CLASS: {
5563 if (*p == (char)0xFF) {
5568 slen = mono_metadata_decode_value (p, &p);
5569 n = g_memdup (p, slen + 1);
5571 t = mono_reflection_type_from_name (n, image);
5573 g_warning ("Cannot load type '%s'", n);
5577 return mono_type_get_object (mono_domain_get (), t);
5581 case MONO_TYPE_OBJECT: {
5584 MonoClass *subc = NULL;
5589 } else if (subt == 0x0E) {
5590 type = MONO_TYPE_STRING;
5592 } else if (subt == 0x55) {
5595 slen = mono_metadata_decode_value (p, &p);
5596 n = g_memdup (p, slen + 1);
5598 t = mono_reflection_type_from_name (n, image);
5600 g_warning ("Cannot load type '%s'", n);
5603 subc = mono_class_from_mono_type (t);
5604 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5605 MonoType simple_type = {{0}};
5606 simple_type.type = subt;
5607 subc = mono_class_from_mono_type (&simple_type);
5609 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5611 val = load_cattr_value (image, &subc->byval_arg, p, end);
5612 obj = mono_object_new (mono_domain_get (), subc);
5613 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5617 case MONO_TYPE_SZARRAY:
5620 guint32 i, alen, basetype;
5623 if (alen == 0xffffffff) {
5627 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5628 basetype = t->data.klass->byval_arg.type;
5633 case MONO_TYPE_BOOLEAN:
5634 for (i=0;i<alen;i++)
5636 MonoBoolean val=*p++;
5637 mono_array_set(arr,MonoBoolean,i,val);
5640 case MONO_TYPE_CHAR:
5643 for (i=0;i<alen;i++)
5645 guint16 val=read16(p);
5646 mono_array_set(arr,guint16,i,val);
5653 for (i=0;i<alen;i++)
5655 guint32 val=read32(p);
5656 mono_array_set(arr,guint32,i,val);
5663 for (i=0;i<alen;i++)
5665 guint64 val=read64(p);
5666 mono_array_set(arr,guint64,i,val);
5670 case MONO_TYPE_CLASS:
5671 case MONO_TYPE_STRING:
5672 for (i = 0; i < alen; i++) {
5673 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5674 mono_array_set (arr, gpointer, i, item);
5678 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5684 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5690 type_is_reference (MonoType *type)
5692 switch (type->type) {
5693 case MONO_TYPE_BOOLEAN:
5694 case MONO_TYPE_CHAR:
5707 case MONO_TYPE_VALUETYPE:
5715 free_param_data (MonoMethodSignature *sig, void **params) {
5717 for (i = 0; i < sig->param_count; ++i) {
5718 if (!type_is_reference (sig->params [i]))
5719 g_free (params [i]);
5724 * Find the method index in the metadata methodDef table.
5725 * Later put these three helper methods in metadata and export them.
5728 find_method_index (MonoMethod *method) {
5729 MonoClass *klass = method->klass;
5732 for (i = 0; i < klass->method.count; ++i) {
5733 if (method == klass->methods [i])
5734 return klass->method.first + 1 + i;
5740 * Find the field index in the metadata FieldDef table.
5743 find_field_index (MonoClass *klass, MonoClassField *field) {
5746 for (i = 0; i < klass->field.count; ++i) {
5747 if (field == &klass->fields [i])
5748 return klass->field.first + 1 + i;
5754 * Find the property index in the metadata Property table.
5757 find_property_index (MonoClass *klass, MonoProperty *property) {
5760 for (i = 0; i < klass->property.count; ++i) {
5761 if (property == &klass->properties [i])
5762 return klass->property.first + 1 + i;
5768 * Find the event index in the metadata Event table.
5771 find_event_index (MonoClass *klass, MonoEvent *event) {
5774 for (i = 0; i < klass->event.count; ++i) {
5775 if (event == &klass->events [i])
5776 return klass->event.first + 1 + i;
5782 create_custom_attr (MonoImage *image, MonoMethod *method,
5783 const char *data, guint32 len)
5785 const char *p = data;
5787 guint32 i, j, num_named;
5791 mono_class_init (method->klass);
5794 attr = mono_object_new (mono_domain_get (), method->klass);
5795 mono_runtime_invoke (method, attr, NULL, NULL);
5799 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5802 /*g_print ("got attr %s\n", method->klass->name);*/
5804 params = g_new (void*, method->signature->param_count);
5808 for (i = 0; i < method->signature->param_count; ++i) {
5809 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5813 attr = mono_object_new (mono_domain_get (), method->klass);
5814 mono_runtime_invoke (method, attr, params, NULL);
5815 free_param_data (method->signature, params);
5817 num_named = read16 (named);
5819 for (j = 0; j < num_named; j++) {
5821 char *name, named_type, data_type;
5822 named_type = *named++;
5823 data_type = *named++; /* type of data */
5824 if (data_type == 0x55) {
5827 type_len = mono_metadata_decode_blob_size (named, &named);
5828 type_name = g_malloc (type_len + 1);
5829 memcpy (type_name, named, type_len);
5830 type_name [type_len] = 0;
5832 /* FIXME: lookup the type and check type consistency */
5835 if (data_type == MONO_TYPE_SZARRAY)
5836 /* The spec does not mention this */
5838 name_len = mono_metadata_decode_blob_size (named, &named);
5839 name = g_malloc (name_len + 1);
5840 memcpy (name, named, name_len);
5841 name [name_len] = 0;
5843 if (named_type == 0x53) {
5844 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5845 void *val = load_cattr_value (image, field->type, named, &named);
5846 mono_field_set_value (attr, field, val);
5847 if (!type_is_reference (field->type))
5849 } else if (named_type == 0x54) {
5852 MonoType *prop_type;
5854 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5855 /* can we have more that 1 arg in a custom attr named property? */
5856 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5857 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5858 mono_property_set_value (prop, attr, pparams, NULL);
5859 if (!type_is_reference (prop_type))
5860 g_free (pparams [0]);
5869 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5876 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5877 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5878 for (i = 0; i < cinfo->num_attrs; ++i) {
5879 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5880 mono_array_set (result, gpointer, i, attr);
5886 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5888 guint32 mtoken, i, len;
5889 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5891 MonoCustomAttrInfo *ainfo;
5892 GList *tmp, *list = NULL;
5895 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5897 i = mono_metadata_custom_attrs_from_index (image, idx);
5901 while (i < ca->rows) {
5902 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5904 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5907 len = g_list_length (list);
5910 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5911 ainfo->num_attrs = len;
5912 ainfo->image = image;
5913 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5914 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5915 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5916 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5917 case CUSTOM_ATTR_TYPE_METHODDEF:
5918 mtoken |= MONO_TOKEN_METHOD_DEF;
5920 case CUSTOM_ATTR_TYPE_MEMBERREF:
5921 mtoken |= MONO_TOKEN_MEMBER_REF;
5924 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5927 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5928 if (!ainfo->attrs [i].ctor)
5929 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5930 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5931 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5932 ainfo->attrs [i].data = data;
5940 mono_custom_attrs_from_method (MonoMethod *method)
5942 MonoCustomAttrInfo *cinfo;
5945 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5947 idx = find_method_index (method);
5948 idx <<= CUSTOM_ATTR_BITS;
5949 idx |= CUSTOM_ATTR_METHODDEF;
5950 return mono_custom_attrs_from_index (method->klass->image, idx);
5954 mono_custom_attrs_from_class (MonoClass *klass)
5956 MonoCustomAttrInfo *cinfo;
5959 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5961 idx = mono_metadata_token_index (klass->type_token);
5962 idx <<= CUSTOM_ATTR_BITS;
5963 idx |= CUSTOM_ATTR_TYPEDEF;
5964 return mono_custom_attrs_from_index (klass->image, idx);
5968 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5970 MonoCustomAttrInfo *cinfo;
5973 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5975 idx = 1; /* there is only one assembly */
5976 idx <<= CUSTOM_ATTR_BITS;
5977 idx |= CUSTOM_ATTR_ASSEMBLY;
5978 return mono_custom_attrs_from_index (assembly->image, idx);
5981 static MonoCustomAttrInfo*
5982 mono_custom_attrs_from_module (MonoImage *image)
5984 MonoCustomAttrInfo *cinfo;
5987 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5989 idx = 1; /* there is only one module */
5990 idx <<= CUSTOM_ATTR_BITS;
5991 idx |= CUSTOM_ATTR_MODULE;
5992 return mono_custom_attrs_from_index (image, idx);
5996 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5998 MonoCustomAttrInfo *cinfo;
6001 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6003 idx = find_property_index (klass, property);
6004 idx <<= CUSTOM_ATTR_BITS;
6005 idx |= CUSTOM_ATTR_PROPERTY;
6006 return mono_custom_attrs_from_index (klass->image, idx);
6010 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6012 MonoCustomAttrInfo *cinfo;
6015 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6017 idx = find_event_index (klass, event);
6018 idx <<= CUSTOM_ATTR_BITS;
6019 idx |= CUSTOM_ATTR_EVENT;
6020 return mono_custom_attrs_from_index (klass->image, idx);
6024 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6026 MonoCustomAttrInfo *cinfo;
6029 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6031 idx = find_field_index (klass, field);
6032 idx <<= CUSTOM_ATTR_BITS;
6033 idx |= CUSTOM_ATTR_FIELDDEF;
6034 return mono_custom_attrs_from_index (klass->image, idx);
6038 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6041 guint32 i, idx, method_index;
6042 guint32 param_list, param_last, param_pos, found;
6044 MonoReflectionMethodAux *aux;
6046 if (method->klass->image->dynamic) {
6047 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6048 if (!aux || !aux->param_cattr)
6050 return aux->param_cattr [param];
6053 image = method->klass->image;
6054 method_index = find_method_index (method);
6055 ca = &image->tables [MONO_TABLE_METHOD];
6057 if (method->klass->generic_inst || method->klass->gen_params ||
6058 method->signature->generic_param_count) {
6059 // FIXME FIXME FIXME
6063 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6064 if (method_index == ca->rows) {
6065 ca = &image->tables [MONO_TABLE_PARAM];
6066 param_last = ca->rows + 1;
6068 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6069 ca = &image->tables [MONO_TABLE_PARAM];
6072 for (i = param_list; i < param_last; ++i) {
6073 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6074 if (param_pos == param) {
6082 idx <<= CUSTOM_ATTR_BITS;
6083 idx |= CUSTOM_ATTR_PARAMDEF;
6084 return mono_custom_attrs_from_index (image, idx);
6088 * mono_reflection_get_custom_attrs:
6089 * @obj: a reflection object handle
6091 * Return an array with all the custom attributes defined of the
6092 * reflection handle @obj. The objects are fully build.
6095 mono_reflection_get_custom_attrs (MonoObject *obj)
6099 MonoCustomAttrInfo *cinfo = NULL;
6101 MONO_ARCH_SAVE_REGS;
6103 klass = obj->vtable->klass;
6104 /* FIXME: need to handle: Module */
6105 if (klass == mono_defaults.monotype_class) {
6106 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6107 klass = mono_class_from_mono_type (rtype->type);
6108 cinfo = mono_custom_attrs_from_class (klass);
6109 } else if (strcmp ("Assembly", klass->name) == 0) {
6110 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6111 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6112 } else if (strcmp ("Module", klass->name) == 0) {
6113 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6114 cinfo = mono_custom_attrs_from_module (module->image);
6115 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6116 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6117 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6118 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6119 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6120 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6121 } else if (strcmp ("MonoField", klass->name) == 0) {
6122 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6123 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6124 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6125 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6126 cinfo = mono_custom_attrs_from_method (rmethod->method);
6127 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6128 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6129 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6130 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6131 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6132 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6133 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6134 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6135 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6136 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6137 } else { /* handle other types here... */
6138 g_error ("get custom attrs not yet supported for %s", klass->name);
6142 result = mono_custom_attrs_construct (cinfo);
6144 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6145 result = mono_array_new (mono_domain_get (), klass, 0);
6151 static MonoMethodSignature*
6152 parameters_to_signature (MonoArray *parameters) {
6153 MonoMethodSignature *sig;
6156 count = parameters? mono_array_length (parameters): 0;
6158 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6159 sig->param_count = count;
6160 sig->sentinelpos = -1; /* FIXME */
6161 for (i = 0; i < count; ++i) {
6162 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6163 sig->params [i] = pt->type;
6168 static MonoMethodSignature*
6169 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6170 MonoMethodSignature *sig;
6172 sig = parameters_to_signature (ctor->parameters);
6173 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6174 sig->ret = &mono_defaults.void_class->byval_arg;
6178 static MonoMethodSignature*
6179 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6180 MonoMethodSignature *sig;
6182 sig = parameters_to_signature (method->parameters);
6183 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6184 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6185 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6189 static MonoMethodSignature*
6190 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6191 MonoMethodSignature *sig;
6193 sig = parameters_to_signature (method->parameters);
6194 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6195 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6196 sig->generic_param_count = 0;
6201 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6203 MonoClass *klass = mono_object_class (prop);
6204 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6205 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6206 *name = mono_string_to_utf8 (pb->name);
6207 *type = pb->type->type;
6209 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6210 *name = g_strdup (p->property->name);
6211 if (p->property->get)
6212 *type = p->property->get->signature->ret;
6214 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6219 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6221 MonoClass *klass = mono_object_class (field);
6222 if (strcmp (klass->name, "FieldBuilder") == 0) {
6223 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6224 *name = mono_string_to_utf8 (fb->name);
6225 *type = fb->type->type;
6227 MonoReflectionField *f = (MonoReflectionField *)field;
6228 *name = g_strdup (f->field->name);
6229 *type = f->field->type;
6234 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6237 MonoTypeEnum simple_type;
6239 if ((p-buffer) + 10 >= *buflen) {
6242 newbuf = g_realloc (buffer, *buflen);
6243 p = newbuf + (p-buffer);
6246 argval = ((char*)arg + sizeof (MonoObject));
6247 simple_type = type->type;
6249 switch (simple_type) {
6250 case MONO_TYPE_BOOLEAN:
6255 case MONO_TYPE_CHAR:
6258 swap_with_size (p, argval, 2, 1);
6264 swap_with_size (p, argval, 4, 1);
6270 swap_with_size (p, argval, 8, 1);
6273 case MONO_TYPE_VALUETYPE:
6274 if (type->data.klass->enumtype) {
6275 simple_type = type->data.klass->enum_basetype->type;
6278 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6281 case MONO_TYPE_STRING: {
6288 str = mono_string_to_utf8 ((MonoString*)arg);
6289 slen = strlen (str);
6290 if ((p-buffer) + 10 + slen >= *buflen) {
6294 newbuf = g_realloc (buffer, *buflen);
6295 p = newbuf + (p-buffer);
6298 mono_metadata_encode_value (slen, p, &p);
6299 memcpy (p, str, slen);
6304 case MONO_TYPE_CLASS: {
6312 k = mono_object_class (arg);
6313 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6314 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6315 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6317 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6318 slen = strlen (str);
6319 if ((p-buffer) + 10 + slen >= *buflen) {
6323 newbuf = g_realloc (buffer, *buflen);
6324 p = newbuf + (p-buffer);
6327 mono_metadata_encode_value (slen, p, &p);
6328 memcpy (p, str, slen);
6333 case MONO_TYPE_SZARRAY: {
6338 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6341 len = mono_array_length ((MonoArray*)arg);
6343 *p++ = (len >> 8) & 0xff;
6344 *p++ = (len >> 16) & 0xff;
6345 *p++ = (len >> 24) & 0xff;
6347 *retbuffer = buffer;
6348 eclass = type->data.klass;
6349 for (i = 0; i < len; ++i) {
6350 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6354 /* it may be a boxed value or a Type */
6355 case MONO_TYPE_OBJECT: {
6356 MonoClass *klass = mono_object_class (arg);
6360 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6363 } else if (klass->enumtype) {
6365 } else if (klass == mono_defaults.string_class) {
6366 simple_type = MONO_TYPE_STRING;
6369 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6370 *p++ = simple_type = klass->byval_arg.type;
6373 g_error ("unhandled type in custom attr");
6375 str = type_get_qualified_name (klass->enum_basetype, NULL);
6376 slen = strlen (str);
6377 if ((p-buffer) + 10 + slen >= *buflen) {
6381 newbuf = g_realloc (buffer, *buflen);
6382 p = newbuf + (p-buffer);
6385 mono_metadata_encode_value (slen, p, &p);
6386 memcpy (p, str, slen);
6389 simple_type = klass->enum_basetype->type;
6393 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6396 *retbuffer = buffer;
6400 * mono_reflection_get_custom_attrs_blob:
6401 * @ctor: custom attribute constructor
6402 * @ctorArgs: arguments o the constructor
6408 * Creates the blob of data that needs to be saved in the metadata and that represents
6409 * the custom attributed described by @ctor, @ctorArgs etc.
6410 * Returns: a Byte array representing the blob of data.
6413 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6416 MonoMethodSignature *sig;
6421 MONO_ARCH_SAVE_REGS;
6423 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6424 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6426 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6428 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6430 p = buffer = g_malloc (buflen);
6431 /* write the prolog */
6434 for (i = 0; i < sig->param_count; ++i) {
6435 arg = mono_array_get (ctorArgs, MonoObject*, i);
6436 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6440 i += mono_array_length (properties);
6442 i += mono_array_length (fields);
6444 *p++ = (i >> 8) & 0xff;
6447 for (i = 0; i < mono_array_length (properties); ++i) {
6452 prop = mono_array_get (properties, gpointer, i);
6453 get_prop_name_and_type (prop, &pname, &ptype);
6454 *p++ = 0x54; /* PROPERTY signature */
6456 /* Preallocate a large enough buffer */
6457 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6458 char *str = type_get_qualified_name (ptype, NULL);
6464 len += strlen (pname);
6466 if ((p-buffer) + 20 + len >= buflen) {
6470 newbuf = g_realloc (buffer, buflen);
6471 p = newbuf + (p-buffer);
6475 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6476 char *str = type_get_qualified_name (ptype, NULL);
6477 int slen = strlen (str);
6481 * This seems to be optional...
6484 mono_metadata_encode_value (slen, p, &p);
6485 memcpy (p, str, slen);
6489 mono_metadata_encode_value (ptype->type, p, &p);
6490 if (ptype->type == MONO_TYPE_SZARRAY)
6491 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6493 len = strlen (pname);
6494 mono_metadata_encode_value (len, p, &p);
6495 memcpy (p, pname, len);
6497 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6504 for (i = 0; i < mono_array_length (fields); ++i) {
6509 field = mono_array_get (fields, gpointer, i);
6510 get_field_name_and_type (field, &fname, &ftype);
6511 *p++ = 0x53; /* FIELD signature */
6512 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6513 char *str = type_get_qualified_name (ftype, NULL);
6514 int slen = strlen (str);
6515 if ((p-buffer) + 10 + slen >= buflen) {
6519 newbuf = g_realloc (buffer, buflen);
6520 p = newbuf + (p-buffer);
6525 * This seems to be optional...
6528 mono_metadata_encode_value (slen, p, &p);
6529 memcpy (p, str, slen);
6533 mono_metadata_encode_value (ftype->type, p, &p);
6535 len = strlen (fname);
6536 mono_metadata_encode_value (len, p, &p);
6537 memcpy (p, fname, len);
6539 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6544 g_assert (p - buffer <= buflen);
6545 buflen = p - buffer;
6546 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6547 p = mono_array_addr (result, char, 0);
6548 memcpy (p, buffer, buflen);
6550 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6556 * mono_reflection_setup_internal_class:
6557 * @tb: a TypeBuilder object
6559 * Creates a MonoClass that represents the TypeBuilder.
6560 * This is a trick that lets us simplify a lot of reflection code
6561 * (and will allow us to support Build and Run assemblies easier).
6564 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6566 MonoClass *klass, *parent;
6568 MONO_ARCH_SAVE_REGS;
6570 klass = g_new0 (MonoClass, 1);
6572 klass->image = &tb->module->dynamic_image->image;
6575 /* check so we can compile corlib correctly */
6576 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6577 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6578 parent = tb->parent->type->data.klass;
6580 parent = my_mono_class_from_mono_type (tb->parent->type);
6584 klass->inited = 1; /* we lie to the runtime */
6585 klass->name = mono_string_to_utf8 (tb->name);
6586 klass->name_space = mono_string_to_utf8 (tb->nspace);
6587 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6588 klass->flags = tb->attrs;
6590 klass->element_class = klass;
6591 klass->reflection_info = tb; /* need to pin. */
6593 /* Put into cache so mono_class_get () will find it */
6594 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6597 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6598 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6602 mono_class_setup_parent (klass, parent);
6603 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6604 const char *old_n = klass->name;
6605 /* trick to get relative numbering right when compiling corlib */
6606 klass->name = "BuildingObject";
6607 mono_class_setup_parent (klass, mono_defaults.object_class);
6608 klass->name = old_n;
6610 mono_class_setup_mono_type (klass);
6612 mono_class_setup_supertypes (klass);
6615 * FIXME: handle interfaces.
6618 tb->type.type = &klass->byval_arg;
6620 if (tb->nesting_type) {
6621 g_assert (tb->nesting_type->type);
6622 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6625 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6629 * mono_reflection_setup_generic_class:
6630 * @tb: a TypeBuilder object
6632 * Setup the generic class after all generic parameters have been added.
6635 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6640 MONO_ARCH_SAVE_REGS;
6642 klass = my_mono_class_from_mono_type (tb->type.type);
6644 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6646 if (klass->gen_params || (count == 0))
6649 klass->num_gen_params = count;
6650 klass->gen_params = g_new0 (MonoGenericParam, count);
6652 for (i = 0; i < count; i++) {
6653 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6654 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6659 * mono_reflection_create_internal_class:
6660 * @tb: a TypeBuilder object
6662 * Actually create the MonoClass that is associated with the TypeBuilder.
6665 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6669 MONO_ARCH_SAVE_REGS;
6671 klass = my_mono_class_from_mono_type (tb->type.type);
6673 if (klass->enumtype && klass->enum_basetype == NULL) {
6674 MonoReflectionFieldBuilder *fb;
6676 g_assert (tb->fields != NULL);
6677 g_assert (mono_array_length (tb->fields) >= 1);
6679 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6681 klass->enum_basetype = fb->type->type;
6682 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6683 if (!klass->element_class)
6684 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6685 klass->instance_size = klass->element_class->instance_size;
6686 klass->size_inited = 1;
6688 * this is almost safe to do with enums and it's needed to be able
6689 * to create objects of the enum type (for use in SetConstant).
6691 /* FIXME: Does this mean enums can't have method overrides ? */
6692 mono_class_setup_vtable (klass, NULL, 0);
6696 static MonoMarshalSpec*
6697 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6698 MonoReflectionMarshal *minfo)
6700 MonoMarshalSpec *res;
6702 res = g_new0 (MonoMarshalSpec, 1);
6703 res->native = minfo->type;
6705 switch (minfo->type) {
6706 case MONO_NATIVE_LPARRAY:
6707 res->data.array_data.elem_type = minfo->eltype;
6708 res->data.array_data.param_num = 0; /* Not yet */
6709 res->data.array_data.num_elem = minfo->count;
6712 case MONO_NATIVE_BYVALTSTR:
6713 case MONO_NATIVE_BYVALARRAY:
6714 res->data.array_data.num_elem = minfo->count;
6717 case MONO_NATIVE_CUSTOM:
6718 if (minfo->marshaltyperef)
6719 res->data.custom_data.custom_name =
6720 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6722 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6733 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6734 ReflectionMethodBuilder *rmb,
6735 MonoMethodSignature *sig)
6738 MonoMethodNormal *pm;
6739 MonoMarshalSpec **specs;
6740 MonoReflectionMethodAux *method_aux;
6743 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6744 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6745 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6748 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6750 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6752 pm = (MonoMethodNormal*)m;
6755 m->flags = rmb->attrs;
6756 m->iflags = rmb->iattrs;
6757 m->name = mono_string_to_utf8 (rmb->name);
6761 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6763 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6764 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6767 m->signature->pinvoke = 1;
6768 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6770 m->signature->pinvoke = 1;
6772 } else if (!m->klass->dummy &&
6773 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6774 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6775 MonoMethodHeader *header;
6777 gint32 max_stack, i;
6778 gint32 num_locals = 0;
6779 gint32 num_clauses = 0;
6783 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6784 code_size = rmb->ilgen->code_len;
6785 max_stack = rmb->ilgen->max_stack;
6786 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6787 if (rmb->ilgen->ex_handlers)
6788 num_clauses = method_count_clauses (rmb->ilgen);
6791 code = mono_array_addr (rmb->code, guint8, 0);
6792 code_size = mono_array_length (rmb->code);
6793 /* we probably need to run a verifier on the code... */
6803 header = g_malloc0 (sizeof (MonoMethodHeader) +
6804 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6805 header->code_size = code_size;
6806 header->code = g_malloc (code_size);
6807 memcpy ((char*)header->code, code, code_size);
6808 header->max_stack = max_stack;
6809 header->init_locals = rmb->init_locals;
6810 header->num_locals = num_locals;
6812 for (i = 0; i < num_locals; ++i) {
6813 MonoReflectionLocalBuilder *lb =
6814 mono_array_get (rmb->ilgen->locals,
6815 MonoReflectionLocalBuilder*, i);
6817 header->locals [i] = g_new0 (MonoType, 1);
6818 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6821 header->num_clauses = num_clauses;
6823 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6828 if (rmb->generic_params) {
6829 int count = mono_array_length (rmb->generic_params);
6830 header->gen_params = g_new0 (MonoGenericParam, count);
6831 for (i = 0; i < count; i++) {
6832 MonoReflectionGenericParam *gp =
6833 mono_array_get (rmb->generic_params,
6834 MonoReflectionGenericParam*, i);
6836 header->gen_params [i] = *gp->type.type->data.generic_param;
6840 pm->header = header;
6844 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6847 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6849 for (i = 0; i < rmb->nrefs; ++i)
6850 mw->data = g_list_append (mw->data, rmb->refs [i]);
6855 /* Parameter names */
6858 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6859 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6860 for (i = 0; i <= m->signature->param_count; ++i) {
6861 MonoReflectionParamBuilder *pb;
6862 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6864 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6866 if (!method_aux->param_cattr)
6867 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6868 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6874 /* Parameter marshalling */
6877 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6878 MonoReflectionParamBuilder *pb;
6879 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6880 if (pb->marshal_info) {
6882 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6883 specs [pb->position] =
6884 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6888 if (specs != NULL) {
6890 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6891 method_aux->param_marshall = specs;
6894 if (klass->image->dynamic && method_aux)
6895 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6901 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6903 ReflectionMethodBuilder rmb;
6904 MonoMethodSignature *sig;
6906 sig = ctor_builder_to_signature (mb);
6908 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6910 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6911 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6913 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6914 /* ilgen is no longer needed */
6922 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6924 ReflectionMethodBuilder rmb;
6925 MonoMethodSignature *sig;
6927 sig = method_builder_to_signature (mb);
6929 reflection_methodbuilder_from_method_builder (&rmb, mb);
6931 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6932 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6934 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6935 /* ilgen is no longer needed */
6941 static MonoClassField*
6942 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6944 MonoClassField *field;
6951 field = g_new0 (MonoClassField, 1);
6953 field->name = mono_string_to_utf8 (fb->name);
6955 /* FIXME: handle type modifiers */
6956 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6957 field->type->attrs = fb->attrs;
6959 field->type = fb->type->type;
6961 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6962 field->data = mono_array_addr (fb->rva_data, char, 0);
6963 if (fb->offset != -1)
6964 field->offset = fb->offset;
6965 field->parent = klass;
6967 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6969 if (fb->def_value) {
6970 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6971 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6972 field->def_value = g_new0 (MonoConstant, 1);
6973 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6974 /* Copy the data from the blob since it might get realloc-ed */
6975 p = assembly->blob.data + idx;
6976 len = mono_metadata_decode_blob_size (p, &p2);
6978 field->def_value->value = g_malloc (len);
6979 memcpy (field->def_value->value, p, len);
6986 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
6987 MonoType **types, MonoType *nested_in)
6990 MonoReflectionTypeBuilder *tb = NULL;
6991 MonoGenericInst *ginst;
6996 klass = mono_class_from_mono_type (type->type);
6997 if (!klass->gen_params && !klass->generic_inst &&
6998 !(klass->nested_in && klass->nested_in->gen_params))
7001 mono_loader_lock ();
7003 domain = mono_object_domain (type);
7005 ginst = g_new0 (MonoGenericInst, 1);
7007 if (!klass->generic_inst) {
7008 ginst->type_argc = type_argc;
7009 ginst->type_argv = types;
7011 for (i = 0; i < ginst->type_argc; ++i) {
7012 if (!ginst->is_open)
7013 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7016 ginst->generic_type = &klass->byval_arg;
7018 MonoGenericInst *kginst = klass->generic_inst;
7020 ginst->type_argc = kginst->type_argc;
7021 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7023 for (i = 0; i < ginst->type_argc; i++) {
7024 MonoType *t = kginst->type_argv [i];
7026 if (t->type == MONO_TYPE_VAR)
7027 t = types [t->data.generic_param->num];
7029 if (!ginst->is_open)
7030 ginst->is_open = mono_class_is_open_constructed_type (t);
7032 ginst->type_argv [i] = t;
7035 ginst->generic_type = kginst->generic_type;
7038 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7041 mono_loader_unlock ();
7045 ginst->context = g_new0 (MonoGenericContext, 1);
7046 ginst->context->ginst = ginst;
7048 geninst = g_new0 (MonoType, 1);
7049 geninst->type = MONO_TYPE_GENERICINST;
7050 geninst->data.generic_inst = ginst;
7052 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7053 tb = (MonoReflectionTypeBuilder *) type;
7055 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7056 ginst->is_dynamic = TRUE;
7057 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7058 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7059 MonoReflectionType *rgt = rgi->generic_type;
7061 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7062 tb = (MonoReflectionTypeBuilder *) rgt;
7064 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7065 ginst->is_dynamic = TRUE;
7067 icount = klass->interface_count;
7069 ginst->ifaces = g_new0 (MonoType *, icount);
7070 ginst->count_ifaces = icount;
7072 for (i = 0; i < icount; i++) {
7073 MonoReflectionType *itype;
7076 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7078 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7079 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7080 if (!ginst->ifaces [i])
7081 ginst->ifaces [i] = itype->type;
7084 ginst->nested_in = nested_in;
7086 mono_class_create_generic (ginst);
7088 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7090 mono_loader_unlock ();
7096 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7098 MonoClass *klass, *pklass = NULL, *oklass = NULL;
7099 MonoReflectionType *parent = NULL, *outer = NULL;
7100 MonoType *geninst, *nested_in = NULL;
7101 MonoReflectionTypeBuilder *tb = NULL;
7102 MonoGenericInst *ginst;
7105 domain = mono_object_domain (type);
7106 klass = mono_class_from_mono_type (type->type);
7108 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7109 tb = (MonoReflectionTypeBuilder *) type;
7112 parent = tb->parent;
7113 pklass = mono_class_from_mono_type (parent->type);
7115 if (tb->nesting_type) {
7116 outer = tb->nesting_type;
7117 oklass = mono_class_from_mono_type (outer->type);
7120 pklass = klass->parent;
7122 parent = mono_type_get_object (domain, &pklass->byval_arg);
7123 oklass = klass->nested_in;
7125 outer = mono_type_get_object (domain, &oklass->byval_arg);
7129 nested_in = mono_reflection_bind_generic_parameters (outer, oklass->num_gen_params, types);
7131 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, nested_in);
7135 ginst = geninst->data.generic_inst;
7137 if (pklass && pklass->generic_inst)
7138 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7144 mono_reflection_generic_inst_get_nested_types (MonoReflectionGenericInst *type)
7146 MonoReflectionTypeBuilder *tb;
7147 MonoGenericInst *ginst;
7150 ginst = type->type.type->data.generic_inst;
7154 if (strcmp (((MonoObject *) type->generic_type)->vtable->klass->name, "TypeBuilder"))
7157 tb = (MonoReflectionTypeBuilder *) type->generic_type;
7159 ginst->count_nested = tb->subtypes ? mono_array_length (tb->subtypes) : 0;
7160 ginst->nested = g_new0 (MonoType *, ginst->count_nested);
7162 for (i = 0; i < ginst->count_nested; i++) {
7163 MonoReflectionTypeBuilder *ntype;
7167 ntype = mono_array_get (tb->subtypes, gpointer, i);
7168 ntype_argc = ntype->generic_params ? mono_array_length (ntype->generic_params) : 0;
7170 if (ntype_argc > ginst->type_argc) {
7171 ntypes = g_new0 (MonoType *, ntype_argc);
7173 for (j = 0; j < ginst->type_argc; j++)
7174 ntypes [j] = ginst->type_argv [j];
7176 for (j = ginst->type_argc; j < ntype_argc; j++) {
7177 MonoReflectionGenericParam *ngparam;
7178 MonoType *pt = g_new0 (MonoType, 1);
7180 ngparam = mono_array_get (ntype->generic_params, gpointer, j);
7182 pt->type = MONO_TYPE_VAR;
7183 pt->data.generic_param = ngparam->type.type->data.generic_param;
7188 ntypes = ginst->type_argv;
7190 ginst->nested [i] = mono_reflection_bind_generic_parameters ((MonoReflectionType *) ntype, ntype_argc, ntypes);
7194 MonoReflectionMethod*
7195 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7197 MonoMethod *method, *inflated;
7198 MonoReflectionMethodBuilder *mb = NULL;
7199 MonoGenericMethod *gmethod;
7200 MonoGenericContext *context;
7203 MONO_ARCH_SAVE_REGS;
7204 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7205 MonoReflectionTypeBuilder *tb;
7208 mb = (MonoReflectionMethodBuilder *) rmethod;
7209 tb = (MonoReflectionTypeBuilder *) mb->type;
7210 klass = mono_class_from_mono_type (tb->type.type);
7212 method = methodbuilder_to_mono_method (klass, mb);
7214 method = rmethod->method;
7216 count = method->signature->generic_param_count;
7217 if (count != mono_array_length (types))
7220 gmethod = g_new0 (MonoGenericMethod, 1);
7221 gmethod->mtype_argc = count;
7222 gmethod->mtype_argv = g_new0 (MonoType *, count);
7223 for (i = 0; i < count; i++) {
7224 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7225 gmethod->mtype_argv [i] = garg->type;
7228 context = g_new0 (MonoGenericContext, 1);
7229 context->ginst = method->klass->generic_inst;
7230 context->gmethod = gmethod;
7232 inflated = mono_class_inflate_generic_method (method, context, NULL);
7234 return mono_method_get_object (
7235 mono_object_domain (rmethod), inflated, NULL);
7239 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7241 MonoGenericMethod *gmethod;
7242 MonoGenericInst *ginst;
7243 MonoGenericContext *context;
7245 ginst = type->type.type->data.generic_inst;
7247 gmethod = g_new0 (MonoGenericMethod, 1);
7248 gmethod->reflection_info = obj;
7250 context = g_new0 (MonoGenericContext, 1);
7251 context->ginst = ginst;
7252 context->gmethod = gmethod;
7254 return mono_class_inflate_generic_method (method, context, ginst->klass);
7258 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7263 klass = mono_class_from_mono_type (type->type.type);
7265 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7266 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7267 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7268 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7269 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7270 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7271 method = ((MonoReflectionMethod *) obj)->method;
7273 method = NULL; /* prevent compiler warning */
7274 g_assert_not_reached ();
7277 return inflate_mono_method (type, method, obj);
7281 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7282 MonoArray *methods, MonoArray *ctors,
7283 MonoArray *fields, MonoArray *properties,
7286 MonoGenericInst *ginst;
7287 MonoDynamicGenericInst *dginst;
7288 MonoClass *klass, *gklass, *pklass;
7291 MONO_ARCH_SAVE_REGS;
7293 klass = mono_class_from_mono_type (type->type.type);
7294 ginst = type->type.type->data.generic_inst;
7296 if (ginst->initialized)
7299 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7301 gklass = mono_class_from_mono_type (ginst->generic_type);
7302 mono_class_init (gklass);
7305 pklass = mono_class_from_mono_type (ginst->parent);
7307 pklass = gklass->parent;
7309 mono_class_setup_parent (klass, pklass);
7311 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7312 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7313 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7314 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7315 dginst->count_events = events ? mono_array_length (events) : 0;
7317 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7318 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7319 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7320 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7321 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7323 for (i = 0; i < dginst->count_methods; i++) {
7324 MonoObject *obj = mono_array_get (methods, gpointer, i);
7326 dginst->methods [i] = inflate_method (type, obj);
7329 for (i = 0; i < dginst->count_ctors; i++) {
7330 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7332 dginst->ctors [i] = inflate_method (type, obj);
7335 for (i = 0; i < dginst->count_fields; i++) {
7336 MonoObject *obj = mono_array_get (fields, gpointer, i);
7337 MonoClassField *field;
7339 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7340 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7341 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7342 field = ((MonoReflectionField *) obj)->field;
7344 field = NULL; /* prevent compiler warning */
7345 g_assert_not_reached ();
7348 dginst->fields [i] = *field;
7349 dginst->fields [i].generic_type = field->type;
7350 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7353 for (i = 0; i < dginst->count_properties; i++) {
7354 MonoObject *obj = mono_array_get (properties, gpointer, i);
7355 MonoProperty *property = &dginst->properties [i];
7357 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7358 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7360 property->parent = klass;
7361 property->attrs = pb->attrs;
7362 property->name = mono_string_to_utf8 (pb->name);
7364 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7366 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7367 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7368 *property = *((MonoReflectionProperty *) obj)->property;
7371 property->get = inflate_mono_method (type, property->get, NULL);
7373 property->set = inflate_mono_method (type, property->set, NULL);
7375 g_assert_not_reached ();
7378 for (i = 0; i < dginst->count_events; i++) {
7379 MonoObject *obj = mono_array_get (events, gpointer, i);
7380 MonoEvent *event = &dginst->events [i];
7382 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7383 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7385 event->parent = klass;
7386 event->attrs = eb->attrs;
7387 event->name = mono_string_to_utf8 (eb->name);
7389 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7390 if (eb->remove_method)
7391 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7392 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7393 *event = *((MonoReflectionEvent *) obj)->event;
7396 event->add = inflate_mono_method (type, event->add, NULL);
7398 event->remove = inflate_mono_method (type, event->remove, NULL);
7400 g_assert_not_reached ();
7403 ginst->initialized = TRUE;
7407 ensure_runtime_vtable (MonoClass *klass)
7409 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7410 int i, num, j, onum;
7411 MonoMethod **overrides;
7413 if (!tb || klass->wastypebuilder)
7416 ensure_runtime_vtable (klass->parent);
7418 num = tb->ctors? mono_array_length (tb->ctors): 0;
7419 num += tb->num_methods;
7420 klass->method.count = num;
7421 klass->methods = g_new (MonoMethod*, num);
7422 num = tb->ctors? mono_array_length (tb->ctors): 0;
7423 for (i = 0; i < num; ++i)
7424 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7425 num = tb->num_methods;
7427 for (i = 0; i < num; ++i)
7428 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7430 klass->wastypebuilder = TRUE;
7431 if (tb->interfaces) {
7432 klass->interface_count = mono_array_length (tb->interfaces);
7433 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7434 for (i = 0; i < klass->interface_count; ++i) {
7435 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7436 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7440 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7441 for (i = 0; i < klass->method.count; ++i)
7442 klass->methods [i]->slot = i;
7447 for (i = 0; i < tb->num_methods; ++i) {
7448 MonoReflectionMethodBuilder *mb =
7449 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7450 if (mb->override_method)
7455 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7459 for (i = 0; i < tb->num_methods; ++i) {
7460 MonoReflectionMethodBuilder *mb =
7461 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7462 if (mb->override_method) {
7463 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7464 overrides [onum * 2] =
7465 mb->override_method->method;
7466 overrides [onum * 2 + 1] =
7469 g_assert (mb->mhandle);
7476 mono_class_setup_vtable (klass, overrides, onum);
7480 typebuilder_setup_fields (MonoClass *klass)
7482 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7483 MonoReflectionFieldBuilder *fb;
7484 MonoClassField *field;
7489 klass->field.count = tb->num_fields;
7490 klass->field.first = 0;
7491 klass->field.last = klass->field.count;
7493 if (!klass->field.count)
7496 klass->fields = g_new0 (MonoClassField, klass->field.count);
7498 for (i = 0; i < klass->field.count; ++i) {
7499 fb = mono_array_get (tb->fields, gpointer, i);
7500 field = &klass->fields [i];
7501 field->name = mono_string_to_utf8 (fb->name);
7503 /* FIXME: handle type modifiers */
7504 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7505 field->type->attrs = fb->attrs;
7507 field->type = fb->type->type;
7509 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7510 field->data = mono_array_addr (fb->rva_data, char, 0);
7511 if (fb->offset != -1)
7512 field->offset = fb->offset;
7513 field->parent = klass;
7515 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7517 if (fb->def_value) {
7518 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7519 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7520 field->def_value = g_new0 (MonoConstant, 1);
7521 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7522 /* Copy the data from the blob since it might get realloc-ed */
7523 p = assembly->blob.data + idx;
7524 len = mono_metadata_decode_blob_size (p, &p2);
7526 field->def_value->value = g_malloc (len);
7527 memcpy (field->def_value->value, p, len);
7530 mono_class_layout_fields (klass);
7534 typebuilder_setup_properties (MonoClass *klass)
7536 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7537 MonoReflectionPropertyBuilder *pb;
7540 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7541 klass->property.first = 0;
7542 klass->property.last = klass->property.count;
7544 klass->properties = g_new0 (MonoProperty, klass->property.count);
7545 for (i = 0; i < klass->property.count; ++i) {
7546 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7547 klass->properties [i].parent = klass;
7548 klass->properties [i].attrs = pb->attrs;
7549 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7551 klass->properties [i].get = pb->get_method->mhandle;
7553 klass->properties [i].set = pb->set_method->mhandle;
7557 MonoReflectionEvent *
7558 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7560 MonoEvent *event = g_new0 (MonoEvent, 1);
7564 klass = my_mono_class_from_mono_type (tb->type.type);
7566 event->parent = klass;
7567 event->attrs = eb->attrs;
7568 event->name = mono_string_to_utf8 (eb->name);
7570 event->add = eb->add_method->mhandle;
7571 if (eb->remove_method)
7572 event->remove = eb->remove_method->mhandle;
7573 if (eb->raise_method)
7574 event->raise = eb->raise_method->mhandle;
7576 if (eb->other_methods) {
7577 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7578 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7579 MonoReflectionMethodBuilder *mb =
7580 mono_array_get (eb->other_methods,
7581 MonoReflectionMethodBuilder*, j);
7582 event->other [j] = mb->mhandle;
7586 return mono_event_get_object (mono_object_domain (tb), klass, event);
7590 typebuilder_setup_events (MonoClass *klass)
7592 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7593 MonoReflectionEventBuilder *eb;
7596 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7597 klass->event.first = 0;
7598 klass->event.last = klass->event.count;
7600 klass->events = g_new0 (MonoEvent, klass->event.count);
7601 for (i = 0; i < klass->event.count; ++i) {
7602 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7603 klass->events [i].parent = klass;
7604 klass->events [i].attrs = eb->attrs;
7605 klass->events [i].name = mono_string_to_utf8 (eb->name);
7607 klass->events [i].add = eb->add_method->mhandle;
7608 if (eb->remove_method)
7609 klass->events [i].remove = eb->remove_method->mhandle;
7610 if (eb->raise_method)
7611 klass->events [i].raise = eb->raise_method->mhandle;
7613 if (eb->other_methods) {
7614 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7615 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7616 MonoReflectionMethodBuilder *mb =
7617 mono_array_get (eb->other_methods,
7618 MonoReflectionMethodBuilder*, j);
7619 klass->events [i].other [j] = mb->mhandle;
7626 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7629 MonoReflectionType* res;
7631 MONO_ARCH_SAVE_REGS;
7633 klass = my_mono_class_from_mono_type (tb->type.type);
7635 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7638 * Fields to set in klass:
7639 * the various flags: delegate/unicode/contextbound etc.
7642 klass->flags = tb->attrs;
7644 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7645 /* No need to fully construct the type */
7646 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7648 /* enums are done right away */
7649 if (!klass->enumtype)
7650 ensure_runtime_vtable (klass);
7652 /* fields and object layout */
7653 if (klass->parent) {
7654 if (!klass->parent->size_inited)
7655 mono_class_init (klass->parent);
7656 klass->instance_size += klass->parent->instance_size;
7657 klass->class_size += klass->parent->class_size;
7658 klass->min_align = klass->parent->min_align;
7660 klass->instance_size = sizeof (MonoObject);
7661 klass->min_align = 1;
7664 /* FIXME: handle packing_size and instance_size */
7665 typebuilder_setup_fields (klass);
7667 typebuilder_setup_properties (klass);
7669 typebuilder_setup_events (klass);
7671 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7672 /* with enums res == tb: need to fix that. */
7673 if (!klass->enumtype)
7674 g_assert (res != (MonoReflectionType*)tb);
7678 MonoReflectionGenericParam *
7679 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7681 static MonoClass *System_Reflection_MonoGenericParam;
7683 MonoGenericParam *param;
7684 MonoReflectionGenericParam *res;
7687 if (!System_Reflection_MonoGenericParam) {
7688 System_Reflection_MonoGenericParam = mono_class_from_name (
7689 mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7690 g_assert (System_Reflection_MonoGenericParam);
7693 param = g_new0 (MonoGenericParam, 1);
7696 tb = (MonoReflectionTypeBuilder *) mb->type;
7698 domain = mono_object_domain (tb);
7699 image = (MonoImage*)tb->module->dynamic_image;
7701 param->method = NULL;
7702 param->name = mono_string_to_utf8 (name);
7705 res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7706 res->type.type = g_new0 (MonoType, 1);
7707 res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7708 res->type.type->data.generic_param = param;
7710 res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7718 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7720 MonoGenericParam *param;
7721 MonoReflectionMethodBuilder *mb = NULL;
7722 MonoReflectionTypeBuilder *tb;
7726 param = gparam->type.type->data.generic_param;
7727 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7728 param->constraints = g_new0 (MonoClass *, count + 1);
7729 for (i = 0; i < count; i++) {
7730 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7732 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7735 if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7736 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7737 tb = (MonoReflectionTypeBuilder *) mb->type;
7739 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7741 image = (MonoImage*)tb->module->dynamic_image;
7743 param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7744 param->pklass->reflection_info = gparam;
7746 gparam->initialized = TRUE;
7750 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7752 MonoDynamicImage *assembly = sig->module->dynamic_image;
7753 guint32 na = mono_array_length (sig->arguments);
7758 MONO_ARCH_SAVE_REGS;
7760 p = buf = g_malloc (10 + na * 10);
7762 mono_metadata_encode_value (0x07, p, &p);
7763 mono_metadata_encode_value (na, p, &p);
7764 for (i = 0; i < na; ++i) {
7765 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7766 encode_reflection_type (assembly, type, p, &p);
7770 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7771 p = mono_array_addr (result, char, 0);
7772 memcpy (p, buf, buflen);
7779 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7781 MonoDynamicImage *assembly = sig->module->dynamic_image;
7782 guint32 na = mono_array_length (sig->arguments);
7787 MONO_ARCH_SAVE_REGS;
7789 p = buf = g_malloc (10 + na * 10);
7791 mono_metadata_encode_value (0x06, p, &p);
7792 for (i = 0; i < na; ++i) {
7793 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7794 encode_reflection_type (assembly, type, p, &p);
7798 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7799 p = mono_array_addr (result, char, 0);
7800 memcpy (p, buf, buflen);
7807 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7809 ReflectionMethodBuilder rmb;
7810 MonoMethodSignature *sig;
7813 sig = dynamic_method_to_signature (mb);
7815 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7818 * Resolve references.
7820 rmb.nrefs = mb->nrefs;
7821 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7822 for (i = 0; i < mb->nrefs; ++i) {
7823 gpointer ref = resolve_object (mb->module->image,
7824 mono_array_get (mb->refs, MonoObject*, i));
7827 mono_raise_exception (mono_get_exception_type_load (NULL));
7834 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7838 /* ilgen is no longer needed */
7843 * mono_reflection_lookup_dynamic_token:
7845 * Finish the Builder object pointed to by TOKEN and return the corresponding
7846 * runtime structure.
7849 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7851 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7854 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7857 return resolve_object (image, obj);
7861 resolve_object (MonoImage *image, MonoObject *obj)
7863 gpointer result = NULL;
7865 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7866 result = mono_string_intern ((MonoString*)obj);
7869 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7870 MonoReflectionType *tb = (MonoReflectionType*)obj;
7871 result = mono_class_from_mono_type (tb->type);
7874 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7875 result = ((MonoReflectionMethod*)obj)->method;
7878 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7879 result = ((MonoReflectionMethod*)obj)->method;
7882 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7883 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7884 result = mb->mhandle;
7886 /* Type is not yet created */
7887 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7889 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7892 * Hopefully this has been filled in by calling CreateType() on the
7896 * TODO: This won't work if the application finishes another
7897 * TypeBuilder instance instead of this one.
7899 result = mb->mhandle;
7902 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7903 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7905 result = cb->mhandle;
7907 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7909 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7910 result = cb->mhandle;
7913 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7914 result = ((MonoReflectionField*)obj)->field;
7917 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7918 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7919 result = fb->handle;
7922 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7924 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7925 result = fb->handle;
7928 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7929 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7932 klass = tb->type.type->data.klass;
7933 if (klass->wastypebuilder) {
7934 /* Already created */
7938 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7939 result = tb->type.type->data.klass;
7943 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7944 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7945 MonoMethodSignature *sig;
7948 if (helper->arguments)
7949 nargs = mono_array_length (helper->arguments);
7953 sig = mono_metadata_signature_alloc (image, nargs);
7954 sig->explicit_this = helper->call_conv & 64;
7955 sig->hasthis = helper->call_conv & 32;
7957 if (helper->call_conv == 0) /* unmanaged */
7958 sig->call_convention = helper->unmanaged_call_conv - 1;
7960 if (helper->call_conv & 0x02)
7961 sig->call_convention = MONO_CALL_VARARG;
7963 sig->call_convention = MONO_CALL_DEFAULT;
7965 sig->param_count = nargs;
7966 /* TODO: Copy type ? */
7967 sig->ret = helper->return_type->type;
7968 for (i = 0; i < nargs; ++i) {
7969 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7970 sig->params [i] = rt->type;
7976 g_print (obj->vtable->klass->name);
7977 g_assert_not_reached ();