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 case MONO_NATIVE_LPARRAY:
1555 mono_metadata_encode_value (minfo->type, p, &p);
1556 if (minfo->eltype || (minfo->count > 0)) {
1557 mono_metadata_encode_value (minfo->eltype, p, &p);
1558 if (minfo->count > 0) {
1559 mono_metadata_encode_value (0, p, &p);
1560 mono_metadata_encode_value (minfo->count, p, &p);
1564 case MONO_NATIVE_CUSTOM:
1565 mono_metadata_encode_value (minfo->type, p, &p);
1567 str = mono_string_to_utf8 (minfo->guid);
1569 mono_metadata_encode_value (len, p, &p);
1570 memcpy (p, str, len);
1574 mono_metadata_encode_value (0, p, &p);
1576 if (minfo->marshaltype) {
1577 str = mono_string_to_utf8 (minfo->marshaltype);
1579 mono_metadata_encode_value (len, p, &p);
1580 if (p + len >= buf + bufsize) {
1583 buf = g_realloc (buf, bufsize);
1586 memcpy (p, str, len);
1590 mono_metadata_encode_value (0, p, &p);
1592 if (minfo->marshaltyperef) {
1593 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1595 mono_metadata_encode_value (len, p, &p);
1596 if (p + len >= buf + bufsize) {
1599 buf = g_realloc (buf, bufsize);
1602 memcpy (p, str, len);
1606 mono_metadata_encode_value (0, p, &p);
1608 if (minfo->mcookie) {
1609 str = mono_string_to_utf8 (minfo->mcookie);
1611 mono_metadata_encode_value (len, p, &p);
1612 if (p + len >= buf + bufsize) {
1615 buf = g_realloc (buf, bufsize);
1618 memcpy (p, str, len);
1622 mono_metadata_encode_value (0, p, &p);
1626 mono_metadata_encode_value (minfo->type, p, &p);
1630 mono_metadata_encode_value (len, b, &b);
1631 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1637 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1639 MonoDynamicTable *table;
1643 /* maybe this fixup should be done in the C# code */
1644 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1645 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1646 table = &assembly->tables [MONO_TABLE_FIELD];
1647 fb->table_idx = table->next_idx ++;
1648 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1649 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1650 name = mono_string_to_utf8 (fb->name);
1651 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1653 values [MONO_FIELD_FLAGS] = fb->attrs;
1654 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1656 if (fb->offset != -1) {
1657 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1659 alloc_table (table, table->rows);
1660 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1661 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1662 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1664 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1665 guint32 field_type = 0;
1666 table = &assembly->tables [MONO_TABLE_CONSTANT];
1668 alloc_table (table, table->rows);
1669 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1670 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1671 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1672 values [MONO_CONSTANT_TYPE] = field_type;
1673 values [MONO_CONSTANT_PADDING] = 0;
1675 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1677 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1679 alloc_table (table, table->rows);
1680 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1681 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1683 * We store it in the code section because it's simpler for now.
1686 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1688 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1689 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1691 if (fb->marshal_info) {
1692 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1694 alloc_table (table, table->rows);
1695 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1696 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1697 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1702 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1706 char *b = blob_size;
1707 guint32 nparams = 0;
1708 MonoReflectionMethodBuilder *mb = fb->get_method;
1709 MonoReflectionMethodBuilder *smb = fb->set_method;
1710 guint32 idx, i, size;
1712 if (mb && mb->parameters)
1713 nparams = mono_array_length (mb->parameters);
1714 if (!mb && smb && smb->parameters)
1715 nparams = mono_array_length (smb->parameters) - 1;
1716 size = 24 + nparams * 10;
1717 buf = p = g_malloc (size);
1720 mono_metadata_encode_value (nparams, p, &p);
1722 encode_reflection_type (assembly, mb->rtype, p, &p);
1723 for (i = 0; i < nparams; ++i) {
1724 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1725 encode_reflection_type (assembly, pt, p, &p);
1728 /* the property type is the last param */
1729 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1730 for (i = 0; i < nparams; ++i) {
1731 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1732 encode_reflection_type (assembly, pt, p, &p);
1736 g_assert (p - buf < size);
1737 mono_metadata_encode_value (p-buf, b, &b);
1738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1744 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1746 MonoDynamicTable *table;
1749 guint num_methods = 0;
1753 * we need to set things in the following tables:
1754 * PROPERTYMAP (info already filled in _get_type_info ())
1755 * PROPERTY (rows already preallocated in _get_type_info ())
1756 * METHOD (method info already done with the generic method code)
1759 table = &assembly->tables [MONO_TABLE_PROPERTY];
1760 pb->table_idx = table->next_idx ++;
1761 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1762 name = mono_string_to_utf8 (pb->name);
1763 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1765 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1766 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1768 /* FIXME: we still don't handle 'other' methods */
1769 if (pb->get_method) num_methods ++;
1770 if (pb->set_method) num_methods ++;
1772 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1773 table->rows += num_methods;
1774 alloc_table (table, table->rows);
1776 if (pb->get_method) {
1777 semaidx = table->next_idx ++;
1778 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1779 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1780 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1781 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1783 if (pb->set_method) {
1784 semaidx = table->next_idx ++;
1785 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1786 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1787 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1788 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1793 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1795 MonoDynamicTable *table;
1798 guint num_methods = 0;
1802 * we need to set things in the following tables:
1803 * EVENTMAP (info already filled in _get_type_info ())
1804 * EVENT (rows already preallocated in _get_type_info ())
1805 * METHOD (method info already done with the generic method code)
1808 table = &assembly->tables [MONO_TABLE_EVENT];
1809 eb->table_idx = table->next_idx ++;
1810 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1811 name = mono_string_to_utf8 (eb->name);
1812 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1814 values [MONO_EVENT_FLAGS] = eb->attrs;
1815 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1818 * FIXME: we still don't handle 'other' methods
1820 if (eb->add_method) num_methods ++;
1821 if (eb->remove_method) num_methods ++;
1822 if (eb->raise_method) num_methods ++;
1824 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1825 table->rows += num_methods;
1826 alloc_table (table, table->rows);
1828 if (eb->add_method) {
1829 semaidx = table->next_idx ++;
1830 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1831 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1832 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1833 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1835 if (eb->remove_method) {
1836 semaidx = table->next_idx ++;
1837 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1838 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1839 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1840 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1842 if (eb->raise_method) {
1843 semaidx = table->next_idx ++;
1844 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1845 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1846 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1847 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1852 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1854 static MonoClass *NewConstraintAttr;
1855 static MonoMethod *NewConstraintAttr_ctor;
1856 MonoDynamicTable *table;
1858 guint32 token, type;
1859 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1862 if (!NewConstraintAttr)
1863 NewConstraintAttr = mono_class_from_name (
1864 mono_defaults.corlib, "System.Runtime.CompilerServices",
1865 "NewConstraintAttribute");
1866 g_assert (NewConstraintAttr);
1868 if (!NewConstraintAttr_ctor) {
1871 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1872 MonoMethod *m = NewConstraintAttr->methods [i];
1874 if (strcmp (m->name, ".ctor"))
1877 NewConstraintAttr_ctor = m;
1881 g_assert (NewConstraintAttr_ctor);
1884 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1886 alloc_table (table, table->rows);
1888 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1889 owner <<= CUSTOM_ATTR_BITS;
1890 owner |= CUSTOM_ATTR_GENERICPAR;
1891 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1893 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1895 type = mono_metadata_token_index (token);
1896 type <<= CUSTOM_ATTR_TYPE_BITS;
1897 switch (mono_metadata_token_table (token)) {
1898 case MONO_TABLE_METHOD:
1899 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1901 case MONO_TABLE_MEMBERREF:
1902 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1905 g_warning ("got wrong token in custom attr");
1908 values [MONO_CUSTOM_ATTR_TYPE] = type;
1910 buf = p = g_malloc (1);
1911 mono_metadata_encode_value (4, p, &p);
1912 g_assert (p-buf == 1);
1914 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1916 values += MONO_CUSTOM_ATTR_SIZE;
1921 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1923 MonoDynamicTable *table;
1924 guint32 num_constraints, i;
1928 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1929 num_constraints = gparam->iface_constraints ?
1930 mono_array_length (gparam->iface_constraints) : 0;
1931 table->rows += num_constraints;
1932 if (gparam->base_type)
1934 alloc_table (table, table->rows);
1936 if (gparam->base_type) {
1937 table_idx = table->next_idx ++;
1938 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1940 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1941 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1942 assembly, gparam->base_type->type);
1945 for (i = 0; i < num_constraints; i++) {
1946 MonoReflectionType *constraint = mono_array_get (
1947 gparam->iface_constraints, gpointer, i);
1949 table_idx = table->next_idx ++;
1950 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1952 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1953 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1954 assembly, constraint->type);
1957 if (gparam->has_ctor_constraint)
1958 encode_new_constraint (assembly, owner);
1962 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1964 MonoDynamicTable *table;
1965 MonoGenericParam *param;
1969 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1970 table_idx = table->next_idx ++;
1971 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1973 param = gparam->type.type->data.generic_param;
1975 values [MONO_GENERICPARAM_OWNER] = owner;
1976 if (gparam->has_value_type)
1977 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1978 else if (gparam->has_reference_type)
1979 values [MONO_GENERICPARAM_FLAGS] = 0x04;
1981 values [MONO_GENERICPARAM_FLAGS] = 0x00;
1982 values [MONO_GENERICPARAM_NUMBER] = param->num;
1983 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1984 values [MONO_GENERICPARAM_KIND] = 0;
1986 encode_constraints (gparam, table_idx, assembly);
1990 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1992 MonoDynamicTable *table;
1995 guint32 cols [MONO_ASSEMBLY_SIZE];
1999 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2002 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2003 table = &assembly->tables [MONO_TABLE_MODULEREF];
2004 token = table->next_idx ++;
2006 alloc_table (table, table->rows);
2007 values = table->values + token * MONO_MODULEREF_SIZE;
2008 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2010 token <<= RESOLTION_SCOPE_BITS;
2011 token |= RESOLTION_SCOPE_MODULEREF;
2012 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2017 if (image->assembly->dynamic)
2019 memset (cols, 0, sizeof (cols));
2021 /* image->assembly->image is the manifest module */
2022 image = image->assembly->image;
2023 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2026 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2027 token = table->next_idx ++;
2029 alloc_table (table, table->rows);
2030 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2031 if (strcmp ("corlib", image->assembly_name) == 0)
2032 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
2034 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2035 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2036 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2037 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2038 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2039 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2040 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2041 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2043 if (strcmp ("", image->assembly->aname.culture)) {
2044 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2045 image->assembly->aname.culture);
2048 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2049 guchar pubtoken [9];
2051 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2052 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2055 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2056 * This is currently only a problem with references to System.Xml (see bug#27706),
2057 * but there may be other cases that makes this necessary. Note, we need to set
2058 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
2059 * recognized by ms, yuck!
2060 * FIXME: need to add more assembly names, as needed.
2062 if (strcmp (image->assembly_name, "corlib") == 0 ||
2063 strcmp (image->assembly_name, "mscorlib") == 0 ||
2064 strcmp (image->assembly_name, "System") == 0 ||
2065 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2066 strcmp (image->assembly_name, "System.Xml") == 0 ||
2067 strcmp (image->assembly_name, "System.Data") == 0 ||
2068 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2069 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
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;
2073 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2074 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2075 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2076 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2077 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2078 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2079 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2080 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2081 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2082 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2083 strcmp (image->assembly_name, "System.Design") == 0 ||
2084 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2085 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2086 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2087 strcmp (image->assembly_name, "System.Management") == 0 ||
2088 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2089 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2090 strcmp (image->assembly_name, "System.Security") == 0 ||
2091 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2092 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2093 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2094 strcmp (image->assembly_name, "System.Web") == 0) {
2095 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2096 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2097 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2098 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2100 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2103 token <<= RESOLTION_SCOPE_BITS;
2104 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2105 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2110 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2112 MonoDynamicTable *table;
2118 char *b = blob_size;
2120 switch (type->type) {
2121 case MONO_TYPE_FNPTR:
2123 case MONO_TYPE_SZARRAY:
2124 case MONO_TYPE_ARRAY:
2126 case MONO_TYPE_MVAR:
2127 case MONO_TYPE_GENERICINST:
2128 encode_type (assembly, type, p, &p);
2130 case MONO_TYPE_CLASS:
2131 case MONO_TYPE_VALUETYPE: {
2132 MonoClass *k = mono_class_from_mono_type (type);
2133 if (!k || !k->generic_inst)
2135 encode_generic_inst (assembly, k->generic_inst, p, &p);
2142 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2143 if (assembly->save) {
2144 g_assert (p-sig < 128);
2145 mono_metadata_encode_value (p-sig, b, &b);
2146 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2147 alloc_table (table, table->rows + 1);
2148 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2149 values [MONO_TYPESPEC_SIGNATURE] = token;
2152 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2153 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2159 * Despite the name, we handle also TypeSpec (with the above helper).
2162 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2164 MonoDynamicTable *table;
2166 guint32 token, scope, enclosing;
2169 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2172 token = create_typespec (assembly, type);
2175 klass = my_mono_class_from_mono_type (type);
2177 klass = mono_class_from_mono_type (type);
2180 * If it's in the same module and not a generic type parameter:
2182 if ((klass->image == &assembly->image) &&
2183 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2184 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2185 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2186 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2190 if (klass->nested_in) {
2191 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2192 /* get the typeref idx of the enclosing type */
2193 enclosing >>= TYPEDEFORREF_BITS;
2194 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2196 scope = resolution_scope_from_image (assembly, klass->image);
2198 table = &assembly->tables [MONO_TABLE_TYPEREF];
2199 if (assembly->save) {
2200 alloc_table (table, table->rows + 1);
2201 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2202 values [MONO_TYPEREF_SCOPE] = scope;
2203 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2204 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2206 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2207 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2209 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2214 * Insert a memberef row into the metadata: the token that point to the memberref
2215 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2216 * mono_image_get_fieldref_token()).
2217 * The sig param is an index to an already built signature.
2220 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2222 MonoDynamicTable *table;
2224 guint32 token, pclass;
2227 parent = mono_image_typedef_or_ref (assembly, type);
2228 switch (parent & TYPEDEFORREF_MASK) {
2229 case TYPEDEFORREF_TYPEREF:
2230 pclass = MEMBERREF_PARENT_TYPEREF;
2232 case TYPEDEFORREF_TYPESPEC:
2233 pclass = MEMBERREF_PARENT_TYPESPEC;
2235 case TYPEDEFORREF_TYPEDEF:
2236 pclass = MEMBERREF_PARENT_TYPEDEF;
2239 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2242 /* extract the index */
2243 parent >>= TYPEDEFORREF_BITS;
2245 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2247 if (assembly->save) {
2248 alloc_table (table, table->rows + 1);
2249 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2250 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2251 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2252 values [MONO_MEMBERREF_SIGNATURE] = sig;
2255 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2262 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2266 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2269 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2270 method->name, method_encode_signature (assembly, method->signature));
2271 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2276 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2279 ReflectionMethodBuilder rmb;
2281 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2285 reflection_methodbuilder_from_method_builder (&rmb, mb);
2287 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2288 mono_string_to_utf8 (rmb.name),
2289 method_builder_encode_signature (assembly, &rmb));
2290 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2295 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2298 ReflectionMethodBuilder rmb;
2300 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2304 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2306 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2307 mono_string_to_utf8 (rmb.name),
2308 method_builder_encode_signature (assembly, &rmb));
2309 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2314 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2319 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2322 g_assert (f->field->parent);
2323 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2324 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2325 f->field->name, fieldref_encode_signature (assembly, type));
2326 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2331 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2336 guint32 nparams = gmethod->mtype_argc;
2337 guint32 size = 10 + nparams * 10;
2340 char *b = blob_size;
2342 if (!assembly->save)
2345 p = buf = g_malloc (size);
2347 * FIXME: vararg, explicit_this, differenc call_conv values...
2349 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2350 mono_metadata_encode_value (nparams, p, &p);
2352 for (i = 0; i < nparams; i++)
2353 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2356 g_assert (p - buf < size);
2357 mono_metadata_encode_value (p-buf, b, &b);
2358 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2364 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2366 MonoDynamicTable *table;
2368 guint32 token, mtoken = 0, sig;
2369 MonoMethodInflated *imethod;
2370 MonoMethod *declaring;
2372 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2374 g_assert (method->signature->is_inflated);
2375 imethod = (MonoMethodInflated *) method;
2376 declaring = imethod->declaring;
2378 sig = method_encode_signature (assembly, declaring->signature);
2379 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2380 declaring->name, sig);
2382 if (!declaring->signature->generic_param_count)
2385 switch (mono_metadata_token_table (mtoken)) {
2386 case MONO_TABLE_MEMBERREF:
2387 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2389 case MONO_TABLE_METHOD:
2390 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2393 g_assert_not_reached ();
2396 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2398 if (assembly->save) {
2399 alloc_table (table, table->rows + 1);
2400 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2401 values [MONO_METHODSPEC_METHOD] = mtoken;
2402 values [MONO_METHODSPEC_SIGNATURE] = sig;
2405 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2412 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2414 MonoMethodInflated *imethod;
2417 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2421 g_assert (m->signature->is_inflated);
2422 imethod = (MonoMethodInflated *) m;
2424 if (imethod->declaring->signature->generic_param_count)
2425 token = method_encode_methodspec (assembly, m);
2427 guint32 sig = method_encode_signature (
2428 assembly, imethod->declaring->signature);
2429 token = mono_image_get_memberref_token (
2430 assembly, &m->klass->byval_arg, m->name, sig);
2433 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2438 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2440 MonoDynamicTable *table;
2447 char *b = blob_size;
2451 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2452 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2453 * Because of this, we must not insert it into the `typeref' hash table.
2456 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2460 g_assert (tb->generic_params);
2461 klass = mono_class_from_mono_type (tb->type.type);
2463 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2464 encode_type (assembly, &klass->byval_arg, p, &p);
2466 count = mono_array_length (tb->generic_params);
2467 mono_metadata_encode_value (count, p, &p);
2468 for (i = 0; i < count; i++) {
2469 MonoReflectionGenericParam *gparam;
2471 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2473 encode_type (assembly, gparam->type.type, p, &p);
2476 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2477 if (assembly->save) {
2478 g_assert (p-sig < 128);
2479 mono_metadata_encode_value (p-sig, b, &b);
2480 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2481 alloc_table (table, table->rows + 1);
2482 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2483 values [MONO_TYPESPEC_SIGNATURE] = token;
2486 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2487 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2493 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2495 MonoDynamicTable *table;
2498 guint32 token, pclass, parent, sig;
2501 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2505 klass = mono_class_from_mono_type (fb->typeb->type);
2506 name = mono_string_to_utf8 (fb->name);
2508 sig = fieldref_encode_signature (assembly, fb->type->type);
2510 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2511 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2513 pclass = MEMBERREF_PARENT_TYPESPEC;
2514 parent >>= TYPEDEFORREF_BITS;
2516 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2518 if (assembly->save) {
2519 alloc_table (table, table->rows + 1);
2520 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2521 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2522 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2523 values [MONO_MEMBERREF_SIGNATURE] = sig;
2526 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2528 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2533 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2541 char *b = blob_size;
2543 if (!assembly->save)
2547 g_assert (helper->type == 2);
2549 if (helper->arguments)
2550 nargs = mono_array_length (helper->arguments);
2554 size = 10 + (nargs * 10);
2556 p = buf = g_malloc (size);
2558 /* Encode calling convention */
2559 /* Change Any to Standard */
2560 if ((helper->call_conv & 0x03) == 0x03)
2561 helper->call_conv = 0x01;
2562 /* explicit_this implies has_this */
2563 if (helper->call_conv & 0x40)
2564 helper->call_conv &= 0x20;
2566 if (helper->call_conv == 0) /* Unmanaged */
2567 *p = helper->unmanaged_call_conv - 1;
2570 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2571 if (helper->call_conv & 0x02) /* varargs */
2576 mono_metadata_encode_value (nargs, p, &p);
2577 encode_reflection_type (assembly, helper->return_type, p, &p);
2578 for (i = 0; i < nargs; ++i) {
2579 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2580 encode_reflection_type (assembly, pt, p, &p);
2583 g_assert (p - buf < size);
2584 mono_metadata_encode_value (p-buf, b, &b);
2585 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2592 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2595 MonoDynamicTable *table;
2598 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2599 idx = table->next_idx ++;
2601 alloc_table (table, table->rows);
2602 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2604 values [MONO_STAND_ALONE_SIGNATURE] =
2605 mono_reflection_encode_sighelper (assembly, helper);
2611 reflection_cc_to_file (int call_conv) {
2612 switch (call_conv & 0x3) {
2614 case 1: return MONO_CALL_DEFAULT;
2615 case 2: return MONO_CALL_VARARG;
2617 g_assert_not_reached ();
2624 MonoMethodSignature *sig;
2630 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2635 MonoMethodSignature *sig;
2638 name = mono_string_to_utf8 (m->name);
2639 nparams = mono_array_length (m->parameters);
2640 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2642 sig->call_convention = reflection_cc_to_file (m->call_conv);
2643 sig->param_count = nparams;
2644 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2645 for (i = 0; i < nparams; ++i) {
2646 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2647 sig->params [i] = t->type;
2650 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2652 if (strcmp (name, am->name) == 0 &&
2653 mono_metadata_type_equal (am->parent, m->parent->type) &&
2654 mono_metadata_signature_equal (am->sig, sig)) {
2657 m->table_idx = am->token & 0xffffff;
2661 am = g_new0 (ArrayMethod, 1);
2664 am->parent = m->parent->type;
2665 am->token = mono_image_get_memberref_token (assembly, am->parent,
2666 name, method_encode_signature (assembly, sig));
2667 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2668 m->table_idx = am->token & 0xffffff;
2673 * Insert into the metadata tables all the info about the TypeBuilder tb.
2674 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2677 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2679 MonoDynamicTable *table;
2681 int i, is_object = 0, is_system = 0;
2684 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2685 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2686 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2687 n = mono_string_to_utf8 (tb->name);
2688 if (strcmp (n, "Object") == 0)
2690 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2692 n = mono_string_to_utf8 (tb->nspace);
2693 if (strcmp (n, "System") == 0)
2695 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2697 if (tb->parent && !(is_system && is_object) &&
2698 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2699 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2701 values [MONO_TYPEDEF_EXTENDS] = 0;
2702 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2703 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2706 * if we have explicitlayout or sequentiallayouts, output data in the
2707 * ClassLayout table.
2709 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2710 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2712 alloc_table (table, table->rows);
2713 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2714 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2715 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2716 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2719 /* handle interfaces */
2720 if (tb->interfaces) {
2721 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2723 table->rows += mono_array_length (tb->interfaces);
2724 alloc_table (table, table->rows);
2725 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2726 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2727 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2728 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2729 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2730 values += MONO_INTERFACEIMPL_SIZE;
2734 /* handle generic parameters */
2735 if (tb->generic_params) {
2736 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2737 table->rows += mono_array_length (tb->generic_params);
2738 alloc_table (table, table->rows);
2739 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2740 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2742 mono_image_get_generic_param_info (
2743 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2749 table = &assembly->tables [MONO_TABLE_FIELD];
2750 table->rows += tb->num_fields;
2751 alloc_table (table, table->rows);
2752 for (i = 0; i < tb->num_fields; ++i)
2753 mono_image_get_field_info (
2754 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2757 /* handle constructors */
2759 table = &assembly->tables [MONO_TABLE_METHOD];
2760 table->rows += mono_array_length (tb->ctors);
2761 alloc_table (table, table->rows);
2762 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2763 mono_image_get_ctor_info (domain,
2764 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2767 /* handle methods */
2769 table = &assembly->tables [MONO_TABLE_METHOD];
2770 table->rows += tb->num_methods;
2771 alloc_table (table, table->rows);
2772 for (i = 0; i < tb->num_methods; ++i)
2773 mono_image_get_method_info (
2774 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2777 /* Do the same with properties etc.. */
2778 if (tb->events && mono_array_length (tb->events)) {
2779 table = &assembly->tables [MONO_TABLE_EVENT];
2780 table->rows += mono_array_length (tb->events);
2781 alloc_table (table, table->rows);
2782 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2784 alloc_table (table, table->rows);
2785 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2786 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2787 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2788 for (i = 0; i < mono_array_length (tb->events); ++i)
2789 mono_image_get_event_info (
2790 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2792 if (tb->properties && mono_array_length (tb->properties)) {
2793 table = &assembly->tables [MONO_TABLE_PROPERTY];
2794 table->rows += mono_array_length (tb->properties);
2795 alloc_table (table, table->rows);
2796 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2798 alloc_table (table, table->rows);
2799 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2800 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2801 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2802 for (i = 0; i < mono_array_length (tb->properties); ++i)
2803 mono_image_get_property_info (
2804 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2807 mono_image_add_decl_security (assembly,
2808 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2812 MonoDynamicTable *ntable;
2814 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2815 ntable->rows += mono_array_length (tb->subtypes);
2816 alloc_table (ntable, ntable->rows);
2817 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2819 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2820 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2822 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2823 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2824 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2825 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2826 mono_string_to_utf8 (tb->name), tb->table_idx,
2827 ntable->next_idx, ntable->rows);*/
2828 values += MONO_NESTED_CLASS_SIZE;
2835 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2839 g_ptr_array_add (types, type);
2841 if (!type->subtypes)
2844 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2845 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2846 collect_types (types, subtype);
2851 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2852 MonoReflectionTypeBuilder **type2)
2854 if ((*type1)->table_idx < (*type2)->table_idx)
2857 if ((*type1)->table_idx > (*type2)->table_idx)
2864 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2869 for (i = 0; i < mono_array_length (pinfo); ++i) {
2870 MonoReflectionParamBuilder *pb;
2871 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2874 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2879 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2882 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2884 for (i = 0; i < tb->num_fields; ++i) {
2885 MonoReflectionFieldBuilder* fb;
2886 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2887 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2891 for (i = 0; i < mono_array_length (tb->events); ++i) {
2892 MonoReflectionEventBuilder* eb;
2893 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2894 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2897 if (tb->properties) {
2898 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2899 MonoReflectionPropertyBuilder* pb;
2900 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2901 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2905 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2906 MonoReflectionCtorBuilder* cb;
2907 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2908 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2909 params_add_cattrs (assembly, cb->pinfo);
2914 for (i = 0; i < tb->num_methods; ++i) {
2915 MonoReflectionMethodBuilder* mb;
2916 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2917 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2918 params_add_cattrs (assembly, mb->pinfo);
2923 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2924 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2929 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2932 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2934 /* no types in the module */
2938 for (i = 0; i < mb->num_types; ++i)
2939 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2943 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2944 MonoDynamicImage *assembly)
2946 MonoDynamicTable *table;
2950 char *b = blob_size;
2953 table = &assembly->tables [MONO_TABLE_FILE];
2955 alloc_table (table, table->rows);
2956 values = table->values + table->next_idx * MONO_FILE_SIZE;
2957 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2958 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2959 if (module->image->dynamic) {
2960 /* This depends on the fact that the main module is emitted last */
2961 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2962 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2966 path = g_strdup (module->image->name);
2968 mono_sha1_get_digest_from_file (path, hash);
2971 mono_metadata_encode_value (20, b, &b);
2972 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2973 mono_image_add_stream_data (&assembly->blob, hash, 20);
2978 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2980 MonoDynamicTable *table;
2984 table = &assembly->tables [MONO_TABLE_MODULE];
2985 mb->table_idx = table->next_idx ++;
2986 name = mono_string_to_utf8 (mb->module.name);
2987 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2989 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2992 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2993 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2994 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2998 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2999 guint32 module_index, guint32 parent_index,
3000 MonoDynamicImage *assembly)
3002 MonoDynamicTable *table;
3006 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3007 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3010 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3012 alloc_table (table, table->rows);
3013 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3015 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3016 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3017 if (klass->nested_in)
3018 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3020 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3021 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3022 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3024 res = table->next_idx;
3028 /* Emit nested types */
3029 if (klass->nested_classes) {
3032 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3033 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3040 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3041 guint32 module_index, guint32 parent_index,
3042 MonoDynamicImage *assembly)
3047 klass = mono_class_from_mono_type (tb->type.type);
3049 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3051 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3052 parent_index, assembly);
3056 * We need to do this ourselves since klass->nested_classes is not set up.
3059 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3060 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3065 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3066 guint32 module_index,
3067 MonoDynamicImage *assembly)
3069 MonoImage *image = module->image;
3073 t = &image->tables [MONO_TABLE_TYPEDEF];
3075 for (i = 0; i < t->rows; ++i) {
3076 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3078 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3079 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3083 #define align_pointer(base,p)\
3085 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3087 (p) += 4 - (__diff & 3);\
3091 compare_semantics (const void *a, const void *b)
3093 const guint32 *a_values = a;
3094 const guint32 *b_values = b;
3095 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3098 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3102 compare_custom_attrs (const void *a, const void *b)
3104 const guint32 *a_values = a;
3105 const guint32 *b_values = b;
3107 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3111 compare_field_marshal (const void *a, const void *b)
3113 const guint32 *a_values = a;
3114 const guint32 *b_values = b;
3116 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3120 compare_nested (const void *a, const void *b)
3122 const guint32 *a_values = a;
3123 const guint32 *b_values = b;
3125 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3129 * build_compressed_metadata() fills in the blob of data that represents the
3130 * raw metadata as it will be saved in the PE file. The five streams are output
3131 * and the metadata tables are comnpressed from the guint32 array representation,
3132 * to the compressed on-disk format.
3135 build_compressed_metadata (MonoDynamicImage *assembly)
3137 MonoDynamicTable *table;
3139 guint64 valid_mask = 0;
3140 guint64 sorted_mask;
3141 guint32 heapt_size = 0;
3142 guint32 meta_size = 256; /* allow for header and other stuff */
3143 guint32 table_offset;
3144 guint32 ntables = 0;
3153 MonoDynamicStream *stream;
3156 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3157 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3158 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3159 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3160 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3162 /* tables that are sorted */
3163 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3164 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3165 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3166 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3167 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3168 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3170 /* Compute table sizes */
3171 /* the MonoImage has already been created in mono_image_basic_init() */
3172 meta = &assembly->image;
3174 /* Setup the info used by compute_sizes () */
3175 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3176 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3177 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3179 meta_size += assembly->blob.index;
3180 meta_size += assembly->guid.index;
3181 meta_size += assembly->sheap.index;
3182 meta_size += assembly->us.index;
3184 for (i=0; i < 64; ++i)
3185 meta->tables [i].rows = assembly->tables [i].rows;
3187 for (i = 0; i < 64; i++){
3188 if (meta->tables [i].rows == 0)
3190 valid_mask |= (guint64)1 << i;
3192 meta->tables [i].row_size = mono_metadata_compute_size (
3193 meta, i, &meta->tables [i].size_bitfield);
3194 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3196 heapt_size += 24; /* #~ header size */
3197 heapt_size += ntables * 4;
3198 meta_size += heapt_size;
3199 meta->raw_metadata = g_malloc0 (meta_size);
3200 p = meta->raw_metadata;
3201 /* the metadata signature */
3202 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3203 /* version numbers and 4 bytes reserved */
3204 int16val = (guint16*)p;
3205 *int16val++ = GUINT16_TO_LE (1);
3206 *int16val = GUINT16_TO_LE (1);
3208 /* version string */
3209 int32val = (guint32*)p;
3210 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3212 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3213 p += GUINT32_FROM_LE (*int32val);
3214 align_pointer (meta->raw_metadata, p);
3215 int16val = (guint16*)p;
3216 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3217 *int16val = GUINT16_TO_LE (5); /* number of streams */
3221 * write the stream info.
3223 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3224 table_offset += 3; table_offset &= ~3;
3226 assembly->tstream.index = heapt_size;
3227 for (i = 0; i < 5; ++i) {
3228 int32val = (guint32*)p;
3229 stream_desc [i].stream->offset = table_offset;
3230 *int32val++ = GUINT32_TO_LE (table_offset);
3231 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3232 table_offset += GUINT32_FROM_LE (*int32val);
3233 table_offset += 3; table_offset &= ~3;
3235 strcpy (p, stream_desc [i].name);
3236 p += strlen (stream_desc [i].name) + 1;
3237 align_pointer (meta->raw_metadata, p);
3240 * now copy the data, the table stream header and contents goes first.
3242 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3243 p = meta->raw_metadata + assembly->tstream.offset;
3244 int32val = (guint32*)p;
3245 *int32val = GUINT32_TO_LE (0); /* reserved */
3248 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3249 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3250 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3251 *p++ = 1; /* version */
3254 *p++ = 1; /* version */
3258 if (meta->idx_string_wide)
3260 if (meta->idx_guid_wide)
3262 if (meta->idx_blob_wide)
3265 *p++ = 0; /* reserved */
3266 int64val = (guint64*)p;
3267 *int64val++ = GUINT64_TO_LE (valid_mask);
3268 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3270 int32val = (guint32*)p;
3271 for (i = 0; i < 64; i++){
3272 if (meta->tables [i].rows == 0)
3274 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3276 p = (unsigned char*)int32val;
3278 /* sort the tables that still need sorting */
3279 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3281 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3282 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3284 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3285 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3287 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3288 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3290 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3292 /* compress the tables */
3293 for (i = 0; i < 64; i++){
3296 guint32 bitfield = meta->tables [i].size_bitfield;
3297 if (!meta->tables [i].rows)
3299 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3300 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3301 meta->tables [i].base = p;
3302 for (row = 1; row <= meta->tables [i].rows; ++row) {
3303 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3304 for (col = 0; col < assembly->tables [i].columns; ++col) {
3305 switch (mono_metadata_table_size (bitfield, col)) {
3307 *p++ = values [col];
3310 *p++ = values [col] & 0xff;
3311 *p++ = (values [col] >> 8) & 0xff;
3314 *p++ = values [col] & 0xff;
3315 *p++ = (values [col] >> 8) & 0xff;
3316 *p++ = (values [col] >> 16) & 0xff;
3317 *p++ = (values [col] >> 24) & 0xff;
3320 g_assert_not_reached ();
3324 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3327 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3328 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3329 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3330 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3331 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3333 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3337 * Some tables in metadata need to be sorted according to some criteria, but
3338 * when methods and fields are first created with reflection, they may be assigned a token
3339 * that doesn't correspond to the final token they will get assigned after the sorting.
3340 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3341 * with the reflection objects that represent them. Once all the tables are set up, the
3342 * reflection objects will contains the correct table index. fixup_method() will fixup the
3343 * tokens for the method with ILGenerator @ilgen.
3346 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3347 guint32 code_idx = GPOINTER_TO_UINT (value);
3348 MonoReflectionILTokenInfo *iltoken;
3349 MonoReflectionFieldBuilder *field;
3350 MonoReflectionCtorBuilder *ctor;
3351 MonoReflectionMethodBuilder *method;
3352 MonoReflectionTypeBuilder *tb;
3353 MonoReflectionArrayMethod *am;
3355 unsigned char *target;
3357 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3358 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3359 target = assembly->code.data + code_idx + iltoken->code_pos;
3360 switch (target [3]) {
3361 case MONO_TABLE_FIELD:
3362 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3363 field = (MonoReflectionFieldBuilder *)iltoken->member;
3364 idx = field->table_idx;
3365 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3366 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3367 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3369 g_assert_not_reached ();
3372 case MONO_TABLE_METHOD:
3373 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3374 method = (MonoReflectionMethodBuilder *)iltoken->member;
3375 idx = method->table_idx;
3376 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3377 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3378 idx = ctor->table_idx;
3379 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3380 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3381 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3382 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3384 g_assert_not_reached ();
3387 case MONO_TABLE_TYPEDEF:
3388 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3389 g_assert_not_reached ();
3390 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3391 idx = tb->table_idx;
3393 case MONO_TABLE_MEMBERREF:
3394 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3395 am = (MonoReflectionArrayMethod*)iltoken->member;
3396 idx = am->table_idx;
3397 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3398 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3399 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3400 g_assert (m->klass->generic_inst);
3402 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3404 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3405 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3406 g_assert (f->generic_type);
3409 g_assert_not_reached ();
3412 case MONO_TABLE_METHODSPEC:
3413 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3414 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3415 g_assert (m->signature->generic_param_count);
3418 g_assert_not_reached ();
3422 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3424 target [0] = idx & 0xff;
3425 target [1] = (idx >> 8) & 0xff;
3426 target [2] = (idx >> 16) & 0xff;
3433 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3434 * value is not known when the table is emitted.
3437 fixup_cattrs (MonoDynamicImage *assembly)
3439 MonoDynamicTable *table;
3441 guint32 type, i, idx, token;
3444 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3446 for (i = 0; i < table->rows; ++i) {
3447 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3449 type = values [MONO_CUSTOM_ATTR_TYPE];
3450 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3451 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3452 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3453 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3456 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3457 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3458 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3459 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3466 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3468 MonoDynamicTable *table;
3472 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3474 alloc_table (table, table->rows);
3475 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3476 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3477 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3478 name = mono_string_to_utf8 (rsrc->name);
3479 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3481 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3486 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3488 MonoDynamicTable *table;
3492 char *b = blob_size;
3494 guint32 idx, offset;
3496 if (rsrc->filename) {
3497 name = mono_string_to_utf8 (rsrc->filename);
3498 sname = g_path_get_basename (name);
3500 table = &assembly->tables [MONO_TABLE_FILE];
3502 alloc_table (table, table->rows);
3503 values = table->values + table->next_idx * MONO_FILE_SIZE;
3504 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3505 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3508 mono_sha1_get_digest_from_file (name, hash);
3509 mono_metadata_encode_value (20, b, &b);
3510 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3511 mono_image_add_stream_data (&assembly->blob, hash, 20);
3513 idx = table->next_idx++;
3515 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3518 offset = mono_array_length (rsrc->data);
3519 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3520 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3521 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3522 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3526 * The entry should be emitted into the MANIFESTRESOURCE table of
3527 * the main module, but that needs to reference the FILE table
3528 * which isn't emitted yet.
3535 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3539 set_version_from_string (MonoString *version, guint32 *values)
3541 gchar *ver, *p, *str;
3544 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3545 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3546 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3547 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3550 ver = str = mono_string_to_utf8 (version);
3551 for (i = 0; i < 4; ++i) {
3552 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3558 /* handle Revision and Build */
3568 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3572 char *b = blob_size;
3577 len = mono_array_length (pkey);
3578 mono_metadata_encode_value (len, b, &b);
3579 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3580 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3582 /* need to get the actual value from the key type... */
3583 assembly->strong_name_size = 128;
3584 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3590 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3592 MonoDynamicTable *table;
3593 MonoDynamicImage *assembly;
3594 MonoReflectionAssemblyBuilder *assemblyb;
3599 guint32 module_index;
3601 assemblyb = moduleb->assemblyb;
3602 assembly = moduleb->dynamic_image;
3603 domain = mono_object_domain (assemblyb);
3605 /* Emit ASSEMBLY table */
3606 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3607 alloc_table (table, 1);
3608 values = table->values + MONO_ASSEMBLY_SIZE;
3609 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3610 name = mono_string_to_utf8 (assemblyb->name);
3611 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3613 if (assemblyb->culture) {
3614 name = mono_string_to_utf8 (assemblyb->culture);
3615 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3618 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3620 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3621 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3622 set_version_from_string (assemblyb->version, values);
3624 /* Emit FILE + EXPORTED_TYPE table */
3626 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3628 MonoReflectionModuleBuilder *file_module =
3629 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3630 if (file_module != moduleb) {
3631 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3633 if (file_module->types) {
3634 for (j = 0; j < file_module->num_types; ++j) {
3635 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3636 mono_image_fill_export_table (domain, tb, module_index, 0,
3642 if (assemblyb->loaded_modules) {
3643 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3644 MonoReflectionModule *file_module =
3645 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3646 mono_image_fill_file_table (domain, file_module, assembly);
3648 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3652 /* Emit MANIFESTRESOURCE table */
3654 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3656 MonoReflectionModuleBuilder *file_module =
3657 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3658 /* The table for the main module is emitted later */
3659 if (file_module != moduleb) {
3661 if (file_module->resources) {
3662 int len = mono_array_length (file_module->resources);
3663 for (j = 0; j < len; ++j) {
3664 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3665 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3673 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3674 * for the modulebuilder @moduleb.
3675 * At the end of the process, method and field tokens are fixed up and the
3676 * on-disk compressed metadata representation is created.
3679 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3681 MonoDynamicTable *table;
3682 MonoDynamicImage *assembly;
3683 MonoReflectionAssemblyBuilder *assemblyb;
3688 assemblyb = moduleb->assemblyb;
3689 assembly = moduleb->dynamic_image;
3690 domain = mono_object_domain (assemblyb);
3692 if (assembly->text_rva)
3695 assembly->text_rva = START_TEXT_RVA;
3697 if (moduleb->is_main) {
3698 mono_image_emit_manifest (moduleb);
3701 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3702 table->rows = 1; /* .<Module> */
3704 alloc_table (table, table->rows);
3706 * Set the first entry.
3708 values = table->values + table->columns;
3709 values [MONO_TYPEDEF_FLAGS] = 0;
3710 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3711 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3712 values [MONO_TYPEDEF_EXTENDS] = 0;
3713 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3714 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3717 * handle global methods
3718 * FIXME: test what to do when global methods are defined in multiple modules.
3720 if (moduleb->global_methods) {
3721 table = &assembly->tables [MONO_TABLE_METHOD];
3722 table->rows += mono_array_length (moduleb->global_methods);
3723 alloc_table (table, table->rows);
3724 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3725 mono_image_get_method_info (
3726 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3728 if (moduleb->global_fields) {
3729 table = &assembly->tables [MONO_TABLE_FIELD];
3730 table->rows += mono_array_length (moduleb->global_fields);
3731 alloc_table (table, table->rows);
3732 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3733 mono_image_get_field_info (
3734 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3737 table = &assembly->tables [MONO_TABLE_MODULE];
3738 alloc_table (table, 1);
3739 mono_image_fill_module_table (domain, moduleb, assembly);
3743 /* Collect all types into a list sorted by their table_idx */
3744 GPtrArray *types = g_ptr_array_new ();
3747 for (i = 0; i < moduleb->num_types; ++i) {
3748 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3749 collect_types (types, type);
3752 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3753 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3754 table->rows += types->len;
3755 alloc_table (table, table->rows);
3757 for (i = 0; i < types->len; ++i) {
3758 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3759 mono_image_get_type_info (domain, type, assembly);
3761 g_ptr_array_free (types, TRUE);
3765 * table->rows is already set above and in mono_image_fill_module_table.
3767 /* add all the custom attributes at the end, once all the indexes are stable */
3768 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3770 module_add_cattrs (assembly, moduleb);
3773 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3774 fixup_cattrs (assembly);
3778 * mono_image_insert_string:
3779 * @module: module builder object
3782 * Insert @str into the user string stream of @module.
3785 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3787 MonoDynamicImage *assembly;
3792 MONO_ARCH_SAVE_REGS;
3794 if (!module->dynamic_image)
3795 mono_image_module_basic_init (module);
3797 assembly = module->dynamic_image;
3799 if (assembly->save) {
3800 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3801 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3804 char *swapped = g_malloc (2 * mono_string_length (str));
3805 const char *p = (const char*)mono_string_chars (str);
3807 swap_with_size (swapped, p, 2, mono_string_length (str));
3808 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3812 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3814 mono_image_add_stream_data (&assembly->us, "", 1);
3817 idx = assembly->us.index ++;
3819 mono_g_hash_table_insert (assembly->tokens,
3820 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3822 return MONO_TOKEN_STRING | idx;
3826 * mono_image_create_token:
3827 * @assembly: a dynamic assembly
3830 * Get a token to insert in the IL code stream for the given MemberInfo.
3831 * @obj can be one of:
3832 * ConstructorBuilder
3842 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3847 klass = obj->vtable->klass;
3848 if (strcmp (klass->name, "MethodBuilder") == 0) {
3849 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3851 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3852 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3854 token = mono_image_get_methodbuilder_token (assembly, mb);
3855 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3857 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3858 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3860 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3861 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3863 token = mono_image_get_ctorbuilder_token (assembly, mb);
3864 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3866 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3867 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3869 if (tb->generic_params) {
3870 token = mono_image_get_generic_field_token (assembly, fb);
3872 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3875 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3876 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3877 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3879 else if (strcmp (klass->name, "MonoType") == 0 ||
3880 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3881 MonoReflectionType *tb = (MonoReflectionType *)obj;
3882 token = mono_metadata_token_from_dor (
3883 mono_image_typedef_or_ref (assembly, tb->type));
3885 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3886 MonoReflectionType *tb = (MonoReflectionType *)obj;
3887 token = mono_metadata_token_from_dor (
3888 mono_image_typedef_or_ref (assembly, tb->type));
3890 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3891 strcmp (klass->name, "MonoMethod") == 0) {
3892 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3893 if (m->method->signature->is_inflated) {
3894 token = mono_image_get_methodspec_token (assembly, m->method);
3895 } else if (m->method->signature->generic_param_count) {
3896 g_assert_not_reached ();
3897 } else if ((m->method->klass->image == &assembly->image) &&
3898 !m->method->klass->generic_inst) {
3899 static guint32 method_table_idx = 0xffffff;
3901 * Each token should have a unique index, but the indexes are
3902 * assigned by managed code, so we don't know about them. An
3903 * easy solution is to count backwards...
3905 method_table_idx --;
3906 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3908 token = mono_image_get_methodref_token (assembly, m->method);
3909 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3911 else if (strcmp (klass->name, "MonoField") == 0) {
3912 MonoReflectionField *f = (MonoReflectionField *)obj;
3913 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3914 static guint32 field_table_idx = 0xffffff;
3916 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3918 token = mono_image_get_fieldref_token (assembly, f);
3919 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3921 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3922 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3923 token = mono_image_get_array_token (assembly, m);
3925 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3926 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3927 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3930 g_error ("requested token for %s\n", klass->name);
3932 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3939 guint32 import_lookup_table;
3943 guint32 import_address_table_rva;
3951 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3953 static MonoDynamicImage*
3954 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3955 char *assembly_name, char *module_name)
3957 static const guchar entrycode [16] = {0xff, 0x25, 0};
3958 MonoDynamicImage *image;
3962 * We need to use the current ms version or the ms runtime it won't find
3963 * the support dlls. D'oh!
3964 * const char *version = "mono-" VERSION;
3966 const char *version = "v1.0.3705";
3969 image = GC_MALLOC (sizeof (MonoDynamicImage));
3971 image = g_new0 (MonoDynamicImage, 1);
3974 /* keep in sync with image.c */
3975 image->image.name = assembly_name;
3976 image->image.assembly_name = image->image.name; /* they may be different */
3977 image->image.module_name = module_name;
3978 image->image.version = g_strdup (version);
3979 image->image.dynamic = TRUE;
3981 image->image.references = g_new0 (MonoAssembly*, 1);
3982 image->image.references [0] = NULL;
3984 mono_image_init (&image->image);
3986 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3987 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3988 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3989 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3990 image->handleref = g_hash_table_new (NULL, NULL);
3991 image->tokens = mono_g_hash_table_new (NULL, NULL);
3992 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3993 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3994 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3996 string_heap_init (&image->sheap);
3997 mono_image_add_stream_data (&image->us, "", 1);
3998 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3999 /* import tables... */
4000 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4001 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4002 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4003 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4004 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4005 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4006 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4007 stream_data_align (&image->code);
4009 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4011 for (i=0; i < 64; ++i) {
4012 image->tables [i].next_idx = 1;
4013 image->tables [i].columns = table_sizes [i];
4016 image->image.assembly = (MonoAssembly*)assembly;
4017 image->run = assembly->run;
4018 image->save = assembly->save;
4024 * mono_image_basic_init:
4025 * @assembly: an assembly builder object
4027 * Create the MonoImage that represents the assembly builder and setup some
4028 * of the helper hash table and the basic metadata streams.
4031 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4033 MonoDynamicAssembly *assembly;
4034 MonoDynamicImage *image;
4036 MONO_ARCH_SAVE_REGS;
4038 if (assemblyb->dynamic_assembly)
4042 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4044 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4047 assembly->assembly.dynamic = TRUE;
4048 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4049 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4050 if (assemblyb->culture)
4051 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4053 assembly->assembly.aname.culture = g_strdup ("");
4055 assembly->run = assemblyb->access != 2;
4056 assembly->save = assemblyb->access != 1;
4058 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4059 assembly->assembly.aname.name = image->image.name;
4060 assembly->assembly.image = &image->image;
4062 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4063 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4067 calc_section_size (MonoDynamicImage *assembly)
4071 /* alignment constraints */
4072 assembly->code.index += 3;
4073 assembly->code.index &= ~3;
4074 assembly->meta_size += 3;
4075 assembly->meta_size &= ~3;
4076 assembly->resources.index += 3;
4077 assembly->resources.index &= ~3;
4079 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4080 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4083 if (assembly->win32_res) {
4084 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4086 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4087 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4091 assembly->sections [MONO_SECTION_RELOC].size = 12;
4092 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4102 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4106 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4108 ResTreeNode *t1 = (ResTreeNode*)a;
4109 ResTreeNode *t2 = (ResTreeNode*)b;
4111 return t1->id - t2->id;
4115 * resource_tree_create:
4117 * Organize the resources into a resource tree.
4119 static ResTreeNode *
4120 resource_tree_create (MonoArray *win32_resources)
4122 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4126 tree = g_new0 (ResTreeNode, 1);
4128 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4129 MonoReflectionWin32Resource *win32_res =
4130 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4134 lang_node = g_new0 (ResTreeNode, 1);
4135 lang_node->id = win32_res->lang_id;
4136 lang_node->win32_res = win32_res;
4138 /* Create type node if neccesary */
4140 for (l = tree->children; l; l = l->next)
4141 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4142 type_node = (ResTreeNode*)l->data;
4147 type_node = g_new0 (ResTreeNode, 1);
4148 type_node->id = win32_res->res_type;
4151 * The resource types have to be sorted otherwise
4152 * Windows Explorer can't display the version information.
4154 tree->children = g_slist_insert_sorted (tree->children, type_node,
4155 resource_tree_compare_by_id);
4158 /* Create res node if neccesary */
4160 for (l = type_node->children; l; l = l->next)
4161 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4162 res_node = (ResTreeNode*)l->data;
4167 res_node = g_new0 (ResTreeNode, 1);
4168 res_node->id = win32_res->res_id;
4169 type_node->children = g_slist_append (type_node->children, res_node);
4172 res_node->children = g_slist_append (res_node->children, lang_node);
4179 * resource_tree_encode:
4181 * Encode the resource tree into the format used in the PE file.
4184 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4187 MonoPEResourceDir dir;
4188 MonoPEResourceDirEntry dir_entry;
4189 MonoPEResourceDataEntry data_entry;
4193 * For the format of the resource directory, see the article
4194 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4198 memset (&dir, 0, sizeof (dir));
4199 memset (&dir_entry, 0, sizeof (dir_entry));
4200 memset (&data_entry, 0, sizeof (data_entry));
4202 g_assert (sizeof (dir) == 16);
4203 g_assert (sizeof (dir_entry) == 8);
4204 g_assert (sizeof (data_entry) == 16);
4206 node->offset = p - begin;
4208 /* IMAGE_RESOURCE_DIRECTORY */
4209 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4211 memcpy (p, &dir, sizeof (dir));
4214 /* Reserve space for entries */
4216 p += sizeof (dir_entry) * dir.res_id_entries;
4218 /* Write children */
4219 for (l = node->children; l; l = l->next) {
4220 ResTreeNode *child = (ResTreeNode*)l->data;
4222 if (child->win32_res) {
4224 child->offset = p - begin;
4226 /* IMAGE_RESOURCE_DATA_ENTRY */
4227 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4228 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4230 memcpy (p, &data_entry, sizeof (data_entry));
4231 p += sizeof (data_entry);
4233 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4234 p += data_entry.rde_size;
4237 resource_tree_encode (child, begin, p, &p);
4240 /* IMAGE_RESOURCE_ENTRY */
4241 for (l = node->children; l; l = l->next) {
4242 ResTreeNode *child = (ResTreeNode*)l->data;
4243 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4245 dir_entry.is_dir = child->win32_res ? 0 : 1;
4246 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4248 memcpy (entries, &dir_entry, sizeof (dir_entry));
4249 entries += sizeof (dir_entry);
4256 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4261 MonoReflectionWin32Resource *win32_res;
4264 if (!assemblyb->win32_resources)
4268 * Resources are stored in a three level tree inside the PE file.
4269 * - level one contains a node for each type of resource
4270 * - level two contains a node for each resource
4271 * - level three contains a node for each instance of a resource for a
4272 * specific language.
4275 tree = resource_tree_create (assemblyb->win32_resources);
4277 /* Estimate the size of the encoded tree */
4279 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4280 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4281 size += mono_array_length (win32_res->res_data);
4283 /* Directory structure */
4284 size += mono_array_length (assemblyb->win32_resources) * 256;
4285 p = buf = g_malloc (size);
4287 resource_tree_encode (tree, p, p, &p);
4289 g_assert (p - buf < size);
4291 assembly->win32_res = g_malloc (p - buf);
4292 assembly->win32_res_size = p - buf;
4293 memcpy (assembly->win32_res, buf, p - buf);
4299 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4301 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4304 p += sizeof (MonoPEResourceDir);
4305 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4306 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4307 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4308 if (dir_entry->is_dir)
4309 fixup_resource_directory (res_section, child, rva);
4311 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4312 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4315 p += sizeof (MonoPEResourceDirEntry);
4320 * mono_image_create_pefile:
4321 * @mb: a module builder object
4323 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4324 * assembly->pefile where it can be easily retrieved later in chunks.
4327 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4328 MonoMSDOSHeader *msdos;
4329 MonoDotNetHeader *header;
4330 MonoSectionTable *section;
4331 MonoCLIHeader *cli_header;
4332 guint32 size, image_size, virtual_base, text_offset;
4333 guint32 header_start, section_start, file_offset, virtual_offset;
4334 MonoDynamicImage *assembly;
4335 MonoReflectionAssemblyBuilder *assemblyb;
4336 MonoDynamicStream *pefile;
4338 guint32 *rva, value;
4341 static const unsigned char msheader[] = {
4342 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4343 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4346 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4347 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4348 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4349 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4352 assemblyb = mb->assemblyb;
4354 mono_image_basic_init (assemblyb);
4355 assembly = mb->dynamic_image;
4357 /* already created */
4358 if (assembly->pefile.index)
4361 mono_image_build_metadata (mb);
4363 if (mb->is_main && assemblyb->resources) {
4364 int len = mono_array_length (assemblyb->resources);
4365 for (i = 0; i < len; ++i)
4366 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4369 if (mb->resources) {
4370 int len = mono_array_length (mb->resources);
4371 for (i = 0; i < len; ++i)
4372 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4375 build_compressed_metadata (assembly);
4378 assembly_add_win32_resources (assembly, assemblyb);
4380 nsections = calc_section_size (assembly);
4382 pefile = &assembly->pefile;
4384 /* The DOS header and stub */
4385 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4386 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4388 /* the dotnet header */
4389 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4391 /* the section tables */
4392 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4394 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4395 virtual_offset = VIRT_ALIGN;
4398 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4399 if (!assembly->sections [i].size)
4402 file_offset += FILE_ALIGN - 1;
4403 file_offset &= ~(FILE_ALIGN - 1);
4404 virtual_offset += VIRT_ALIGN - 1;
4405 virtual_offset &= ~(VIRT_ALIGN - 1);
4407 assembly->sections [i].offset = file_offset;
4408 assembly->sections [i].rva = virtual_offset;
4410 file_offset += assembly->sections [i].size;
4411 virtual_offset += assembly->sections [i].size;
4412 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4415 file_offset += FILE_ALIGN - 1;
4416 file_offset &= ~(FILE_ALIGN - 1);
4417 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4419 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4421 /* back-patch info */
4422 msdos = (MonoMSDOSHeader*)pefile->data;
4423 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4424 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4425 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4427 header = (MonoDotNetHeader*)(pefile->data + header_start);
4428 header->pesig [0] = 'P';
4429 header->pesig [1] = 'E';
4431 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4432 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4433 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4434 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4435 if (assemblyb->pekind == 1) {
4437 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4440 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4443 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4445 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4446 header->pe.pe_major = 6;
4447 header->pe.pe_minor = 0;
4448 size = assembly->sections [MONO_SECTION_TEXT].size;
4449 size += FILE_ALIGN - 1;
4450 size &= ~(FILE_ALIGN - 1);
4451 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4452 size = assembly->sections [MONO_SECTION_RSRC].size;
4453 size += FILE_ALIGN - 1;
4454 size &= ~(FILE_ALIGN - 1);
4455 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4456 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4457 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4458 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4459 /* pe_rva_entry_point always at the beginning of the text section */
4460 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4462 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4463 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4464 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4465 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4466 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4467 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4468 size = section_start;
4469 size += FILE_ALIGN - 1;
4470 size &= ~(FILE_ALIGN - 1);
4471 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4473 size += VIRT_ALIGN - 1;
4474 size &= ~(VIRT_ALIGN - 1);
4475 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4478 // Translate the PEFileKind value to the value expected by the Windows loader
4481 short kind = assemblyb->pekind;
4484 // PEFileKinds.ConsoleApplication == 2
4485 // PEFileKinds.WindowApplication == 3
4488 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4489 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4495 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4497 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4498 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4499 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4500 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4501 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4502 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4504 /* fill data directory entries */
4506 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4507 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4509 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4510 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4512 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4513 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4514 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4515 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4516 /* patch imported function RVA name */
4517 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4518 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4520 /* the import table */
4521 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4522 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4523 /* patch imported dll RVA name and other entries in the dir */
4524 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4525 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4526 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4527 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4528 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4529 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4531 p = (assembly->code.data + assembly->ilt_offset);
4532 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4533 *p++ = (value) & 0xff;
4534 *p++ = (value >> 8) & (0xff);
4535 *p++ = (value >> 16) & (0xff);
4536 *p++ = (value >> 24) & (0xff);
4538 /* the CLI header info */
4539 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4540 cli_header->ch_size = GUINT32_FROM_LE (72);
4541 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4542 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4543 if (assemblyb->entry_point) {
4544 guint32 table_idx = 0;
4545 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4546 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4547 table_idx = methodb->table_idx;
4550 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4551 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4554 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4555 /* The embedded managed resources */
4556 text_offset = assembly->text_rva + assembly->code.index;
4557 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4558 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4559 text_offset += assembly->resources.index;
4560 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4561 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4562 text_offset += assembly->meta_size;
4563 if (assembly->strong_name_size) {
4564 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4565 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4566 text_offset += assembly->strong_name_size;
4569 /* write the section tables and section content */
4570 section = (MonoSectionTable*)(pefile->data + section_start);
4571 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4572 static const char *section_names [] = {
4573 ".text", ".rsrc", ".reloc"
4575 if (!assembly->sections [i].size)
4577 strcpy (section->st_name, section_names [i]);
4578 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4579 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4580 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4581 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4582 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4583 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4584 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4586 case MONO_SECTION_TEXT:
4587 /* patch entry point */
4588 p = (assembly->code.data + 2);
4589 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4590 *p++ = (value) & 0xff;
4591 *p++ = (value >> 8) & 0xff;
4592 *p++ = (value >> 16) & 0xff;
4593 *p++ = (value >> 24) & 0xff;
4595 text_offset = assembly->sections [i].offset;
4596 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4597 text_offset += assembly->code.index;
4598 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4599 text_offset += assembly->resources.index;
4600 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4601 text_offset += assembly->meta_size;
4602 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4604 g_free (assembly->image.raw_metadata);
4606 case MONO_SECTION_RELOC:
4607 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4608 *rva = GUINT32_FROM_LE (assembly->text_rva);
4610 *rva = GUINT32_FROM_LE (12);
4612 data16 = (guint16*)rva;
4614 * the entrypoint is always at the start of the text section
4615 * 3 is IMAGE_REL_BASED_HIGHLOW
4616 * 2 is patch_size_rva - text_rva
4618 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4620 *data16 = 0; /* terminate */
4622 case MONO_SECTION_RSRC:
4623 if (assembly->win32_res) {
4624 text_offset = assembly->sections [i].offset;
4626 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4627 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4629 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4633 g_assert_not_reached ();
4638 /* check that the file is properly padded */
4641 FILE *f = fopen ("mypetest.exe", "w");
4642 fwrite (pefile->data, pefile->index, 1, f);
4648 MonoReflectionModule *
4649 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4653 MonoImageOpenStatus status;
4654 MonoDynamicAssembly *assembly;
4656 name = mono_string_to_utf8 (fileName);
4658 image = mono_image_open (name, &status);
4661 if (status == MONO_IMAGE_ERROR_ERRNO)
4662 exc = mono_get_exception_file_not_found (fileName);
4664 exc = mono_get_exception_bad_image_format (name);
4666 mono_raise_exception (exc);
4671 assembly = ab->dynamic_assembly;
4672 image->assembly = (MonoAssembly*)assembly;
4674 mono_assembly_load_references (image, &status);
4676 mono_image_close (image);
4677 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4680 return mono_module_get_object (mono_domain_get (), image);
4684 * We need to return always the same object for MethodInfo, FieldInfo etc..
4685 * but we need to consider the reflected type.
4686 * type uses a different hash, since it uses custom hash/equal functions.
4691 MonoClass *refclass;
4695 reflected_equal (gconstpointer a, gconstpointer b) {
4696 const ReflectedEntry *ea = a;
4697 const ReflectedEntry *eb = b;
4699 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4703 reflected_hash (gconstpointer a) {
4704 const ReflectedEntry *ea = a;
4705 return GPOINTER_TO_UINT (ea->item);
4708 #define CHECK_OBJECT(t,p,k) \
4714 mono_domain_lock (domain); \
4715 if (!domain->refobject_hash) \
4716 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4717 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4718 mono_domain_unlock (domain); \
4724 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4726 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4729 #define CACHE_OBJECT(p,o,k) \
4731 ReflectedEntry *e = ALLOC_REFENTRY; \
4733 e->refclass = (k); \
4734 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4735 mono_domain_unlock (domain); \
4739 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4741 /* this is done only once */
4742 mono_domain_lock (domain);
4743 CACHE_OBJECT (assembly, res, NULL);
4747 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4749 /* this is done only once */
4750 mono_domain_lock (domain);
4751 CACHE_OBJECT (module, res, NULL);
4755 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4757 MonoDynamicImage *image = moduleb->dynamic_image;
4758 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4761 * FIXME: we already created an image in mono_image_basic_init (), but
4762 * we don't know which module it belongs to, since that is only
4763 * determined at assembly save time.
4765 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4766 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4768 moduleb->module.image = &image->image;
4769 moduleb->dynamic_image = image;
4770 register_module (mono_object_domain (moduleb), moduleb, image);
4775 * mono_assembly_get_object:
4776 * @domain: an app domain
4777 * @assembly: an assembly
4779 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4781 MonoReflectionAssembly*
4782 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4784 static MonoClass *System_Reflection_Assembly;
4785 MonoReflectionAssembly *res;
4787 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4788 if (!System_Reflection_Assembly)
4789 System_Reflection_Assembly = mono_class_from_name (
4790 mono_defaults.corlib, "System.Reflection", "Assembly");
4791 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4792 res->assembly = assembly;
4793 CACHE_OBJECT (assembly, res, NULL);
4799 MonoReflectionModule*
4800 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4802 static MonoClass *System_Reflection_Module;
4803 MonoReflectionModule *res;
4805 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4806 if (!System_Reflection_Module)
4807 System_Reflection_Module = mono_class_from_name (
4808 mono_defaults.corlib, "System.Reflection", "Module");
4809 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4812 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4814 res->fqname = mono_string_new (domain, image->name);
4815 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4816 res->scopename = mono_string_new (domain, image->module_name);
4818 mono_image_addref (image);
4820 CACHE_OBJECT (image, res, NULL);
4824 MonoReflectionModule*
4825 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4827 static MonoClass *System_Reflection_Module;
4828 MonoReflectionModule *res;
4829 MonoTableInfo *table;
4830 guint32 cols [MONO_FILE_SIZE];
4832 guint32 i, name_idx;
4835 if (!System_Reflection_Module)
4836 System_Reflection_Module = mono_class_from_name (
4837 mono_defaults.corlib, "System.Reflection", "Module");
4838 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4840 table = &image->tables [MONO_TABLE_FILE];
4841 g_assert (table_index < table->rows);
4842 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4845 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4846 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4848 // Check whenever the row has a corresponding row in the moduleref table
4849 table = &image->tables [MONO_TABLE_MODULEREF];
4850 for (i = 0; i < table->rows; ++i) {
4851 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4852 val = mono_metadata_string_heap (image, name_idx);
4853 if (strcmp (val, name) == 0)
4854 res->image = image->modules [i];
4857 res->fqname = mono_string_new (domain, name);
4858 res->name = mono_string_new (domain, name);
4859 res->scopename = mono_string_new (domain, name);
4860 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4866 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4868 if ((t1->type != t2->type) ||
4869 (t1->byref != t2->byref))
4873 case MONO_TYPE_VOID:
4874 case MONO_TYPE_BOOLEAN:
4875 case MONO_TYPE_CHAR:
4886 case MONO_TYPE_STRING:
4889 case MONO_TYPE_OBJECT:
4890 case MONO_TYPE_TYPEDBYREF:
4892 case MONO_TYPE_VALUETYPE:
4893 case MONO_TYPE_CLASS:
4894 case MONO_TYPE_SZARRAY:
4895 return t1->data.klass == t2->data.klass;
4897 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4898 case MONO_TYPE_ARRAY:
4899 if (t1->data.array->rank != t2->data.array->rank)
4901 return t1->data.array->eklass == t2->data.array->eklass;
4902 case MONO_TYPE_GENERICINST: {
4904 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4906 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4908 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4909 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4915 case MONO_TYPE_MVAR:
4916 return t1->data.generic_param == t2->data.generic_param;
4918 g_error ("implement type compare for %0x!", t1->type);
4926 mymono_metadata_type_hash (MonoType *t1)
4932 hash |= t1->byref << 6; /* do not collide with t1->type values */
4934 case MONO_TYPE_VALUETYPE:
4935 case MONO_TYPE_CLASS:
4936 case MONO_TYPE_SZARRAY:
4937 /* check if the distribution is good enough */
4938 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4940 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4945 static MonoReflectionGenericInst*
4946 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4948 static MonoClass *System_Reflection_MonoGenericInst;
4949 MonoReflectionGenericInst *res;
4950 MonoGenericInst *ginst;
4953 if (!System_Reflection_MonoGenericInst) {
4954 System_Reflection_MonoGenericInst = mono_class_from_name (
4955 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4956 g_assert (System_Reflection_MonoGenericInst);
4959 ginst = geninst->data.generic_inst;
4960 gklass = mono_class_from_mono_type (ginst->generic_type);
4962 mono_class_init (ginst->klass);
4964 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4966 res->type.type = geninst;
4967 if (gklass->wastypebuilder && gklass->reflection_info)
4968 res->generic_type = gklass->reflection_info;
4970 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4976 * mono_type_get_object:
4977 * @domain: an app domain
4980 * Return an System.MonoType object representing the type @type.
4983 mono_type_get_object (MonoDomain *domain, MonoType *type)
4985 MonoReflectionType *res;
4986 MonoClass *klass = mono_class_from_mono_type (type);
4988 mono_domain_lock (domain);
4989 if (!domain->type_hash)
4990 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4991 (GCompareFunc)mymono_metadata_type_equal);
4992 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4993 mono_domain_unlock (domain);
4996 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4997 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4998 mono_g_hash_table_insert (domain->type_hash, type, res);
4999 mono_domain_unlock (domain);
5002 if (klass->reflection_info && !klass->wastypebuilder) {
5003 //g_assert_not_reached ();
5004 /* should this be considered an error condition? */
5006 mono_domain_unlock (domain);
5007 return klass->reflection_info;
5010 mono_class_init (klass);
5011 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5013 mono_g_hash_table_insert (domain->type_hash, type, res);
5014 mono_domain_unlock (domain);
5019 * mono_method_get_object:
5020 * @domain: an app domain
5022 * @refclass: the reflected type (can be NULL)
5024 * Return an System.Reflection.MonoMethod object representing the method @method.
5026 MonoReflectionMethod*
5027 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5030 * We use the same C representation for methods and constructors, but the type
5031 * name in C# is different.
5035 MonoReflectionMethod *ret;
5038 refclass = method->klass;
5040 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5041 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5042 cname = "MonoCMethod";
5044 cname = "MonoMethod";
5045 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5047 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5048 ret->method = method;
5049 ret->name = mono_string_new (domain, method->name);
5050 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5051 CACHE_OBJECT (method, ret, refclass);
5056 * mono_field_get_object:
5057 * @domain: an app domain
5061 * Return an System.Reflection.MonoField object representing the field @field
5064 MonoReflectionField*
5065 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5067 MonoReflectionField *res;
5070 CHECK_OBJECT (MonoReflectionField *, field, klass);
5071 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5072 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5075 res->name = mono_string_new (domain, field->name);
5076 res->attrs = field->type->attrs;
5077 res->type = mono_type_get_object (domain, field->type);
5078 CACHE_OBJECT (field, res, klass);
5083 * mono_property_get_object:
5084 * @domain: an app domain
5086 * @property: a property
5088 * Return an System.Reflection.MonoProperty object representing the property @property
5091 MonoReflectionProperty*
5092 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5094 MonoReflectionProperty *res;
5097 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5098 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5099 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5101 res->property = property;
5102 CACHE_OBJECT (property, res, klass);
5107 * mono_event_get_object:
5108 * @domain: an app domain
5112 * Return an System.Reflection.MonoEvent object representing the event @event
5115 MonoReflectionEvent*
5116 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5118 MonoReflectionEvent *res;
5121 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5122 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5123 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5126 CACHE_OBJECT (event, res, klass);
5131 * mono_param_get_objects:
5132 * @domain: an app domain
5135 * Return an System.Reflection.ParameterInfo array object representing the parameters
5136 * in the method @method.
5139 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5141 static MonoClass *System_Reflection_ParameterInfo;
5142 MonoArray *res = NULL;
5143 MonoReflectionMethod *member = NULL;
5144 MonoReflectionParameter *param = NULL;
5148 if (!System_Reflection_ParameterInfo)
5149 System_Reflection_ParameterInfo = mono_class_from_name (
5150 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5152 if (!method->signature->param_count)
5153 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5155 /* Note: the cache is based on the address of the signature into the method
5156 * since we already cache MethodInfos with the method as keys.
5158 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5160 member = mono_method_get_object (domain, method, NULL);
5161 names = g_new (char *, method->signature->param_count);
5162 mono_method_get_param_names (method, (const char **) names);
5164 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5165 for (i = 0; i < method->signature->param_count; ++i) {
5166 param = (MonoReflectionParameter *)mono_object_new (domain,
5167 System_Reflection_ParameterInfo);
5168 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5169 param->DefaultValueImpl = NULL; /* FIXME */
5170 param->MemberImpl = (MonoObject*)member;
5171 param->NameImpl = mono_string_new (domain, names [i]);
5172 param->PositionImpl = i;
5173 param->AttrsImpl = method->signature->params [i]->attrs;
5174 mono_array_set (res, gpointer, i, param);
5177 CACHE_OBJECT (&(method->signature), res, NULL);
5182 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5186 memset (assembly, 0, sizeof (MonoAssemblyName));
5188 assembly->culture = "";
5190 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5193 while (*p == ' ' || *p == ',') {
5202 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5204 assembly->major = strtoul (p, &s, 10);
5205 if (s == p || *s != '.')
5208 assembly->minor = strtoul (p, &s, 10);
5209 if (s == p || *s != '.')
5212 assembly->build = strtoul (p, &s, 10);
5213 if (s == p || *s != '.')
5216 assembly->revision = strtoul (p, &s, 10);
5219 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5221 if (strncmp (p, "neutral", 7) == 0) {
5222 assembly->culture = "";
5225 assembly->culture = p;
5226 while (*p && *p != ',') {
5230 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5233 while (*s && isxdigit (*s)) {
5237 assembly->hash_len = s - p;
5238 if (!(s-p) || ((s-p) & 1))
5240 assembly->hash_value = s = p;
5241 while (*s && isxdigit (*s)) {
5243 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5246 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5251 while (*p && *p != ',')
5255 while (*p == ' ' || *p == ',') {
5269 * mono_reflection_parse_type:
5272 * Parse a type name as accepted by the GetType () method and output the info
5273 * extracted in the info structure.
5274 * the name param will be mangled, so, make a copy before passing it to this function.
5275 * The fields in info will be valid until the memory pointed to by name is valid.
5276 * Returns 0 on parse error.
5277 * See also mono_type_get_name () below.
5280 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5282 char *start, *p, *w, *last_point, *startn;
5283 int in_modifiers = 0;
5284 int isbyref = 0, rank;
5286 start = p = w = name;
5288 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5289 info->name = info->name_space = NULL;
5290 info->nested = NULL;
5291 info->modifiers = NULL;
5293 /* last_point separates the namespace from the name */
5299 *p = 0; /* NULL terminate the name */
5301 info->nested = g_list_append (info->nested, startn);
5302 /* we have parsed the nesting namespace + name */
5306 info->name_space = start;
5308 info->name = last_point + 1;
5310 info->name_space = (char *)"";
5336 info->name_space = start;
5338 info->name = last_point + 1;
5340 info->name_space = (char *)"";
5347 if (isbyref) /* only one level allowed by the spec */
5350 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5354 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5365 else if (*p != '*') /* '*' means unknown lower bound */
5371 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5383 return 0; /* missing assembly name */
5384 if (!assembly_name_to_aname (&info->assembly, p))
5391 if (info->assembly.name)
5394 *w = 0; /* terminate class name */
5395 if (!info->name || !*info->name)
5397 /* add other consistency checks */
5402 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5409 image = mono_defaults.corlib;
5412 klass = mono_class_from_name_case (image, info->name_space, info->name);
5414 klass = mono_class_from_name (image, info->name_space, info->name);
5417 for (mod = info->nested; mod; mod = mod->next) {
5420 mono_class_init (klass);
5421 nested = klass->nested_classes;
5424 klass = nested->data;
5426 if (g_strcasecmp (klass->name, mod->data) == 0)
5429 if (strcmp (klass->name, mod->data) == 0)
5433 nested = nested->next;
5440 mono_class_init (klass);
5441 for (mod = info->modifiers; mod; mod = mod->next) {
5442 modval = GPOINTER_TO_UINT (mod->data);
5443 if (!modval) { /* byref: must be last modifier */
5444 return &klass->this_arg;
5445 } else if (modval == -1) {
5446 klass = mono_ptr_class_get (&klass->byval_arg);
5447 } else { /* array rank */
5448 klass = mono_array_class_get (klass, modval);
5450 mono_class_init (klass);
5453 return &klass->byval_arg;
5457 * mono_reflection_get_type:
5458 * @image: a metadata context
5459 * @info: type description structure
5460 * @ignorecase: flag for case-insensitive string compares
5462 * Build a MonoType from the type description in @info.
5467 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5470 MonoReflectionAssembly *assembly;
5474 type = mono_reflection_get_type_internal (image, info, ignorecase);
5477 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5480 // Reconstruct the type name
5481 fullName = g_string_new ("");
5482 if (info->name_space && (info->name_space [0] != '\0'))
5483 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5485 g_string_printf (fullName, info->name);
5486 for (mod = info->nested; mod; mod = mod->next)
5487 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5490 mono_domain_try_type_resolve (
5491 mono_domain_get (), fullName->str, NULL);
5492 if (assembly && (!image || (assembly->assembly->image == image)))
5493 type = mono_reflection_get_type_internal (assembly->assembly->image,
5495 g_string_free (fullName, TRUE);
5500 * mono_reflection_type_from_name:
5502 * @image: a metadata context (can be NULL).
5504 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5505 * it defaults to get the type from @image or, if @image is NULL or loading
5506 * from it fails, uses corlib.
5510 mono_reflection_type_from_name (char *name, MonoImage *image)
5513 MonoTypeNameParse info;
5514 MonoAssembly *assembly;
5516 /*g_print ("requested type %s\n", str);*/
5517 if (!mono_reflection_parse_type (name, &info)) {
5518 g_list_free (info.modifiers);
5519 g_list_free (info.nested);
5523 if (info.assembly.name) {
5524 assembly = mono_assembly_loaded (&info.assembly);
5525 /* do we need to load if it's not already loaded? */
5527 g_list_free (info.modifiers);
5528 g_list_free (info.nested);
5532 image = assembly->image;
5533 } else if (image == NULL) {
5534 image = mono_defaults.corlib;
5537 type = mono_reflection_get_type (image, &info, FALSE);
5538 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5539 image = mono_defaults.corlib;
5540 type = mono_reflection_get_type (image, &info, FALSE);
5543 g_list_free (info.modifiers);
5544 g_list_free (info.nested);
5549 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5551 int slen, type = t->type;
5556 case MONO_TYPE_BOOLEAN: {
5557 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5562 case MONO_TYPE_CHAR:
5564 case MONO_TYPE_I2: {
5565 guint16 *val = g_malloc (sizeof (guint16));
5570 #if SIZEOF_VOID_P == 4
5576 case MONO_TYPE_I4: {
5577 guint32 *val = g_malloc (sizeof (guint32));
5582 #if SIZEOF_VOID_P == 8
5583 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5588 case MONO_TYPE_I8: {
5589 guint64 *val = g_malloc (sizeof (guint64));
5594 case MONO_TYPE_VALUETYPE:
5595 if (t->data.klass->enumtype) {
5596 type = t->data.klass->enum_basetype->type;
5599 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5602 case MONO_TYPE_STRING:
5603 if (*p == (char)0xFF) {
5607 slen = mono_metadata_decode_value (p, &p);
5609 return mono_string_new_len (mono_domain_get (), p, slen);
5610 case MONO_TYPE_CLASS: {
5613 if (*p == (char)0xFF) {
5618 slen = mono_metadata_decode_value (p, &p);
5619 n = g_memdup (p, slen + 1);
5621 t = mono_reflection_type_from_name (n, image);
5623 g_warning ("Cannot load type '%s'", n);
5627 return mono_type_get_object (mono_domain_get (), t);
5631 case MONO_TYPE_OBJECT: {
5634 MonoClass *subc = NULL;
5639 } else if (subt == 0x0E) {
5640 type = MONO_TYPE_STRING;
5642 } else if (subt == 0x55) {
5645 slen = mono_metadata_decode_value (p, &p);
5646 n = g_memdup (p, slen + 1);
5648 t = mono_reflection_type_from_name (n, image);
5650 g_warning ("Cannot load type '%s'", n);
5653 subc = mono_class_from_mono_type (t);
5654 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5655 MonoType simple_type = {{0}};
5656 simple_type.type = subt;
5657 subc = mono_class_from_mono_type (&simple_type);
5659 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5661 val = load_cattr_value (image, &subc->byval_arg, p, end);
5662 obj = mono_object_new (mono_domain_get (), subc);
5663 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5667 case MONO_TYPE_SZARRAY:
5670 guint32 i, alen, basetype;
5673 if (alen == 0xffffffff) {
5677 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5678 basetype = t->data.klass->byval_arg.type;
5683 case MONO_TYPE_BOOLEAN:
5684 for (i=0;i<alen;i++)
5686 MonoBoolean val=*p++;
5687 mono_array_set(arr,MonoBoolean,i,val);
5690 case MONO_TYPE_CHAR:
5693 for (i=0;i<alen;i++)
5695 guint16 val=read16(p);
5696 mono_array_set(arr,guint16,i,val);
5703 for (i=0;i<alen;i++)
5705 guint32 val=read32(p);
5706 mono_array_set(arr,guint32,i,val);
5713 for (i=0;i<alen;i++)
5715 guint64 val=read64(p);
5716 mono_array_set(arr,guint64,i,val);
5720 case MONO_TYPE_CLASS:
5721 case MONO_TYPE_STRING:
5722 for (i = 0; i < alen; i++) {
5723 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5724 mono_array_set (arr, gpointer, i, item);
5728 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5734 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5740 type_is_reference (MonoType *type)
5742 switch (type->type) {
5743 case MONO_TYPE_BOOLEAN:
5744 case MONO_TYPE_CHAR:
5757 case MONO_TYPE_VALUETYPE:
5765 free_param_data (MonoMethodSignature *sig, void **params) {
5767 for (i = 0; i < sig->param_count; ++i) {
5768 if (!type_is_reference (sig->params [i]))
5769 g_free (params [i]);
5774 * Find the method index in the metadata methodDef table.
5775 * Later put these three helper methods in metadata and export them.
5778 find_method_index (MonoMethod *method) {
5779 MonoClass *klass = method->klass;
5782 for (i = 0; i < klass->method.count; ++i) {
5783 if (method == klass->methods [i])
5784 return klass->method.first + 1 + i;
5790 * Find the field index in the metadata FieldDef table.
5793 find_field_index (MonoClass *klass, MonoClassField *field) {
5796 for (i = 0; i < klass->field.count; ++i) {
5797 if (field == &klass->fields [i])
5798 return klass->field.first + 1 + i;
5804 * Find the property index in the metadata Property table.
5807 find_property_index (MonoClass *klass, MonoProperty *property) {
5810 for (i = 0; i < klass->property.count; ++i) {
5811 if (property == &klass->properties [i])
5812 return klass->property.first + 1 + i;
5818 * Find the event index in the metadata Event table.
5821 find_event_index (MonoClass *klass, MonoEvent *event) {
5824 for (i = 0; i < klass->event.count; ++i) {
5825 if (event == &klass->events [i])
5826 return klass->event.first + 1 + i;
5832 create_custom_attr (MonoImage *image, MonoMethod *method,
5833 const char *data, guint32 len)
5835 const char *p = data;
5837 guint32 i, j, num_named;
5841 mono_class_init (method->klass);
5844 attr = mono_object_new (mono_domain_get (), method->klass);
5845 mono_runtime_invoke (method, attr, NULL, NULL);
5849 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5852 /*g_print ("got attr %s\n", method->klass->name);*/
5854 params = g_new (void*, method->signature->param_count);
5858 for (i = 0; i < method->signature->param_count; ++i) {
5859 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5863 attr = mono_object_new (mono_domain_get (), method->klass);
5864 mono_runtime_invoke (method, attr, params, NULL);
5865 free_param_data (method->signature, params);
5867 num_named = read16 (named);
5869 for (j = 0; j < num_named; j++) {
5871 char *name, named_type, data_type;
5872 named_type = *named++;
5873 data_type = *named++; /* type of data */
5874 if (data_type == 0x55) {
5877 type_len = mono_metadata_decode_blob_size (named, &named);
5878 type_name = g_malloc (type_len + 1);
5879 memcpy (type_name, named, type_len);
5880 type_name [type_len] = 0;
5882 /* FIXME: lookup the type and check type consistency */
5885 if (data_type == MONO_TYPE_SZARRAY)
5886 /* The spec does not mention this */
5888 name_len = mono_metadata_decode_blob_size (named, &named);
5889 name = g_malloc (name_len + 1);
5890 memcpy (name, named, name_len);
5891 name [name_len] = 0;
5893 if (named_type == 0x53) {
5894 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5895 void *val = load_cattr_value (image, field->type, named, &named);
5896 mono_field_set_value (attr, field, val);
5897 if (!type_is_reference (field->type))
5899 } else if (named_type == 0x54) {
5902 MonoType *prop_type;
5904 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5905 /* can we have more that 1 arg in a custom attr named property? */
5906 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5907 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5908 mono_property_set_value (prop, attr, pparams, NULL);
5909 if (!type_is_reference (prop_type))
5910 g_free (pparams [0]);
5919 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5926 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5927 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5928 for (i = 0; i < cinfo->num_attrs; ++i) {
5929 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5930 mono_array_set (result, gpointer, i, attr);
5936 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5938 guint32 mtoken, i, len;
5939 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5941 MonoCustomAttrInfo *ainfo;
5942 GList *tmp, *list = NULL;
5945 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5947 i = mono_metadata_custom_attrs_from_index (image, idx);
5951 while (i < ca->rows) {
5952 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5954 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5957 len = g_list_length (list);
5960 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5961 ainfo->num_attrs = len;
5962 ainfo->image = image;
5963 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5964 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5965 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5966 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5967 case CUSTOM_ATTR_TYPE_METHODDEF:
5968 mtoken |= MONO_TOKEN_METHOD_DEF;
5970 case CUSTOM_ATTR_TYPE_MEMBERREF:
5971 mtoken |= MONO_TOKEN_MEMBER_REF;
5974 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5977 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5978 if (!ainfo->attrs [i].ctor)
5979 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5980 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5981 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5982 ainfo->attrs [i].data = data;
5990 mono_custom_attrs_from_method (MonoMethod *method)
5992 MonoCustomAttrInfo *cinfo;
5995 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5997 idx = find_method_index (method);
5998 idx <<= CUSTOM_ATTR_BITS;
5999 idx |= CUSTOM_ATTR_METHODDEF;
6000 return mono_custom_attrs_from_index (method->klass->image, idx);
6004 mono_custom_attrs_from_class (MonoClass *klass)
6006 MonoCustomAttrInfo *cinfo;
6009 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6011 idx = mono_metadata_token_index (klass->type_token);
6012 idx <<= CUSTOM_ATTR_BITS;
6013 idx |= CUSTOM_ATTR_TYPEDEF;
6014 return mono_custom_attrs_from_index (klass->image, idx);
6018 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6020 MonoCustomAttrInfo *cinfo;
6023 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6025 idx = 1; /* there is only one assembly */
6026 idx <<= CUSTOM_ATTR_BITS;
6027 idx |= CUSTOM_ATTR_ASSEMBLY;
6028 return mono_custom_attrs_from_index (assembly->image, idx);
6031 static MonoCustomAttrInfo*
6032 mono_custom_attrs_from_module (MonoImage *image)
6034 MonoCustomAttrInfo *cinfo;
6037 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6039 idx = 1; /* there is only one module */
6040 idx <<= CUSTOM_ATTR_BITS;
6041 idx |= CUSTOM_ATTR_MODULE;
6042 return mono_custom_attrs_from_index (image, idx);
6046 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6048 MonoCustomAttrInfo *cinfo;
6051 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6053 idx = find_property_index (klass, property);
6054 idx <<= CUSTOM_ATTR_BITS;
6055 idx |= CUSTOM_ATTR_PROPERTY;
6056 return mono_custom_attrs_from_index (klass->image, idx);
6060 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6062 MonoCustomAttrInfo *cinfo;
6065 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6067 idx = find_event_index (klass, event);
6068 idx <<= CUSTOM_ATTR_BITS;
6069 idx |= CUSTOM_ATTR_EVENT;
6070 return mono_custom_attrs_from_index (klass->image, idx);
6074 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6076 MonoCustomAttrInfo *cinfo;
6079 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6081 idx = find_field_index (klass, field);
6082 idx <<= CUSTOM_ATTR_BITS;
6083 idx |= CUSTOM_ATTR_FIELDDEF;
6084 return mono_custom_attrs_from_index (klass->image, idx);
6088 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6091 guint32 i, idx, method_index;
6092 guint32 param_list, param_last, param_pos, found;
6094 MonoReflectionMethodAux *aux;
6096 if (method->klass->image->dynamic) {
6097 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6098 if (!aux || !aux->param_cattr)
6100 return aux->param_cattr [param];
6103 image = method->klass->image;
6104 method_index = find_method_index (method);
6105 ca = &image->tables [MONO_TABLE_METHOD];
6107 if (method->klass->generic_inst || method->klass->gen_params ||
6108 method->signature->generic_param_count) {
6109 // FIXME FIXME FIXME
6113 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6114 if (method_index == ca->rows) {
6115 ca = &image->tables [MONO_TABLE_PARAM];
6116 param_last = ca->rows + 1;
6118 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6119 ca = &image->tables [MONO_TABLE_PARAM];
6122 for (i = param_list; i < param_last; ++i) {
6123 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6124 if (param_pos == param) {
6132 idx <<= CUSTOM_ATTR_BITS;
6133 idx |= CUSTOM_ATTR_PARAMDEF;
6134 return mono_custom_attrs_from_index (image, idx);
6138 * mono_reflection_get_custom_attrs:
6139 * @obj: a reflection object handle
6141 * Return an array with all the custom attributes defined of the
6142 * reflection handle @obj. The objects are fully build.
6145 mono_reflection_get_custom_attrs (MonoObject *obj)
6149 MonoCustomAttrInfo *cinfo = NULL;
6151 MONO_ARCH_SAVE_REGS;
6153 klass = obj->vtable->klass;
6154 /* FIXME: need to handle: Module */
6155 if (klass == mono_defaults.monotype_class) {
6156 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6157 klass = mono_class_from_mono_type (rtype->type);
6158 cinfo = mono_custom_attrs_from_class (klass);
6159 } else if (strcmp ("Assembly", klass->name) == 0) {
6160 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6161 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6162 } else if (strcmp ("Module", klass->name) == 0) {
6163 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6164 cinfo = mono_custom_attrs_from_module (module->image);
6165 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6166 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6167 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6168 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6169 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6170 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6171 } else if (strcmp ("MonoField", klass->name) == 0) {
6172 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6173 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6174 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6175 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6176 cinfo = mono_custom_attrs_from_method (rmethod->method);
6177 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6178 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6179 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6180 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6181 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6182 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6183 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6184 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6185 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6186 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6187 } else { /* handle other types here... */
6188 g_error ("get custom attrs not yet supported for %s", klass->name);
6192 result = mono_custom_attrs_construct (cinfo);
6194 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6195 result = mono_array_new (mono_domain_get (), klass, 0);
6201 static MonoMethodSignature*
6202 parameters_to_signature (MonoArray *parameters) {
6203 MonoMethodSignature *sig;
6206 count = parameters? mono_array_length (parameters): 0;
6208 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6209 sig->param_count = count;
6210 sig->sentinelpos = -1; /* FIXME */
6211 for (i = 0; i < count; ++i) {
6212 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6213 sig->params [i] = pt->type;
6218 static MonoMethodSignature*
6219 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6220 MonoMethodSignature *sig;
6222 sig = parameters_to_signature (ctor->parameters);
6223 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6224 sig->ret = &mono_defaults.void_class->byval_arg;
6228 static MonoMethodSignature*
6229 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6230 MonoMethodSignature *sig;
6232 sig = parameters_to_signature (method->parameters);
6233 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6234 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6235 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6239 static MonoMethodSignature*
6240 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6241 MonoMethodSignature *sig;
6243 sig = parameters_to_signature (method->parameters);
6244 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6245 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6246 sig->generic_param_count = 0;
6251 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6253 MonoClass *klass = mono_object_class (prop);
6254 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6255 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6256 *name = mono_string_to_utf8 (pb->name);
6257 *type = pb->type->type;
6259 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6260 *name = g_strdup (p->property->name);
6261 if (p->property->get)
6262 *type = p->property->get->signature->ret;
6264 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6269 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6271 MonoClass *klass = mono_object_class (field);
6272 if (strcmp (klass->name, "FieldBuilder") == 0) {
6273 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6274 *name = mono_string_to_utf8 (fb->name);
6275 *type = fb->type->type;
6277 MonoReflectionField *f = (MonoReflectionField *)field;
6278 *name = g_strdup (f->field->name);
6279 *type = f->field->type;
6284 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6287 MonoTypeEnum simple_type;
6289 if ((p-buffer) + 10 >= *buflen) {
6292 newbuf = g_realloc (buffer, *buflen);
6293 p = newbuf + (p-buffer);
6296 argval = ((char*)arg + sizeof (MonoObject));
6297 simple_type = type->type;
6299 switch (simple_type) {
6300 case MONO_TYPE_BOOLEAN:
6305 case MONO_TYPE_CHAR:
6308 swap_with_size (p, argval, 2, 1);
6314 swap_with_size (p, argval, 4, 1);
6320 swap_with_size (p, argval, 8, 1);
6323 case MONO_TYPE_VALUETYPE:
6324 if (type->data.klass->enumtype) {
6325 simple_type = type->data.klass->enum_basetype->type;
6328 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6331 case MONO_TYPE_STRING: {
6338 str = mono_string_to_utf8 ((MonoString*)arg);
6339 slen = strlen (str);
6340 if ((p-buffer) + 10 + slen >= *buflen) {
6344 newbuf = g_realloc (buffer, *buflen);
6345 p = newbuf + (p-buffer);
6348 mono_metadata_encode_value (slen, p, &p);
6349 memcpy (p, str, slen);
6354 case MONO_TYPE_CLASS: {
6362 k = mono_object_class (arg);
6363 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6364 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6365 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6367 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6368 slen = strlen (str);
6369 if ((p-buffer) + 10 + slen >= *buflen) {
6373 newbuf = g_realloc (buffer, *buflen);
6374 p = newbuf + (p-buffer);
6377 mono_metadata_encode_value (slen, p, &p);
6378 memcpy (p, str, slen);
6383 case MONO_TYPE_SZARRAY: {
6388 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6391 len = mono_array_length ((MonoArray*)arg);
6393 *p++ = (len >> 8) & 0xff;
6394 *p++ = (len >> 16) & 0xff;
6395 *p++ = (len >> 24) & 0xff;
6397 *retbuffer = buffer;
6398 eclass = type->data.klass;
6399 for (i = 0; i < len; ++i) {
6400 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6404 /* it may be a boxed value or a Type */
6405 case MONO_TYPE_OBJECT: {
6406 MonoClass *klass = mono_object_class (arg);
6410 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6413 } else if (klass->enumtype) {
6415 } else if (klass == mono_defaults.string_class) {
6416 simple_type = MONO_TYPE_STRING;
6419 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6420 *p++ = simple_type = klass->byval_arg.type;
6423 g_error ("unhandled type in custom attr");
6425 str = type_get_qualified_name (klass->enum_basetype, NULL);
6426 slen = strlen (str);
6427 if ((p-buffer) + 10 + slen >= *buflen) {
6431 newbuf = g_realloc (buffer, *buflen);
6432 p = newbuf + (p-buffer);
6435 mono_metadata_encode_value (slen, p, &p);
6436 memcpy (p, str, slen);
6439 simple_type = klass->enum_basetype->type;
6443 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6446 *retbuffer = buffer;
6450 * mono_reflection_get_custom_attrs_blob:
6451 * @ctor: custom attribute constructor
6452 * @ctorArgs: arguments o the constructor
6458 * Creates the blob of data that needs to be saved in the metadata and that represents
6459 * the custom attributed described by @ctor, @ctorArgs etc.
6460 * Returns: a Byte array representing the blob of data.
6463 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6466 MonoMethodSignature *sig;
6471 MONO_ARCH_SAVE_REGS;
6473 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6474 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6476 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6478 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6480 p = buffer = g_malloc (buflen);
6481 /* write the prolog */
6484 for (i = 0; i < sig->param_count; ++i) {
6485 arg = mono_array_get (ctorArgs, MonoObject*, i);
6486 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6490 i += mono_array_length (properties);
6492 i += mono_array_length (fields);
6494 *p++ = (i >> 8) & 0xff;
6497 for (i = 0; i < mono_array_length (properties); ++i) {
6502 prop = mono_array_get (properties, gpointer, i);
6503 get_prop_name_and_type (prop, &pname, &ptype);
6504 *p++ = 0x54; /* PROPERTY signature */
6506 /* Preallocate a large enough buffer */
6507 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6508 char *str = type_get_qualified_name (ptype, NULL);
6514 len += strlen (pname);
6516 if ((p-buffer) + 20 + len >= buflen) {
6520 newbuf = g_realloc (buffer, buflen);
6521 p = newbuf + (p-buffer);
6525 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6526 char *str = type_get_qualified_name (ptype, NULL);
6527 int slen = strlen (str);
6531 * This seems to be optional...
6534 mono_metadata_encode_value (slen, p, &p);
6535 memcpy (p, str, slen);
6539 mono_metadata_encode_value (ptype->type, p, &p);
6540 if (ptype->type == MONO_TYPE_SZARRAY)
6541 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6543 len = strlen (pname);
6544 mono_metadata_encode_value (len, p, &p);
6545 memcpy (p, pname, len);
6547 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6554 for (i = 0; i < mono_array_length (fields); ++i) {
6559 field = mono_array_get (fields, gpointer, i);
6560 get_field_name_and_type (field, &fname, &ftype);
6561 *p++ = 0x53; /* FIELD signature */
6562 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6563 char *str = type_get_qualified_name (ftype, NULL);
6564 int slen = strlen (str);
6565 if ((p-buffer) + 10 + slen >= buflen) {
6569 newbuf = g_realloc (buffer, buflen);
6570 p = newbuf + (p-buffer);
6575 * This seems to be optional...
6578 mono_metadata_encode_value (slen, p, &p);
6579 memcpy (p, str, slen);
6583 mono_metadata_encode_value (ftype->type, p, &p);
6585 len = strlen (fname);
6586 mono_metadata_encode_value (len, p, &p);
6587 memcpy (p, fname, len);
6589 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6594 g_assert (p - buffer <= buflen);
6595 buflen = p - buffer;
6596 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6597 p = mono_array_addr (result, char, 0);
6598 memcpy (p, buffer, buflen);
6600 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6606 * mono_reflection_setup_internal_class:
6607 * @tb: a TypeBuilder object
6609 * Creates a MonoClass that represents the TypeBuilder.
6610 * This is a trick that lets us simplify a lot of reflection code
6611 * (and will allow us to support Build and Run assemblies easier).
6614 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6616 MonoClass *klass, *parent;
6618 MONO_ARCH_SAVE_REGS;
6620 klass = g_new0 (MonoClass, 1);
6622 klass->image = &tb->module->dynamic_image->image;
6625 /* check so we can compile corlib correctly */
6626 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6627 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6628 parent = tb->parent->type->data.klass;
6630 parent = my_mono_class_from_mono_type (tb->parent->type);
6634 klass->inited = 1; /* we lie to the runtime */
6635 klass->name = mono_string_to_utf8 (tb->name);
6636 klass->name_space = mono_string_to_utf8 (tb->nspace);
6637 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6638 klass->flags = tb->attrs;
6640 klass->element_class = klass;
6641 klass->reflection_info = tb; /* need to pin. */
6643 /* Put into cache so mono_class_get () will find it */
6644 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6647 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6648 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6652 mono_class_setup_parent (klass, parent);
6653 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6654 const char *old_n = klass->name;
6655 /* trick to get relative numbering right when compiling corlib */
6656 klass->name = "BuildingObject";
6657 mono_class_setup_parent (klass, mono_defaults.object_class);
6658 klass->name = old_n;
6660 mono_class_setup_mono_type (klass);
6662 mono_class_setup_supertypes (klass);
6665 * FIXME: handle interfaces.
6668 tb->type.type = &klass->byval_arg;
6670 if (tb->nesting_type) {
6671 g_assert (tb->nesting_type->type);
6672 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6675 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6679 * mono_reflection_setup_generic_class:
6680 * @tb: a TypeBuilder object
6682 * Setup the generic class after all generic parameters have been added.
6685 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6690 MONO_ARCH_SAVE_REGS;
6692 klass = my_mono_class_from_mono_type (tb->type.type);
6694 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6696 if (klass->gen_params || (count == 0))
6699 klass->num_gen_params = count;
6700 klass->gen_params = g_new0 (MonoGenericParam, count);
6702 for (i = 0; i < count; i++) {
6703 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6704 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6709 * mono_reflection_create_internal_class:
6710 * @tb: a TypeBuilder object
6712 * Actually create the MonoClass that is associated with the TypeBuilder.
6715 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6719 MONO_ARCH_SAVE_REGS;
6721 klass = my_mono_class_from_mono_type (tb->type.type);
6723 if (klass->enumtype && klass->enum_basetype == NULL) {
6724 MonoReflectionFieldBuilder *fb;
6726 g_assert (tb->fields != NULL);
6727 g_assert (mono_array_length (tb->fields) >= 1);
6729 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6731 klass->enum_basetype = fb->type->type;
6732 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6733 if (!klass->element_class)
6734 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6735 klass->instance_size = klass->element_class->instance_size;
6736 klass->size_inited = 1;
6738 * this is almost safe to do with enums and it's needed to be able
6739 * to create objects of the enum type (for use in SetConstant).
6741 /* FIXME: Does this mean enums can't have method overrides ? */
6742 mono_class_setup_vtable (klass, NULL, 0);
6746 static MonoMarshalSpec*
6747 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6748 MonoReflectionMarshal *minfo)
6750 MonoMarshalSpec *res;
6752 res = g_new0 (MonoMarshalSpec, 1);
6753 res->native = minfo->type;
6755 switch (minfo->type) {
6756 case MONO_NATIVE_LPARRAY:
6757 res->data.array_data.elem_type = minfo->eltype;
6758 res->data.array_data.param_num = 0; /* Not yet */
6759 res->data.array_data.num_elem = minfo->count;
6762 case MONO_NATIVE_BYVALTSTR:
6763 case MONO_NATIVE_BYVALARRAY:
6764 res->data.array_data.num_elem = minfo->count;
6767 case MONO_NATIVE_CUSTOM:
6768 if (minfo->marshaltyperef)
6769 res->data.custom_data.custom_name =
6770 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6772 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6783 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6784 ReflectionMethodBuilder *rmb,
6785 MonoMethodSignature *sig)
6788 MonoMethodNormal *pm;
6789 MonoMarshalSpec **specs;
6790 MonoReflectionMethodAux *method_aux;
6793 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6794 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6795 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6798 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6800 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6802 pm = (MonoMethodNormal*)m;
6805 m->flags = rmb->attrs;
6806 m->iflags = rmb->iattrs;
6807 m->name = mono_string_to_utf8 (rmb->name);
6811 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6813 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6814 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6817 m->signature->pinvoke = 1;
6818 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6820 m->signature->pinvoke = 1;
6822 } else if (!m->klass->dummy &&
6823 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6824 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6825 MonoMethodHeader *header;
6827 gint32 max_stack, i;
6828 gint32 num_locals = 0;
6829 gint32 num_clauses = 0;
6833 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6834 code_size = rmb->ilgen->code_len;
6835 max_stack = rmb->ilgen->max_stack;
6836 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6837 if (rmb->ilgen->ex_handlers)
6838 num_clauses = method_count_clauses (rmb->ilgen);
6841 code = mono_array_addr (rmb->code, guint8, 0);
6842 code_size = mono_array_length (rmb->code);
6843 /* we probably need to run a verifier on the code... */
6853 header = g_malloc0 (sizeof (MonoMethodHeader) +
6854 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6855 header->code_size = code_size;
6856 header->code = g_malloc (code_size);
6857 memcpy ((char*)header->code, code, code_size);
6858 header->max_stack = max_stack;
6859 header->init_locals = rmb->init_locals;
6860 header->num_locals = num_locals;
6862 for (i = 0; i < num_locals; ++i) {
6863 MonoReflectionLocalBuilder *lb =
6864 mono_array_get (rmb->ilgen->locals,
6865 MonoReflectionLocalBuilder*, i);
6867 header->locals [i] = g_new0 (MonoType, 1);
6868 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6871 header->num_clauses = num_clauses;
6873 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6878 if (rmb->generic_params) {
6879 int count = mono_array_length (rmb->generic_params);
6880 header->gen_params = g_new0 (MonoGenericParam, count);
6881 for (i = 0; i < count; i++) {
6882 MonoReflectionGenericParam *gp =
6883 mono_array_get (rmb->generic_params,
6884 MonoReflectionGenericParam*, i);
6886 header->gen_params [i] = *gp->type.type->data.generic_param;
6890 pm->header = header;
6894 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6897 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6899 for (i = 0; i < rmb->nrefs; ++i)
6900 mw->data = g_list_append (mw->data, rmb->refs [i]);
6905 /* Parameter names */
6908 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6909 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6910 for (i = 0; i <= m->signature->param_count; ++i) {
6911 MonoReflectionParamBuilder *pb;
6912 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6914 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6916 if (!method_aux->param_cattr)
6917 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6918 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6924 /* Parameter marshalling */
6927 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6928 MonoReflectionParamBuilder *pb;
6929 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6930 if (pb->marshal_info) {
6932 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6933 specs [pb->position] =
6934 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6938 if (specs != NULL) {
6940 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6941 method_aux->param_marshall = specs;
6944 if (klass->image->dynamic && method_aux)
6945 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6951 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6953 ReflectionMethodBuilder rmb;
6954 MonoMethodSignature *sig;
6956 sig = ctor_builder_to_signature (mb);
6958 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6960 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6961 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6963 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6964 /* ilgen is no longer needed */
6972 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6974 ReflectionMethodBuilder rmb;
6975 MonoMethodSignature *sig;
6977 sig = method_builder_to_signature (mb);
6979 reflection_methodbuilder_from_method_builder (&rmb, mb);
6981 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6982 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6984 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6985 /* ilgen is no longer needed */
6991 static MonoClassField*
6992 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6994 MonoClassField *field;
7001 field = g_new0 (MonoClassField, 1);
7003 field->name = mono_string_to_utf8 (fb->name);
7005 /* FIXME: handle type modifiers */
7006 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7007 field->type->attrs = fb->attrs;
7009 field->type = fb->type->type;
7011 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7012 field->data = mono_array_addr (fb->rva_data, char, 0);
7013 if (fb->offset != -1)
7014 field->offset = fb->offset;
7015 field->parent = klass;
7017 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7019 if (fb->def_value) {
7020 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7021 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7022 field->def_value = g_new0 (MonoConstant, 1);
7023 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7024 /* Copy the data from the blob since it might get realloc-ed */
7025 p = assembly->blob.data + idx;
7026 len = mono_metadata_decode_blob_size (p, &p2);
7028 field->def_value->value = g_malloc (len);
7029 memcpy (field->def_value->value, p, len);
7036 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7040 MonoReflectionTypeBuilder *tb = NULL;
7041 MonoGenericInst *ginst;
7046 klass = mono_class_from_mono_type (type->type);
7047 if (!klass->gen_params && !klass->generic_inst &&
7048 !(klass->nested_in && klass->nested_in->gen_params))
7051 mono_loader_lock ();
7053 domain = mono_object_domain (type);
7055 ginst = g_new0 (MonoGenericInst, 1);
7057 if (!klass->generic_inst) {
7058 ginst->type_argc = type_argc;
7059 ginst->type_argv = types;
7061 for (i = 0; i < ginst->type_argc; ++i) {
7062 if (!ginst->is_open)
7063 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7066 ginst->generic_type = &klass->byval_arg;
7068 MonoGenericInst *kginst = klass->generic_inst;
7070 ginst->type_argc = kginst->type_argc;
7071 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7073 for (i = 0; i < ginst->type_argc; i++) {
7074 MonoType *t = kginst->type_argv [i];
7076 if (t->type == MONO_TYPE_VAR)
7077 t = types [t->data.generic_param->num];
7079 if (!ginst->is_open)
7080 ginst->is_open = mono_class_is_open_constructed_type (t);
7082 ginst->type_argv [i] = t;
7085 ginst->generic_type = kginst->generic_type;
7088 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7091 mono_loader_unlock ();
7095 ginst->context = g_new0 (MonoGenericContext, 1);
7096 ginst->context->ginst = ginst;
7098 geninst = g_new0 (MonoType, 1);
7099 geninst->type = MONO_TYPE_GENERICINST;
7100 geninst->data.generic_inst = ginst;
7102 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7103 tb = (MonoReflectionTypeBuilder *) type;
7105 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7106 ginst->is_dynamic = TRUE;
7107 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7108 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7109 MonoReflectionType *rgt = rgi->generic_type;
7111 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7112 tb = (MonoReflectionTypeBuilder *) rgt;
7114 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7115 ginst->is_dynamic = TRUE;
7117 icount = klass->interface_count;
7119 ginst->ifaces = g_new0 (MonoType *, icount);
7120 ginst->count_ifaces = icount;
7122 for (i = 0; i < icount; i++) {
7123 MonoReflectionType *itype;
7126 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7128 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7129 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7130 if (!ginst->ifaces [i])
7131 ginst->ifaces [i] = itype->type;
7134 mono_class_create_generic (ginst);
7136 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7138 mono_loader_unlock ();
7144 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7146 MonoClass *klass, *pklass = NULL;
7147 MonoReflectionType *parent = NULL;
7149 MonoReflectionTypeBuilder *tb = NULL;
7150 MonoGenericInst *ginst;
7153 domain = mono_object_domain (type);
7154 klass = mono_class_from_mono_type (type->type);
7156 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7157 tb = (MonoReflectionTypeBuilder *) type;
7160 parent = tb->parent;
7161 pklass = mono_class_from_mono_type (parent->type);
7164 pklass = klass->parent;
7166 parent = mono_type_get_object (domain, &pklass->byval_arg);
7169 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7173 ginst = geninst->data.generic_inst;
7175 if (pklass && pklass->generic_inst)
7176 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7181 MonoReflectionMethod*
7182 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7184 MonoMethod *method, *inflated;
7185 MonoReflectionMethodBuilder *mb = NULL;
7186 MonoGenericMethod *gmethod;
7187 MonoGenericContext *context;
7190 MONO_ARCH_SAVE_REGS;
7191 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7192 MonoReflectionTypeBuilder *tb;
7195 mb = (MonoReflectionMethodBuilder *) rmethod;
7196 tb = (MonoReflectionTypeBuilder *) mb->type;
7197 klass = mono_class_from_mono_type (tb->type.type);
7199 method = methodbuilder_to_mono_method (klass, mb);
7201 method = rmethod->method;
7203 count = method->signature->generic_param_count;
7204 if (count != mono_array_length (types))
7207 gmethod = g_new0 (MonoGenericMethod, 1);
7208 gmethod->mtype_argc = count;
7209 gmethod->mtype_argv = g_new0 (MonoType *, count);
7210 for (i = 0; i < count; i++) {
7211 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7212 gmethod->mtype_argv [i] = garg->type;
7215 context = g_new0 (MonoGenericContext, 1);
7216 context->ginst = method->klass->generic_inst;
7217 context->gmethod = gmethod;
7219 inflated = mono_class_inflate_generic_method (method, context, NULL);
7221 return mono_method_get_object (
7222 mono_object_domain (rmethod), inflated, NULL);
7226 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7228 MonoGenericMethod *gmethod;
7229 MonoGenericInst *ginst;
7230 MonoGenericContext *context;
7233 ginst = type->type.type->data.generic_inst;
7235 gmethod = g_new0 (MonoGenericMethod, 1);
7236 gmethod->reflection_info = obj;
7238 gmethod->mtype_argc = method->signature->generic_param_count;
7239 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7241 for (i = 0; i < gmethod->mtype_argc; i++) {
7242 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7243 MonoGenericParam *gparam = &mn->header->gen_params [i];
7245 g_assert (gparam->pklass);
7246 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7249 context = g_new0 (MonoGenericContext, 1);
7250 context->ginst = ginst;
7251 context->gmethod = gmethod;
7253 return mono_class_inflate_generic_method (method, context, ginst->klass);
7257 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7262 klass = mono_class_from_mono_type (type->type.type);
7264 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7265 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7266 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7267 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7268 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7269 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7270 method = ((MonoReflectionMethod *) obj)->method;
7272 method = NULL; /* prevent compiler warning */
7273 g_assert_not_reached ();
7276 return inflate_mono_method (type, method, obj);
7280 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7281 MonoArray *methods, MonoArray *ctors,
7282 MonoArray *fields, MonoArray *properties,
7285 MonoGenericInst *ginst;
7286 MonoDynamicGenericInst *dginst;
7287 MonoClass *klass, *gklass, *pklass;
7290 MONO_ARCH_SAVE_REGS;
7292 klass = mono_class_from_mono_type (type->type.type);
7293 ginst = type->type.type->data.generic_inst;
7295 if (ginst->initialized)
7298 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7300 gklass = mono_class_from_mono_type (ginst->generic_type);
7301 mono_class_init (gklass);
7304 pklass = mono_class_from_mono_type (ginst->parent);
7306 pklass = gklass->parent;
7308 mono_class_setup_parent (klass, pklass);
7310 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7311 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7312 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7313 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7314 dginst->count_events = events ? mono_array_length (events) : 0;
7316 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7317 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7318 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7319 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7320 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7322 for (i = 0; i < dginst->count_methods; i++) {
7323 MonoObject *obj = mono_array_get (methods, gpointer, i);
7325 dginst->methods [i] = inflate_method (type, obj);
7328 for (i = 0; i < dginst->count_ctors; i++) {
7329 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7331 dginst->ctors [i] = inflate_method (type, obj);
7334 for (i = 0; i < dginst->count_fields; i++) {
7335 MonoObject *obj = mono_array_get (fields, gpointer, i);
7336 MonoClassField *field;
7338 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7339 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7340 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7341 field = ((MonoReflectionField *) obj)->field;
7343 field = NULL; /* prevent compiler warning */
7344 g_assert_not_reached ();
7347 dginst->fields [i] = *field;
7348 dginst->fields [i].generic_type = field->type;
7349 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7352 for (i = 0; i < dginst->count_properties; i++) {
7353 MonoObject *obj = mono_array_get (properties, gpointer, i);
7354 MonoProperty *property = &dginst->properties [i];
7356 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7357 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7359 property->parent = klass;
7360 property->attrs = pb->attrs;
7361 property->name = mono_string_to_utf8 (pb->name);
7363 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7365 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7366 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7367 *property = *((MonoReflectionProperty *) obj)->property;
7370 property->get = inflate_mono_method (type, property->get, NULL);
7372 property->set = inflate_mono_method (type, property->set, NULL);
7374 g_assert_not_reached ();
7377 for (i = 0; i < dginst->count_events; i++) {
7378 MonoObject *obj = mono_array_get (events, gpointer, i);
7379 MonoEvent *event = &dginst->events [i];
7381 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7382 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7384 event->parent = klass;
7385 event->attrs = eb->attrs;
7386 event->name = mono_string_to_utf8 (eb->name);
7388 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7389 if (eb->remove_method)
7390 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7391 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7392 *event = *((MonoReflectionEvent *) obj)->event;
7395 event->add = inflate_mono_method (type, event->add, NULL);
7397 event->remove = inflate_mono_method (type, event->remove, NULL);
7399 g_assert_not_reached ();
7402 ginst->initialized = TRUE;
7406 ensure_runtime_vtable (MonoClass *klass)
7408 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7409 int i, num, j, onum;
7410 MonoMethod **overrides;
7412 if (!tb || klass->wastypebuilder)
7415 ensure_runtime_vtable (klass->parent);
7417 num = tb->ctors? mono_array_length (tb->ctors): 0;
7418 num += tb->num_methods;
7419 klass->method.count = num;
7420 klass->methods = g_new (MonoMethod*, num);
7421 num = tb->ctors? mono_array_length (tb->ctors): 0;
7422 for (i = 0; i < num; ++i)
7423 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7424 num = tb->num_methods;
7426 for (i = 0; i < num; ++i)
7427 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7429 klass->wastypebuilder = TRUE;
7430 if (tb->interfaces) {
7431 klass->interface_count = mono_array_length (tb->interfaces);
7432 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7433 for (i = 0; i < klass->interface_count; ++i) {
7434 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7435 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7439 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7440 for (i = 0; i < klass->method.count; ++i)
7441 klass->methods [i]->slot = i;
7446 for (i = 0; i < tb->num_methods; ++i) {
7447 MonoReflectionMethodBuilder *mb =
7448 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7449 if (mb->override_method)
7454 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7458 for (i = 0; i < tb->num_methods; ++i) {
7459 MonoReflectionMethodBuilder *mb =
7460 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7461 if (mb->override_method) {
7462 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7463 overrides [onum * 2] =
7464 mb->override_method->method;
7465 overrides [onum * 2 + 1] =
7468 g_assert (mb->mhandle);
7475 mono_class_setup_vtable (klass, overrides, onum);
7479 typebuilder_setup_fields (MonoClass *klass)
7481 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7482 MonoReflectionFieldBuilder *fb;
7483 MonoClassField *field;
7488 klass->field.count = tb->num_fields;
7489 klass->field.first = 0;
7490 klass->field.last = klass->field.count;
7492 if (!klass->field.count)
7495 klass->fields = g_new0 (MonoClassField, klass->field.count);
7497 for (i = 0; i < klass->field.count; ++i) {
7498 fb = mono_array_get (tb->fields, gpointer, i);
7499 field = &klass->fields [i];
7500 field->name = mono_string_to_utf8 (fb->name);
7502 /* FIXME: handle type modifiers */
7503 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7504 field->type->attrs = fb->attrs;
7506 field->type = fb->type->type;
7508 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7509 field->data = mono_array_addr (fb->rva_data, char, 0);
7510 if (fb->offset != -1)
7511 field->offset = fb->offset;
7512 field->parent = klass;
7514 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7516 if (fb->def_value) {
7517 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7518 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7519 field->def_value = g_new0 (MonoConstant, 1);
7520 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7521 /* Copy the data from the blob since it might get realloc-ed */
7522 p = assembly->blob.data + idx;
7523 len = mono_metadata_decode_blob_size (p, &p2);
7525 field->def_value->value = g_malloc (len);
7526 memcpy (field->def_value->value, p, len);
7529 mono_class_layout_fields (klass);
7533 typebuilder_setup_properties (MonoClass *klass)
7535 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7536 MonoReflectionPropertyBuilder *pb;
7539 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7540 klass->property.first = 0;
7541 klass->property.last = klass->property.count;
7543 klass->properties = g_new0 (MonoProperty, klass->property.count);
7544 for (i = 0; i < klass->property.count; ++i) {
7545 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7546 klass->properties [i].parent = klass;
7547 klass->properties [i].attrs = pb->attrs;
7548 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7550 klass->properties [i].get = pb->get_method->mhandle;
7552 klass->properties [i].set = pb->set_method->mhandle;
7556 MonoReflectionEvent *
7557 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7559 MonoEvent *event = g_new0 (MonoEvent, 1);
7563 klass = my_mono_class_from_mono_type (tb->type.type);
7565 event->parent = klass;
7566 event->attrs = eb->attrs;
7567 event->name = mono_string_to_utf8 (eb->name);
7569 event->add = eb->add_method->mhandle;
7570 if (eb->remove_method)
7571 event->remove = eb->remove_method->mhandle;
7572 if (eb->raise_method)
7573 event->raise = eb->raise_method->mhandle;
7575 if (eb->other_methods) {
7576 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7577 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7578 MonoReflectionMethodBuilder *mb =
7579 mono_array_get (eb->other_methods,
7580 MonoReflectionMethodBuilder*, j);
7581 event->other [j] = mb->mhandle;
7585 return mono_event_get_object (mono_object_domain (tb), klass, event);
7589 typebuilder_setup_events (MonoClass *klass)
7591 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7592 MonoReflectionEventBuilder *eb;
7595 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7596 klass->event.first = 0;
7597 klass->event.last = klass->event.count;
7599 klass->events = g_new0 (MonoEvent, klass->event.count);
7600 for (i = 0; i < klass->event.count; ++i) {
7601 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7602 klass->events [i].parent = klass;
7603 klass->events [i].attrs = eb->attrs;
7604 klass->events [i].name = mono_string_to_utf8 (eb->name);
7606 klass->events [i].add = eb->add_method->mhandle;
7607 if (eb->remove_method)
7608 klass->events [i].remove = eb->remove_method->mhandle;
7609 if (eb->raise_method)
7610 klass->events [i].raise = eb->raise_method->mhandle;
7612 if (eb->other_methods) {
7613 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7614 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7615 MonoReflectionMethodBuilder *mb =
7616 mono_array_get (eb->other_methods,
7617 MonoReflectionMethodBuilder*, j);
7618 klass->events [i].other [j] = mb->mhandle;
7625 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7628 MonoReflectionType* res;
7630 MONO_ARCH_SAVE_REGS;
7632 klass = my_mono_class_from_mono_type (tb->type.type);
7634 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7637 * Fields to set in klass:
7638 * the various flags: delegate/unicode/contextbound etc.
7641 klass->flags = tb->attrs;
7643 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7644 /* No need to fully construct the type */
7645 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7647 /* enums are done right away */
7648 if (!klass->enumtype)
7649 ensure_runtime_vtable (klass);
7651 /* fields and object layout */
7652 if (klass->parent) {
7653 if (!klass->parent->size_inited)
7654 mono_class_init (klass->parent);
7655 klass->instance_size += klass->parent->instance_size;
7656 klass->class_size += klass->parent->class_size;
7657 klass->min_align = klass->parent->min_align;
7659 klass->instance_size = sizeof (MonoObject);
7660 klass->min_align = 1;
7663 /* FIXME: handle packing_size and instance_size */
7664 typebuilder_setup_fields (klass);
7666 typebuilder_setup_properties (klass);
7668 typebuilder_setup_events (klass);
7670 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7671 /* with enums res == tb: need to fix that. */
7672 if (!klass->enumtype)
7673 g_assert (res != (MonoReflectionType*)tb);
7678 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7680 MonoGenericParam *param;
7683 MONO_ARCH_SAVE_REGS;
7685 param = g_new0 (MonoGenericParam, 1);
7687 param->method = NULL;
7688 param->name = mono_string_to_utf8 (gparam->name);
7689 param->num = gparam->index;
7691 image = &gparam->tbuilder->module->dynamic_image->image;
7692 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7694 param->pklass->reflection_info = gparam;
7696 gparam->type.type = g_new0 (MonoType, 1);
7697 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7698 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7699 gparam->type.type->data.generic_param = param;
7703 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7705 MonoDynamicImage *assembly = sig->module->dynamic_image;
7706 guint32 na = mono_array_length (sig->arguments);
7711 MONO_ARCH_SAVE_REGS;
7713 p = buf = g_malloc (10 + na * 10);
7715 mono_metadata_encode_value (0x07, p, &p);
7716 mono_metadata_encode_value (na, p, &p);
7717 for (i = 0; i < na; ++i) {
7718 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7719 encode_reflection_type (assembly, type, p, &p);
7723 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7724 p = mono_array_addr (result, char, 0);
7725 memcpy (p, buf, buflen);
7732 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7734 MonoDynamicImage *assembly = sig->module->dynamic_image;
7735 guint32 na = mono_array_length (sig->arguments);
7740 MONO_ARCH_SAVE_REGS;
7742 p = buf = g_malloc (10 + na * 10);
7744 mono_metadata_encode_value (0x06, p, &p);
7745 for (i = 0; i < na; ++i) {
7746 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7747 encode_reflection_type (assembly, type, p, &p);
7751 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7752 p = mono_array_addr (result, char, 0);
7753 memcpy (p, buf, buflen);
7760 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7762 ReflectionMethodBuilder rmb;
7763 MonoMethodSignature *sig;
7766 sig = dynamic_method_to_signature (mb);
7768 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7771 * Resolve references.
7773 rmb.nrefs = mb->nrefs;
7774 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7775 for (i = 0; i < mb->nrefs; ++i) {
7776 gpointer ref = resolve_object (mb->module->image,
7777 mono_array_get (mb->refs, MonoObject*, i));
7780 mono_raise_exception (mono_get_exception_type_load (NULL));
7787 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7791 /* ilgen is no longer needed */
7796 * mono_reflection_lookup_dynamic_token:
7798 * Finish the Builder object pointed to by TOKEN and return the corresponding
7799 * runtime structure.
7802 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7804 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7807 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7810 return resolve_object (image, obj);
7814 resolve_object (MonoImage *image, MonoObject *obj)
7816 gpointer result = NULL;
7818 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7819 result = mono_string_intern ((MonoString*)obj);
7822 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7823 MonoReflectionType *tb = (MonoReflectionType*)obj;
7824 result = mono_class_from_mono_type (tb->type);
7827 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7828 result = ((MonoReflectionMethod*)obj)->method;
7831 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7832 result = ((MonoReflectionMethod*)obj)->method;
7835 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7836 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7837 result = mb->mhandle;
7839 /* Type is not yet created */
7840 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7842 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7845 * Hopefully this has been filled in by calling CreateType() on the
7849 * TODO: This won't work if the application finishes another
7850 * TypeBuilder instance instead of this one.
7852 result = mb->mhandle;
7855 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7856 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7858 result = cb->mhandle;
7860 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7862 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7863 result = cb->mhandle;
7866 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7867 result = ((MonoReflectionField*)obj)->field;
7870 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7871 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7872 result = fb->handle;
7875 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7877 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7878 result = fb->handle;
7881 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7885 klass = tb->type.type->data.klass;
7886 if (klass->wastypebuilder) {
7887 /* Already created */
7891 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7892 result = tb->type.type->data.klass;
7896 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7897 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7898 MonoMethodSignature *sig;
7901 if (helper->arguments)
7902 nargs = mono_array_length (helper->arguments);
7906 sig = mono_metadata_signature_alloc (image, nargs);
7907 sig->explicit_this = helper->call_conv & 64;
7908 sig->hasthis = helper->call_conv & 32;
7910 if (helper->call_conv == 0) /* unmanaged */
7911 sig->call_convention = helper->unmanaged_call_conv - 1;
7913 if (helper->call_conv & 0x02)
7914 sig->call_convention = MONO_CALL_VARARG;
7916 sig->call_convention = MONO_CALL_DEFAULT;
7918 sig->param_count = nargs;
7919 /* TODO: Copy type ? */
7920 sig->ret = helper->return_type->type;
7921 for (i = 0; i < nargs; ++i) {
7922 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7923 sig->params [i] = rt->type;
7929 g_print (obj->vtable->klass->name);
7930 g_assert_not_reached ();