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 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2032 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2033 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2034 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2035 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2036 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2037 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2038 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2040 if (strcmp ("", image->assembly->aname.culture)) {
2041 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2042 image->assembly->aname.culture);
2045 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2046 guchar pubtoken [9];
2048 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2049 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2052 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2053 * This is currently only a problem with references to System.Xml (see bug#27706),
2054 * but there may be other cases that makes this necessary. Note, we need to set
2055 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
2056 * recognized by ms, yuck!
2057 * FIXME: need to add more assembly names, as needed.
2059 if (strcmp (image->assembly_name, "mscorlib") == 0 ||
2060 strcmp (image->assembly_name, "System") == 0 ||
2061 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2062 strcmp (image->assembly_name, "System.Xml") == 0 ||
2063 strcmp (image->assembly_name, "System.Data") == 0 ||
2064 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2065 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2066 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2067 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2068 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2069 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2070 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2071 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2072 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2073 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2074 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2075 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2076 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2077 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2078 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2079 strcmp (image->assembly_name, "System.Design") == 0 ||
2080 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2081 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2082 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2083 strcmp (image->assembly_name, "System.Management") == 0 ||
2084 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2085 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2086 strcmp (image->assembly_name, "System.Security") == 0 ||
2087 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2088 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2089 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2090 strcmp (image->assembly_name, "System.Web") == 0) {
2091 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2092 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2093 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2094 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2096 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2099 token <<= RESOLTION_SCOPE_BITS;
2100 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2101 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2106 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2108 MonoDynamicTable *table;
2114 char *b = blob_size;
2116 switch (type->type) {
2117 case MONO_TYPE_FNPTR:
2119 case MONO_TYPE_SZARRAY:
2120 case MONO_TYPE_ARRAY:
2122 case MONO_TYPE_MVAR:
2123 case MONO_TYPE_GENERICINST:
2124 encode_type (assembly, type, p, &p);
2126 case MONO_TYPE_CLASS:
2127 case MONO_TYPE_VALUETYPE: {
2128 MonoClass *k = mono_class_from_mono_type (type);
2129 if (!k || !k->generic_inst)
2131 encode_generic_inst (assembly, k->generic_inst, p, &p);
2138 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2139 if (assembly->save) {
2140 g_assert (p-sig < 128);
2141 mono_metadata_encode_value (p-sig, b, &b);
2142 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2143 alloc_table (table, table->rows + 1);
2144 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2145 values [MONO_TYPESPEC_SIGNATURE] = token;
2148 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2149 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2155 * Despite the name, we handle also TypeSpec (with the above helper).
2158 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2160 MonoDynamicTable *table;
2162 guint32 token, scope, enclosing;
2165 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2168 token = create_typespec (assembly, type);
2171 klass = my_mono_class_from_mono_type (type);
2173 klass = mono_class_from_mono_type (type);
2176 * If it's in the same module and not a generic type parameter:
2178 if ((klass->image == &assembly->image) &&
2179 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2180 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2181 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2182 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2186 if (klass->nested_in) {
2187 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2188 /* get the typeref idx of the enclosing type */
2189 enclosing >>= TYPEDEFORREF_BITS;
2190 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2192 scope = resolution_scope_from_image (assembly, klass->image);
2194 table = &assembly->tables [MONO_TABLE_TYPEREF];
2195 if (assembly->save) {
2196 alloc_table (table, table->rows + 1);
2197 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2198 values [MONO_TYPEREF_SCOPE] = scope;
2199 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2200 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2202 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2203 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2205 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2210 * Insert a memberef row into the metadata: the token that point to the memberref
2211 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2212 * mono_image_get_fieldref_token()).
2213 * The sig param is an index to an already built signature.
2216 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2218 MonoDynamicTable *table;
2220 guint32 token, pclass;
2223 parent = mono_image_typedef_or_ref (assembly, type);
2224 switch (parent & TYPEDEFORREF_MASK) {
2225 case TYPEDEFORREF_TYPEREF:
2226 pclass = MEMBERREF_PARENT_TYPEREF;
2228 case TYPEDEFORREF_TYPESPEC:
2229 pclass = MEMBERREF_PARENT_TYPESPEC;
2231 case TYPEDEFORREF_TYPEDEF:
2232 pclass = MEMBERREF_PARENT_TYPEDEF;
2235 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2238 /* extract the index */
2239 parent >>= TYPEDEFORREF_BITS;
2241 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2243 if (assembly->save) {
2244 alloc_table (table, table->rows + 1);
2245 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2246 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2247 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2248 values [MONO_MEMBERREF_SIGNATURE] = sig;
2251 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2258 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2262 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2265 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2266 method->name, method_encode_signature (assembly, method->signature));
2267 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2272 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2275 ReflectionMethodBuilder rmb;
2277 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2281 reflection_methodbuilder_from_method_builder (&rmb, mb);
2283 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2284 mono_string_to_utf8 (rmb.name),
2285 method_builder_encode_signature (assembly, &rmb));
2286 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2291 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2294 ReflectionMethodBuilder rmb;
2296 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2300 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2302 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2303 mono_string_to_utf8 (rmb.name),
2304 method_builder_encode_signature (assembly, &rmb));
2305 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2310 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2315 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2318 g_assert (f->field->parent);
2319 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2320 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2321 f->field->name, fieldref_encode_signature (assembly, type));
2322 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2327 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2332 guint32 nparams = gmethod->mtype_argc;
2333 guint32 size = 10 + nparams * 10;
2336 char *b = blob_size;
2338 if (!assembly->save)
2341 p = buf = g_malloc (size);
2343 * FIXME: vararg, explicit_this, differenc call_conv values...
2345 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2346 mono_metadata_encode_value (nparams, p, &p);
2348 for (i = 0; i < nparams; i++)
2349 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2352 g_assert (p - buf < size);
2353 mono_metadata_encode_value (p-buf, b, &b);
2354 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2360 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2362 MonoDynamicTable *table;
2364 guint32 token, mtoken = 0, sig;
2365 MonoMethodInflated *imethod;
2366 MonoMethod *declaring;
2368 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2370 g_assert (method->signature->is_inflated);
2371 imethod = (MonoMethodInflated *) method;
2372 declaring = imethod->declaring;
2374 sig = method_encode_signature (assembly, declaring->signature);
2375 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2376 declaring->name, sig);
2378 if (!declaring->signature->generic_param_count)
2381 switch (mono_metadata_token_table (mtoken)) {
2382 case MONO_TABLE_MEMBERREF:
2383 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2385 case MONO_TABLE_METHOD:
2386 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2389 g_assert_not_reached ();
2392 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2394 if (assembly->save) {
2395 alloc_table (table, table->rows + 1);
2396 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2397 values [MONO_METHODSPEC_METHOD] = mtoken;
2398 values [MONO_METHODSPEC_SIGNATURE] = sig;
2401 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2408 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2410 MonoMethodInflated *imethod;
2413 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2417 g_assert (m->signature->is_inflated);
2418 imethod = (MonoMethodInflated *) m;
2420 if (imethod->declaring->signature->generic_param_count)
2421 token = method_encode_methodspec (assembly, m);
2423 guint32 sig = method_encode_signature (
2424 assembly, imethod->declaring->signature);
2425 token = mono_image_get_memberref_token (
2426 assembly, &m->klass->byval_arg, m->name, sig);
2429 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2434 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2436 MonoDynamicTable *table;
2443 char *b = blob_size;
2447 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2448 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2449 * Because of this, we must not insert it into the `typeref' hash table.
2452 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2456 g_assert (tb->generic_params);
2457 klass = mono_class_from_mono_type (tb->type.type);
2459 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2460 encode_type (assembly, &klass->byval_arg, p, &p);
2462 count = mono_array_length (tb->generic_params);
2463 mono_metadata_encode_value (count, p, &p);
2464 for (i = 0; i < count; i++) {
2465 MonoReflectionGenericParam *gparam;
2467 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2469 encode_type (assembly, gparam->type.type, p, &p);
2472 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2473 if (assembly->save) {
2474 g_assert (p-sig < 128);
2475 mono_metadata_encode_value (p-sig, b, &b);
2476 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2477 alloc_table (table, table->rows + 1);
2478 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2479 values [MONO_TYPESPEC_SIGNATURE] = token;
2482 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2483 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2489 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2491 MonoDynamicTable *table;
2494 guint32 token, pclass, parent, sig;
2497 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2501 klass = mono_class_from_mono_type (fb->typeb->type);
2502 name = mono_string_to_utf8 (fb->name);
2504 sig = fieldref_encode_signature (assembly, fb->type->type);
2506 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2507 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2509 pclass = MEMBERREF_PARENT_TYPESPEC;
2510 parent >>= TYPEDEFORREF_BITS;
2512 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2514 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2517 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2518 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2519 values [MONO_MEMBERREF_SIGNATURE] = sig;
2522 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2524 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2529 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2537 char *b = blob_size;
2539 if (!assembly->save)
2543 g_assert (helper->type == 2);
2545 if (helper->arguments)
2546 nargs = mono_array_length (helper->arguments);
2550 size = 10 + (nargs * 10);
2552 p = buf = g_malloc (size);
2554 /* Encode calling convention */
2555 /* Change Any to Standard */
2556 if ((helper->call_conv & 0x03) == 0x03)
2557 helper->call_conv = 0x01;
2558 /* explicit_this implies has_this */
2559 if (helper->call_conv & 0x40)
2560 helper->call_conv &= 0x20;
2562 if (helper->call_conv == 0) /* Unmanaged */
2563 *p = helper->unmanaged_call_conv - 1;
2566 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2567 if (helper->call_conv & 0x02) /* varargs */
2572 mono_metadata_encode_value (nargs, p, &p);
2573 encode_reflection_type (assembly, helper->return_type, p, &p);
2574 for (i = 0; i < nargs; ++i) {
2575 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2576 encode_reflection_type (assembly, pt, p, &p);
2579 g_assert (p - buf < size);
2580 mono_metadata_encode_value (p-buf, b, &b);
2581 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2588 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2591 MonoDynamicTable *table;
2594 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2595 idx = table->next_idx ++;
2597 alloc_table (table, table->rows);
2598 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2600 values [MONO_STAND_ALONE_SIGNATURE] =
2601 mono_reflection_encode_sighelper (assembly, helper);
2607 reflection_cc_to_file (int call_conv) {
2608 switch (call_conv & 0x3) {
2610 case 1: return MONO_CALL_DEFAULT;
2611 case 2: return MONO_CALL_VARARG;
2613 g_assert_not_reached ();
2620 MonoMethodSignature *sig;
2626 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2631 MonoMethodSignature *sig;
2634 name = mono_string_to_utf8 (m->name);
2635 nparams = mono_array_length (m->parameters);
2636 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2638 sig->call_convention = reflection_cc_to_file (m->call_conv);
2639 sig->param_count = nparams;
2640 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2641 for (i = 0; i < nparams; ++i) {
2642 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2643 sig->params [i] = t->type;
2646 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2648 if (strcmp (name, am->name) == 0 &&
2649 mono_metadata_type_equal (am->parent, m->parent->type) &&
2650 mono_metadata_signature_equal (am->sig, sig)) {
2653 m->table_idx = am->token & 0xffffff;
2657 am = g_new0 (ArrayMethod, 1);
2660 am->parent = m->parent->type;
2661 am->token = mono_image_get_memberref_token (assembly, am->parent,
2662 name, method_encode_signature (assembly, sig));
2663 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2664 m->table_idx = am->token & 0xffffff;
2669 * Insert into the metadata tables all the info about the TypeBuilder tb.
2670 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2673 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2675 MonoDynamicTable *table;
2677 int i, is_object = 0, is_system = 0;
2680 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2681 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2682 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2683 n = mono_string_to_utf8 (tb->name);
2684 if (strcmp (n, "Object") == 0)
2686 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2688 n = mono_string_to_utf8 (tb->nspace);
2689 if (strcmp (n, "System") == 0)
2691 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2693 if (tb->parent && !(is_system && is_object) &&
2694 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2695 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2697 values [MONO_TYPEDEF_EXTENDS] = 0;
2698 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2699 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2702 * if we have explicitlayout or sequentiallayouts, output data in the
2703 * ClassLayout table.
2705 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2706 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2708 alloc_table (table, table->rows);
2709 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2710 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2711 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2712 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2715 /* handle interfaces */
2716 if (tb->interfaces) {
2717 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2719 table->rows += mono_array_length (tb->interfaces);
2720 alloc_table (table, table->rows);
2721 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2722 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2723 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2724 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2725 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2726 values += MONO_INTERFACEIMPL_SIZE;
2730 /* handle generic parameters */
2731 if (tb->generic_params) {
2732 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2733 table->rows += mono_array_length (tb->generic_params);
2734 alloc_table (table, table->rows);
2735 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2736 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2738 mono_image_get_generic_param_info (
2739 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2745 table = &assembly->tables [MONO_TABLE_FIELD];
2746 table->rows += tb->num_fields;
2747 alloc_table (table, table->rows);
2748 for (i = 0; i < tb->num_fields; ++i)
2749 mono_image_get_field_info (
2750 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2753 /* handle constructors */
2755 table = &assembly->tables [MONO_TABLE_METHOD];
2756 table->rows += mono_array_length (tb->ctors);
2757 alloc_table (table, table->rows);
2758 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2759 mono_image_get_ctor_info (domain,
2760 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2763 /* handle methods */
2765 table = &assembly->tables [MONO_TABLE_METHOD];
2766 table->rows += tb->num_methods;
2767 alloc_table (table, table->rows);
2768 for (i = 0; i < tb->num_methods; ++i)
2769 mono_image_get_method_info (
2770 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2773 /* Do the same with properties etc.. */
2774 if (tb->events && mono_array_length (tb->events)) {
2775 table = &assembly->tables [MONO_TABLE_EVENT];
2776 table->rows += mono_array_length (tb->events);
2777 alloc_table (table, table->rows);
2778 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2780 alloc_table (table, table->rows);
2781 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2782 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2783 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2784 for (i = 0; i < mono_array_length (tb->events); ++i)
2785 mono_image_get_event_info (
2786 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2788 if (tb->properties && mono_array_length (tb->properties)) {
2789 table = &assembly->tables [MONO_TABLE_PROPERTY];
2790 table->rows += mono_array_length (tb->properties);
2791 alloc_table (table, table->rows);
2792 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2794 alloc_table (table, table->rows);
2795 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2796 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2797 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2798 for (i = 0; i < mono_array_length (tb->properties); ++i)
2799 mono_image_get_property_info (
2800 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2803 mono_image_add_decl_security (assembly,
2804 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2808 MonoDynamicTable *ntable;
2810 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2811 ntable->rows += mono_array_length (tb->subtypes);
2812 alloc_table (ntable, ntable->rows);
2813 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2815 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2816 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2818 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2819 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2820 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2821 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2822 mono_string_to_utf8 (tb->name), tb->table_idx,
2823 ntable->next_idx, ntable->rows);*/
2824 values += MONO_NESTED_CLASS_SIZE;
2831 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2835 g_ptr_array_add (types, type);
2837 if (!type->subtypes)
2840 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2841 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2842 collect_types (types, subtype);
2847 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2848 MonoReflectionTypeBuilder **type2)
2850 if ((*type1)->table_idx < (*type2)->table_idx)
2853 if ((*type1)->table_idx > (*type2)->table_idx)
2860 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2865 for (i = 0; i < mono_array_length (pinfo); ++i) {
2866 MonoReflectionParamBuilder *pb;
2867 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2870 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2875 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2878 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2880 for (i = 0; i < tb->num_fields; ++i) {
2881 MonoReflectionFieldBuilder* fb;
2882 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2883 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2887 for (i = 0; i < mono_array_length (tb->events); ++i) {
2888 MonoReflectionEventBuilder* eb;
2889 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2890 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2893 if (tb->properties) {
2894 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2895 MonoReflectionPropertyBuilder* pb;
2896 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2897 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2901 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2902 MonoReflectionCtorBuilder* cb;
2903 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2904 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2905 params_add_cattrs (assembly, cb->pinfo);
2910 for (i = 0; i < tb->num_methods; ++i) {
2911 MonoReflectionMethodBuilder* mb;
2912 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2913 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2914 params_add_cattrs (assembly, mb->pinfo);
2919 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2920 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2925 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2928 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2930 /* no types in the module */
2934 for (i = 0; i < mb->num_types; ++i)
2935 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2939 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2940 MonoDynamicImage *assembly)
2942 MonoDynamicTable *table;
2946 char *b = blob_size;
2949 table = &assembly->tables [MONO_TABLE_FILE];
2951 alloc_table (table, table->rows);
2952 values = table->values + table->next_idx * MONO_FILE_SIZE;
2953 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2954 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2955 if (module->image->dynamic) {
2956 /* This depends on the fact that the main module is emitted last */
2957 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2958 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2962 path = g_strdup (module->image->name);
2964 mono_sha1_get_digest_from_file (path, hash);
2967 mono_metadata_encode_value (20, b, &b);
2968 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2969 mono_image_add_stream_data (&assembly->blob, hash, 20);
2974 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2976 MonoDynamicTable *table;
2980 table = &assembly->tables [MONO_TABLE_MODULE];
2981 mb->table_idx = table->next_idx ++;
2982 name = mono_string_to_utf8 (mb->module.name);
2983 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2985 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2988 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2989 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2990 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2994 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2995 guint32 module_index, guint32 parent_index,
2996 MonoDynamicImage *assembly)
2998 MonoDynamicTable *table;
3002 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3003 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3006 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3008 alloc_table (table, table->rows);
3009 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3011 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3012 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3013 if (klass->nested_in)
3014 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3016 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3017 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3018 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3020 res = table->next_idx;
3024 /* Emit nested types */
3025 if (klass->nested_classes) {
3028 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3029 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3036 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3037 guint32 module_index, guint32 parent_index,
3038 MonoDynamicImage *assembly)
3043 klass = mono_class_from_mono_type (tb->type.type);
3045 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3047 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3048 parent_index, assembly);
3052 * We need to do this ourselves since klass->nested_classes is not set up.
3055 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3056 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3061 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3062 guint32 module_index,
3063 MonoDynamicImage *assembly)
3065 MonoImage *image = module->image;
3069 t = &image->tables [MONO_TABLE_TYPEDEF];
3071 for (i = 0; i < t->rows; ++i) {
3072 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3074 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3075 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3079 #define align_pointer(base,p)\
3081 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3083 (p) += 4 - (__diff & 3);\
3087 compare_semantics (const void *a, const void *b)
3089 const guint32 *a_values = a;
3090 const guint32 *b_values = b;
3091 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3094 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3098 compare_custom_attrs (const void *a, const void *b)
3100 const guint32 *a_values = a;
3101 const guint32 *b_values = b;
3103 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3107 compare_field_marshal (const void *a, const void *b)
3109 const guint32 *a_values = a;
3110 const guint32 *b_values = b;
3112 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3116 compare_nested (const void *a, const void *b)
3118 const guint32 *a_values = a;
3119 const guint32 *b_values = b;
3121 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3125 * build_compressed_metadata() fills in the blob of data that represents the
3126 * raw metadata as it will be saved in the PE file. The five streams are output
3127 * and the metadata tables are comnpressed from the guint32 array representation,
3128 * to the compressed on-disk format.
3131 build_compressed_metadata (MonoDynamicImage *assembly)
3133 MonoDynamicTable *table;
3135 guint64 valid_mask = 0;
3136 guint64 sorted_mask;
3137 guint32 heapt_size = 0;
3138 guint32 meta_size = 256; /* allow for header and other stuff */
3139 guint32 table_offset;
3140 guint32 ntables = 0;
3149 MonoDynamicStream *stream;
3152 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3153 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3154 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3155 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3156 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3158 /* tables that are sorted */
3159 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3160 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3161 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3162 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3163 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3164 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3166 /* Compute table sizes */
3167 /* the MonoImage has already been created in mono_image_basic_init() */
3168 meta = &assembly->image;
3170 /* Setup the info used by compute_sizes () */
3171 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3172 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3173 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3175 meta_size += assembly->blob.index;
3176 meta_size += assembly->guid.index;
3177 meta_size += assembly->sheap.index;
3178 meta_size += assembly->us.index;
3180 for (i=0; i < 64; ++i)
3181 meta->tables [i].rows = assembly->tables [i].rows;
3183 for (i = 0; i < 64; i++){
3184 if (meta->tables [i].rows == 0)
3186 valid_mask |= (guint64)1 << i;
3188 meta->tables [i].row_size = mono_metadata_compute_size (
3189 meta, i, &meta->tables [i].size_bitfield);
3190 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3192 heapt_size += 24; /* #~ header size */
3193 heapt_size += ntables * 4;
3194 meta_size += heapt_size;
3195 meta->raw_metadata = g_malloc0 (meta_size);
3196 p = meta->raw_metadata;
3197 /* the metadata signature */
3198 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3199 /* version numbers and 4 bytes reserved */
3200 int16val = (guint16*)p;
3201 *int16val++ = GUINT16_TO_LE (1);
3202 *int16val = GUINT16_TO_LE (1);
3204 /* version string */
3205 int32val = (guint32*)p;
3206 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3208 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3209 p += GUINT32_FROM_LE (*int32val);
3210 align_pointer (meta->raw_metadata, p);
3211 int16val = (guint16*)p;
3212 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3213 *int16val = GUINT16_TO_LE (5); /* number of streams */
3217 * write the stream info.
3219 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3220 table_offset += 3; table_offset &= ~3;
3222 assembly->tstream.index = heapt_size;
3223 for (i = 0; i < 5; ++i) {
3224 int32val = (guint32*)p;
3225 stream_desc [i].stream->offset = table_offset;
3226 *int32val++ = GUINT32_TO_LE (table_offset);
3227 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3228 table_offset += GUINT32_FROM_LE (*int32val);
3229 table_offset += 3; table_offset &= ~3;
3231 strcpy (p, stream_desc [i].name);
3232 p += strlen (stream_desc [i].name) + 1;
3233 align_pointer (meta->raw_metadata, p);
3236 * now copy the data, the table stream header and contents goes first.
3238 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3239 p = meta->raw_metadata + assembly->tstream.offset;
3240 int32val = (guint32*)p;
3241 *int32val = GUINT32_TO_LE (0); /* reserved */
3244 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3245 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3246 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3247 *p++ = 1; /* version */
3250 *p++ = 1; /* version */
3254 if (meta->idx_string_wide)
3256 if (meta->idx_guid_wide)
3258 if (meta->idx_blob_wide)
3261 *p++ = 0; /* reserved */
3262 int64val = (guint64*)p;
3263 *int64val++ = GUINT64_TO_LE (valid_mask);
3264 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3266 int32val = (guint32*)p;
3267 for (i = 0; i < 64; i++){
3268 if (meta->tables [i].rows == 0)
3270 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3272 p = (unsigned char*)int32val;
3274 /* sort the tables that still need sorting */
3275 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3277 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3278 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3280 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3281 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3283 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3284 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3286 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3288 /* compress the tables */
3289 for (i = 0; i < 64; i++){
3292 guint32 bitfield = meta->tables [i].size_bitfield;
3293 if (!meta->tables [i].rows)
3295 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3296 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3297 meta->tables [i].base = p;
3298 for (row = 1; row <= meta->tables [i].rows; ++row) {
3299 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3300 for (col = 0; col < assembly->tables [i].columns; ++col) {
3301 switch (mono_metadata_table_size (bitfield, col)) {
3303 *p++ = values [col];
3306 *p++ = values [col] & 0xff;
3307 *p++ = (values [col] >> 8) & 0xff;
3310 *p++ = values [col] & 0xff;
3311 *p++ = (values [col] >> 8) & 0xff;
3312 *p++ = (values [col] >> 16) & 0xff;
3313 *p++ = (values [col] >> 24) & 0xff;
3316 g_assert_not_reached ();
3320 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3323 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3324 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3325 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3326 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3327 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3329 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3333 * Some tables in metadata need to be sorted according to some criteria, but
3334 * when methods and fields are first created with reflection, they may be assigned a token
3335 * that doesn't correspond to the final token they will get assigned after the sorting.
3336 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3337 * with the reflection objects that represent them. Once all the tables are set up, the
3338 * reflection objects will contains the correct table index. fixup_method() will fixup the
3339 * tokens for the method with ILGenerator @ilgen.
3342 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3343 guint32 code_idx = GPOINTER_TO_UINT (value);
3344 MonoReflectionILTokenInfo *iltoken;
3345 MonoReflectionFieldBuilder *field;
3346 MonoReflectionCtorBuilder *ctor;
3347 MonoReflectionMethodBuilder *method;
3348 MonoReflectionTypeBuilder *tb;
3349 MonoReflectionArrayMethod *am;
3351 unsigned char *target;
3353 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3354 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3355 target = assembly->code.data + code_idx + iltoken->code_pos;
3356 switch (target [3]) {
3357 case MONO_TABLE_FIELD:
3358 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3359 field = (MonoReflectionFieldBuilder *)iltoken->member;
3360 idx = field->table_idx;
3361 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3362 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3363 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3365 g_assert_not_reached ();
3368 case MONO_TABLE_METHOD:
3369 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3370 method = (MonoReflectionMethodBuilder *)iltoken->member;
3371 idx = method->table_idx;
3372 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3373 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3374 idx = ctor->table_idx;
3375 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3376 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3377 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3378 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3380 g_assert_not_reached ();
3383 case MONO_TABLE_TYPEDEF:
3384 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3385 g_assert_not_reached ();
3386 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3387 idx = tb->table_idx;
3389 case MONO_TABLE_MEMBERREF:
3390 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3391 am = (MonoReflectionArrayMethod*)iltoken->member;
3392 idx = am->table_idx;
3393 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3394 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3395 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3396 g_assert (m->klass->generic_inst);
3398 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3400 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3401 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3402 g_assert (f->generic_type);
3405 g_assert_not_reached ();
3408 case MONO_TABLE_METHODSPEC:
3409 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3410 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3411 g_assert (m->signature->generic_param_count);
3414 g_assert_not_reached ();
3418 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3420 target [0] = idx & 0xff;
3421 target [1] = (idx >> 8) & 0xff;
3422 target [2] = (idx >> 16) & 0xff;
3429 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3430 * value is not known when the table is emitted.
3433 fixup_cattrs (MonoDynamicImage *assembly)
3435 MonoDynamicTable *table;
3437 guint32 type, i, idx, token;
3440 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3442 for (i = 0; i < table->rows; ++i) {
3443 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3445 type = values [MONO_CUSTOM_ATTR_TYPE];
3446 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3447 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3448 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3449 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3452 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3453 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3454 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3455 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3462 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3464 MonoDynamicTable *table;
3468 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3470 alloc_table (table, table->rows);
3471 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3472 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3473 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3474 name = mono_string_to_utf8 (rsrc->name);
3475 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3477 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3482 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3484 MonoDynamicTable *table;
3488 char *b = blob_size;
3490 guint32 idx, offset;
3492 if (rsrc->filename) {
3493 name = mono_string_to_utf8 (rsrc->filename);
3494 sname = g_path_get_basename (name);
3496 table = &assembly->tables [MONO_TABLE_FILE];
3498 alloc_table (table, table->rows);
3499 values = table->values + table->next_idx * MONO_FILE_SIZE;
3500 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3501 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3504 mono_sha1_get_digest_from_file (name, hash);
3505 mono_metadata_encode_value (20, b, &b);
3506 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3507 mono_image_add_stream_data (&assembly->blob, hash, 20);
3509 idx = table->next_idx++;
3511 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3514 offset = mono_array_length (rsrc->data);
3515 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3516 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3517 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3518 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3522 * The entry should be emitted into the MANIFESTRESOURCE table of
3523 * the main module, but that needs to reference the FILE table
3524 * which isn't emitted yet.
3531 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3535 set_version_from_string (MonoString *version, guint32 *values)
3537 gchar *ver, *p, *str;
3540 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3541 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3542 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3543 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3546 ver = str = mono_string_to_utf8 (version);
3547 for (i = 0; i < 4; ++i) {
3548 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3554 /* handle Revision and Build */
3564 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3568 char *b = blob_size;
3573 len = mono_array_length (pkey);
3574 mono_metadata_encode_value (len, b, &b);
3575 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3576 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3578 /* need to get the actual value from the key type... */
3579 assembly->strong_name_size = 128;
3580 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3586 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3588 MonoDynamicTable *table;
3589 MonoDynamicImage *assembly;
3590 MonoReflectionAssemblyBuilder *assemblyb;
3595 guint32 module_index;
3597 assemblyb = moduleb->assemblyb;
3598 assembly = moduleb->dynamic_image;
3599 domain = mono_object_domain (assemblyb);
3601 /* Emit ASSEMBLY table */
3602 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3603 alloc_table (table, 1);
3604 values = table->values + MONO_ASSEMBLY_SIZE;
3605 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3606 name = mono_string_to_utf8 (assemblyb->name);
3607 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3609 if (assemblyb->culture) {
3610 name = mono_string_to_utf8 (assemblyb->culture);
3611 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3614 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3616 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3617 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3618 set_version_from_string (assemblyb->version, values);
3620 /* Emit FILE + EXPORTED_TYPE table */
3622 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3624 MonoReflectionModuleBuilder *file_module =
3625 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3626 if (file_module != moduleb) {
3627 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3629 if (file_module->types) {
3630 for (j = 0; j < file_module->num_types; ++j) {
3631 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3632 mono_image_fill_export_table (domain, tb, module_index, 0,
3638 if (assemblyb->loaded_modules) {
3639 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3640 MonoReflectionModule *file_module =
3641 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3642 mono_image_fill_file_table (domain, file_module, assembly);
3644 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3648 /* Emit MANIFESTRESOURCE table */
3650 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3652 MonoReflectionModuleBuilder *file_module =
3653 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3654 /* The table for the main module is emitted later */
3655 if (file_module != moduleb) {
3657 if (file_module->resources) {
3658 int len = mono_array_length (file_module->resources);
3659 for (j = 0; j < len; ++j) {
3660 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3661 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3669 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3670 * for the modulebuilder @moduleb.
3671 * At the end of the process, method and field tokens are fixed up and the
3672 * on-disk compressed metadata representation is created.
3675 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3677 MonoDynamicTable *table;
3678 MonoDynamicImage *assembly;
3679 MonoReflectionAssemblyBuilder *assemblyb;
3684 assemblyb = moduleb->assemblyb;
3685 assembly = moduleb->dynamic_image;
3686 domain = mono_object_domain (assemblyb);
3688 if (assembly->text_rva)
3691 assembly->text_rva = START_TEXT_RVA;
3693 if (moduleb->is_main) {
3694 mono_image_emit_manifest (moduleb);
3697 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3698 table->rows = 1; /* .<Module> */
3700 alloc_table (table, table->rows);
3702 * Set the first entry.
3704 values = table->values + table->columns;
3705 values [MONO_TYPEDEF_FLAGS] = 0;
3706 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3707 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3708 values [MONO_TYPEDEF_EXTENDS] = 0;
3709 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3710 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3713 * handle global methods
3714 * FIXME: test what to do when global methods are defined in multiple modules.
3716 if (moduleb->global_methods) {
3717 table = &assembly->tables [MONO_TABLE_METHOD];
3718 table->rows += mono_array_length (moduleb->global_methods);
3719 alloc_table (table, table->rows);
3720 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3721 mono_image_get_method_info (
3722 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3724 if (moduleb->global_fields) {
3725 table = &assembly->tables [MONO_TABLE_FIELD];
3726 table->rows += mono_array_length (moduleb->global_fields);
3727 alloc_table (table, table->rows);
3728 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3729 mono_image_get_field_info (
3730 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3733 table = &assembly->tables [MONO_TABLE_MODULE];
3734 alloc_table (table, 1);
3735 mono_image_fill_module_table (domain, moduleb, assembly);
3739 /* Collect all types into a list sorted by their table_idx */
3740 GPtrArray *types = g_ptr_array_new ();
3743 for (i = 0; i < moduleb->num_types; ++i) {
3744 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3745 collect_types (types, type);
3748 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3749 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3750 table->rows += types->len;
3751 alloc_table (table, table->rows);
3753 for (i = 0; i < types->len; ++i) {
3754 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3755 mono_image_get_type_info (domain, type, assembly);
3757 g_ptr_array_free (types, TRUE);
3761 * table->rows is already set above and in mono_image_fill_module_table.
3763 /* add all the custom attributes at the end, once all the indexes are stable */
3764 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3766 module_add_cattrs (assembly, moduleb);
3769 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3770 fixup_cattrs (assembly);
3774 * mono_image_insert_string:
3775 * @module: module builder object
3778 * Insert @str into the user string stream of @module.
3781 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3783 MonoDynamicImage *assembly;
3788 MONO_ARCH_SAVE_REGS;
3790 if (!module->dynamic_image)
3791 mono_image_module_basic_init (module);
3793 assembly = module->dynamic_image;
3795 if (assembly->save) {
3796 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3797 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3798 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3800 char *swapped = g_malloc (2 * mono_string_length (str));
3801 const char *p = (const char*)mono_string_chars (str);
3803 swap_with_size (swapped, p, 2, mono_string_length (str));
3804 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3808 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3810 mono_image_add_stream_data (&assembly->us, "", 1);
3813 idx = assembly->us.index ++;
3815 mono_g_hash_table_insert (assembly->tokens,
3816 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3818 return MONO_TOKEN_STRING | idx;
3822 * mono_image_create_token:
3823 * @assembly: a dynamic assembly
3826 * Get a token to insert in the IL code stream for the given MemberInfo.
3827 * @obj can be one of:
3828 * ConstructorBuilder
3838 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3843 klass = obj->vtable->klass;
3844 if (strcmp (klass->name, "MethodBuilder") == 0) {
3845 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3847 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3848 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3850 token = mono_image_get_methodbuilder_token (assembly, mb);
3851 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3853 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3854 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3856 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3857 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3859 token = mono_image_get_ctorbuilder_token (assembly, mb);
3860 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3862 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3863 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3864 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3865 if (tb->generic_params) {
3866 token = mono_image_get_generic_field_token (assembly, fb);
3868 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3871 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3872 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3873 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3875 else if (strcmp (klass->name, "MonoType") == 0 ||
3876 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3877 MonoReflectionType *tb = (MonoReflectionType *)obj;
3878 token = mono_metadata_token_from_dor (
3879 mono_image_typedef_or_ref (assembly, tb->type));
3881 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3882 MonoReflectionType *tb = (MonoReflectionType *)obj;
3883 token = mono_metadata_token_from_dor (
3884 mono_image_typedef_or_ref (assembly, tb->type));
3886 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3887 strcmp (klass->name, "MonoMethod") == 0) {
3888 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3889 if (m->method->signature->is_inflated) {
3890 token = mono_image_get_methodspec_token (assembly, m->method);
3891 } else if (m->method->signature->generic_param_count) {
3892 g_assert_not_reached ();
3893 } else if ((m->method->klass->image == &assembly->image) &&
3894 !m->method->klass->generic_inst) {
3895 static guint32 method_table_idx = 0xffffff;
3897 * Each token should have a unique index, but the indexes are
3898 * assigned by managed code, so we don't know about them. An
3899 * easy solution is to count backwards...
3901 method_table_idx --;
3902 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3904 token = mono_image_get_methodref_token (assembly, m->method);
3905 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3907 else if (strcmp (klass->name, "MonoField") == 0) {
3908 MonoReflectionField *f = (MonoReflectionField *)obj;
3909 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3910 static guint32 field_table_idx = 0xffffff;
3912 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3914 token = mono_image_get_fieldref_token (assembly, f);
3915 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3917 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3918 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3919 token = mono_image_get_array_token (assembly, m);
3921 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3922 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3923 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3926 g_error ("requested token for %s\n", klass->name);
3928 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3935 guint32 import_lookup_table;
3939 guint32 import_address_table_rva;
3947 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3949 static MonoDynamicImage*
3950 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3951 char *assembly_name, char *module_name)
3953 static const guchar entrycode [16] = {0xff, 0x25, 0};
3954 MonoDynamicImage *image;
3958 * We need to use the current ms version or the ms runtime it won't find
3959 * the support dlls. D'oh!
3960 * const char *version = "mono-" VERSION;
3962 const char *version = "v1.0.3705";
3965 image = GC_MALLOC (sizeof (MonoDynamicImage));
3967 image = g_new0 (MonoDynamicImage, 1);
3970 /* keep in sync with image.c */
3971 image->image.name = assembly_name;
3972 image->image.assembly_name = image->image.name; /* they may be different */
3973 image->image.module_name = module_name;
3974 image->image.version = g_strdup (version);
3975 image->image.dynamic = TRUE;
3977 image->image.references = g_new0 (MonoAssembly*, 1);
3978 image->image.references [0] = NULL;
3980 mono_image_init (&image->image);
3982 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3983 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3984 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3985 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3986 image->handleref = g_hash_table_new (NULL, NULL);
3987 image->tokens = mono_g_hash_table_new (NULL, NULL);
3988 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3989 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3990 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3992 string_heap_init (&image->sheap);
3993 mono_image_add_stream_data (&image->us, "", 1);
3994 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3995 /* import tables... */
3996 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3997 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3998 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3999 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4000 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4001 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4002 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4003 stream_data_align (&image->code);
4005 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4007 for (i=0; i < 64; ++i) {
4008 image->tables [i].next_idx = 1;
4009 image->tables [i].columns = table_sizes [i];
4012 image->image.assembly = (MonoAssembly*)assembly;
4013 image->run = assembly->run;
4014 image->save = assembly->save;
4020 * mono_image_basic_init:
4021 * @assembly: an assembly builder object
4023 * Create the MonoImage that represents the assembly builder and setup some
4024 * of the helper hash table and the basic metadata streams.
4027 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4029 MonoDynamicAssembly *assembly;
4030 MonoDynamicImage *image;
4032 MONO_ARCH_SAVE_REGS;
4034 if (assemblyb->dynamic_assembly)
4038 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4040 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4043 assembly->assembly.dynamic = TRUE;
4044 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4045 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4046 if (assemblyb->culture)
4047 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4049 assembly->assembly.aname.culture = g_strdup ("");
4051 assembly->run = assemblyb->access != 2;
4052 assembly->save = assemblyb->access != 1;
4054 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4055 assembly->assembly.aname.name = image->image.name;
4056 assembly->assembly.image = &image->image;
4058 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4059 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4063 calc_section_size (MonoDynamicImage *assembly)
4067 /* alignment constraints */
4068 assembly->code.index += 3;
4069 assembly->code.index &= ~3;
4070 assembly->meta_size += 3;
4071 assembly->meta_size &= ~3;
4072 assembly->resources.index += 3;
4073 assembly->resources.index &= ~3;
4075 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4076 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4079 if (assembly->win32_res) {
4080 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4082 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4083 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4087 assembly->sections [MONO_SECTION_RELOC].size = 12;
4088 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4098 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4102 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4104 ResTreeNode *t1 = (ResTreeNode*)a;
4105 ResTreeNode *t2 = (ResTreeNode*)b;
4107 return t1->id - t2->id;
4111 * resource_tree_create:
4113 * Organize the resources into a resource tree.
4115 static ResTreeNode *
4116 resource_tree_create (MonoArray *win32_resources)
4118 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4122 tree = g_new0 (ResTreeNode, 1);
4124 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4125 MonoReflectionWin32Resource *win32_res =
4126 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4130 lang_node = g_new0 (ResTreeNode, 1);
4131 lang_node->id = win32_res->lang_id;
4132 lang_node->win32_res = win32_res;
4134 /* Create type node if neccesary */
4136 for (l = tree->children; l; l = l->next)
4137 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4138 type_node = (ResTreeNode*)l->data;
4143 type_node = g_new0 (ResTreeNode, 1);
4144 type_node->id = win32_res->res_type;
4147 * The resource types have to be sorted otherwise
4148 * Windows Explorer can't display the version information.
4150 tree->children = g_slist_insert_sorted (tree->children, type_node,
4151 resource_tree_compare_by_id);
4154 /* Create res node if neccesary */
4156 for (l = type_node->children; l; l = l->next)
4157 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4158 res_node = (ResTreeNode*)l->data;
4163 res_node = g_new0 (ResTreeNode, 1);
4164 res_node->id = win32_res->res_id;
4165 type_node->children = g_slist_append (type_node->children, res_node);
4168 res_node->children = g_slist_append (res_node->children, lang_node);
4175 * resource_tree_encode:
4177 * Encode the resource tree into the format used in the PE file.
4180 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4183 MonoPEResourceDir dir;
4184 MonoPEResourceDirEntry dir_entry;
4185 MonoPEResourceDataEntry data_entry;
4189 * For the format of the resource directory, see the article
4190 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4194 memset (&dir, 0, sizeof (dir));
4195 memset (&dir_entry, 0, sizeof (dir_entry));
4196 memset (&data_entry, 0, sizeof (data_entry));
4198 g_assert (sizeof (dir) == 16);
4199 g_assert (sizeof (dir_entry) == 8);
4200 g_assert (sizeof (data_entry) == 16);
4202 node->offset = p - begin;
4204 /* IMAGE_RESOURCE_DIRECTORY */
4205 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4207 memcpy (p, &dir, sizeof (dir));
4210 /* Reserve space for entries */
4212 p += sizeof (dir_entry) * dir.res_id_entries;
4214 /* Write children */
4215 for (l = node->children; l; l = l->next) {
4216 ResTreeNode *child = (ResTreeNode*)l->data;
4218 if (child->win32_res) {
4220 child->offset = p - begin;
4222 /* IMAGE_RESOURCE_DATA_ENTRY */
4223 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4224 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4226 memcpy (p, &data_entry, sizeof (data_entry));
4227 p += sizeof (data_entry);
4229 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4230 p += data_entry.rde_size;
4233 resource_tree_encode (child, begin, p, &p);
4236 /* IMAGE_RESOURCE_ENTRY */
4237 for (l = node->children; l; l = l->next) {
4238 ResTreeNode *child = (ResTreeNode*)l->data;
4239 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4241 dir_entry.is_dir = child->win32_res ? 0 : 1;
4242 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4244 memcpy (entries, &dir_entry, sizeof (dir_entry));
4245 entries += sizeof (dir_entry);
4252 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4257 MonoReflectionWin32Resource *win32_res;
4260 if (!assemblyb->win32_resources)
4264 * Resources are stored in a three level tree inside the PE file.
4265 * - level one contains a node for each type of resource
4266 * - level two contains a node for each resource
4267 * - level three contains a node for each instance of a resource for a
4268 * specific language.
4271 tree = resource_tree_create (assemblyb->win32_resources);
4273 /* Estimate the size of the encoded tree */
4275 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4276 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4277 size += mono_array_length (win32_res->res_data);
4279 /* Directory structure */
4280 size += mono_array_length (assemblyb->win32_resources) * 256;
4281 p = buf = g_malloc (size);
4283 resource_tree_encode (tree, p, p, &p);
4285 g_assert (p - buf < size);
4287 assembly->win32_res = g_malloc (p - buf);
4288 assembly->win32_res_size = p - buf;
4289 memcpy (assembly->win32_res, buf, p - buf);
4295 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4297 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4300 p += sizeof (MonoPEResourceDir);
4301 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4302 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4303 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4304 if (dir_entry->is_dir)
4305 fixup_resource_directory (res_section, child, rva);
4307 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4308 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4311 p += sizeof (MonoPEResourceDirEntry);
4316 * mono_image_create_pefile:
4317 * @mb: a module builder object
4319 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4320 * assembly->pefile where it can be easily retrieved later in chunks.
4323 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4324 MonoMSDOSHeader *msdos;
4325 MonoDotNetHeader *header;
4326 MonoSectionTable *section;
4327 MonoCLIHeader *cli_header;
4328 guint32 size, image_size, virtual_base, text_offset;
4329 guint32 header_start, section_start, file_offset, virtual_offset;
4330 MonoDynamicImage *assembly;
4331 MonoReflectionAssemblyBuilder *assemblyb;
4332 MonoDynamicStream *pefile;
4334 guint32 *rva, value;
4337 static const unsigned char msheader[] = {
4338 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4339 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4342 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4343 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4344 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4345 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4348 assemblyb = mb->assemblyb;
4350 mono_image_basic_init (assemblyb);
4351 assembly = mb->dynamic_image;
4353 /* already created */
4354 if (assembly->pefile.index)
4357 mono_image_build_metadata (mb);
4359 if (mb->is_main && assemblyb->resources) {
4360 int len = mono_array_length (assemblyb->resources);
4361 for (i = 0; i < len; ++i)
4362 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4365 if (mb->resources) {
4366 int len = mono_array_length (mb->resources);
4367 for (i = 0; i < len; ++i)
4368 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4371 build_compressed_metadata (assembly);
4374 assembly_add_win32_resources (assembly, assemblyb);
4376 nsections = calc_section_size (assembly);
4378 pefile = &assembly->pefile;
4380 /* The DOS header and stub */
4381 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4382 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4384 /* the dotnet header */
4385 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4387 /* the section tables */
4388 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4390 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4391 virtual_offset = VIRT_ALIGN;
4394 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4395 if (!assembly->sections [i].size)
4398 file_offset += FILE_ALIGN - 1;
4399 file_offset &= ~(FILE_ALIGN - 1);
4400 virtual_offset += VIRT_ALIGN - 1;
4401 virtual_offset &= ~(VIRT_ALIGN - 1);
4403 assembly->sections [i].offset = file_offset;
4404 assembly->sections [i].rva = virtual_offset;
4406 file_offset += assembly->sections [i].size;
4407 virtual_offset += assembly->sections [i].size;
4408 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4411 file_offset += FILE_ALIGN - 1;
4412 file_offset &= ~(FILE_ALIGN - 1);
4413 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4415 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4417 /* back-patch info */
4418 msdos = (MonoMSDOSHeader*)pefile->data;
4419 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4420 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4421 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4423 header = (MonoDotNetHeader*)(pefile->data + header_start);
4424 header->pesig [0] = 'P';
4425 header->pesig [1] = 'E';
4427 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4428 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4429 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4430 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4431 if (assemblyb->pekind == 1) {
4433 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4436 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4439 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4441 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4442 header->pe.pe_major = 6;
4443 header->pe.pe_minor = 0;
4444 size = assembly->sections [MONO_SECTION_TEXT].size;
4445 size += FILE_ALIGN - 1;
4446 size &= ~(FILE_ALIGN - 1);
4447 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4448 size = assembly->sections [MONO_SECTION_RSRC].size;
4449 size += FILE_ALIGN - 1;
4450 size &= ~(FILE_ALIGN - 1);
4451 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4452 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4453 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4454 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4455 /* pe_rva_entry_point always at the beginning of the text section */
4456 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4458 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4459 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4460 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4461 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4462 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4463 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4464 size = section_start;
4465 size += FILE_ALIGN - 1;
4466 size &= ~(FILE_ALIGN - 1);
4467 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4469 size += VIRT_ALIGN - 1;
4470 size &= ~(VIRT_ALIGN - 1);
4471 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4474 // Translate the PEFileKind value to the value expected by the Windows loader
4477 short kind = assemblyb->pekind;
4480 // PEFileKinds.ConsoleApplication == 2
4481 // PEFileKinds.WindowApplication == 3
4484 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4485 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4491 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4493 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4494 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4495 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4496 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4497 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4498 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4500 /* fill data directory entries */
4502 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4503 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4505 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4506 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4508 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4509 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4510 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4511 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4512 /* patch imported function RVA name */
4513 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4514 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4516 /* the import table */
4517 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4518 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4519 /* patch imported dll RVA name and other entries in the dir */
4520 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4521 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4522 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4523 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4524 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4525 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4527 p = (assembly->code.data + assembly->ilt_offset);
4528 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4529 *p++ = (value) & 0xff;
4530 *p++ = (value >> 8) & (0xff);
4531 *p++ = (value >> 16) & (0xff);
4532 *p++ = (value >> 24) & (0xff);
4534 /* the CLI header info */
4535 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4536 cli_header->ch_size = GUINT32_FROM_LE (72);
4537 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4538 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4539 if (assemblyb->entry_point) {
4540 guint32 table_idx = 0;
4541 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4542 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4543 table_idx = methodb->table_idx;
4546 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4547 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4550 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4551 /* The embedded managed resources */
4552 text_offset = assembly->text_rva + assembly->code.index;
4553 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4554 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4555 text_offset += assembly->resources.index;
4556 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4557 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4558 text_offset += assembly->meta_size;
4559 if (assembly->strong_name_size) {
4560 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4561 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4562 text_offset += assembly->strong_name_size;
4565 /* write the section tables and section content */
4566 section = (MonoSectionTable*)(pefile->data + section_start);
4567 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4568 static const char *section_names [] = {
4569 ".text", ".rsrc", ".reloc"
4571 if (!assembly->sections [i].size)
4573 strcpy (section->st_name, section_names [i]);
4574 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4575 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4576 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4577 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4578 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4579 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4580 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4582 case MONO_SECTION_TEXT:
4583 /* patch entry point */
4584 p = (assembly->code.data + 2);
4585 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4586 *p++ = (value) & 0xff;
4587 *p++ = (value >> 8) & 0xff;
4588 *p++ = (value >> 16) & 0xff;
4589 *p++ = (value >> 24) & 0xff;
4591 text_offset = assembly->sections [i].offset;
4592 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4593 text_offset += assembly->code.index;
4594 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4595 text_offset += assembly->resources.index;
4596 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4597 text_offset += assembly->meta_size;
4598 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4600 g_free (assembly->image.raw_metadata);
4602 case MONO_SECTION_RELOC:
4603 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4604 *rva = GUINT32_FROM_LE (assembly->text_rva);
4606 *rva = GUINT32_FROM_LE (12);
4608 data16 = (guint16*)rva;
4610 * the entrypoint is always at the start of the text section
4611 * 3 is IMAGE_REL_BASED_HIGHLOW
4612 * 2 is patch_size_rva - text_rva
4614 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4616 *data16 = 0; /* terminate */
4618 case MONO_SECTION_RSRC:
4619 if (assembly->win32_res) {
4620 text_offset = assembly->sections [i].offset;
4622 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4623 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4625 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4629 g_assert_not_reached ();
4634 /* check that the file is properly padded */
4637 FILE *f = fopen ("mypetest.exe", "w");
4638 fwrite (pefile->data, pefile->index, 1, f);
4644 MonoReflectionModule *
4645 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4649 MonoImageOpenStatus status;
4650 MonoDynamicAssembly *assembly;
4652 name = mono_string_to_utf8 (fileName);
4654 image = mono_image_open (name, &status);
4657 if (status == MONO_IMAGE_ERROR_ERRNO)
4658 exc = mono_get_exception_file_not_found (fileName);
4660 exc = mono_get_exception_bad_image_format (name);
4662 mono_raise_exception (exc);
4667 assembly = ab->dynamic_assembly;
4668 image->assembly = (MonoAssembly*)assembly;
4670 mono_assembly_load_references (image, &status);
4672 mono_image_close (image);
4673 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4676 return mono_module_get_object (mono_domain_get (), image);
4680 * We need to return always the same object for MethodInfo, FieldInfo etc..
4681 * but we need to consider the reflected type.
4682 * type uses a different hash, since it uses custom hash/equal functions.
4687 MonoClass *refclass;
4691 reflected_equal (gconstpointer a, gconstpointer b) {
4692 const ReflectedEntry *ea = a;
4693 const ReflectedEntry *eb = b;
4695 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4699 reflected_hash (gconstpointer a) {
4700 const ReflectedEntry *ea = a;
4701 return GPOINTER_TO_UINT (ea->item);
4704 #define CHECK_OBJECT(t,p,k) \
4710 mono_domain_lock (domain); \
4711 if (!domain->refobject_hash) \
4712 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4713 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4714 mono_domain_unlock (domain); \
4720 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4722 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4725 #define CACHE_OBJECT(p,o,k) \
4727 ReflectedEntry *e = ALLOC_REFENTRY; \
4729 e->refclass = (k); \
4730 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4731 mono_domain_unlock (domain); \
4735 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4737 /* this is done only once */
4738 mono_domain_lock (domain);
4739 CACHE_OBJECT (assembly, res, NULL);
4743 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4745 /* this is done only once */
4746 mono_domain_lock (domain);
4747 CACHE_OBJECT (module, res, NULL);
4751 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4753 MonoDynamicImage *image = moduleb->dynamic_image;
4754 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4757 * FIXME: we already created an image in mono_image_basic_init (), but
4758 * we don't know which module it belongs to, since that is only
4759 * determined at assembly save time.
4761 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4762 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4764 moduleb->module.image = &image->image;
4765 moduleb->dynamic_image = image;
4766 register_module (mono_object_domain (moduleb), moduleb, image);
4771 * mono_assembly_get_object:
4772 * @domain: an app domain
4773 * @assembly: an assembly
4775 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4777 MonoReflectionAssembly*
4778 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4780 static MonoClass *System_Reflection_Assembly;
4781 MonoReflectionAssembly *res;
4783 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4784 if (!System_Reflection_Assembly)
4785 System_Reflection_Assembly = mono_class_from_name (
4786 mono_defaults.corlib, "System.Reflection", "Assembly");
4787 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4788 res->assembly = assembly;
4789 CACHE_OBJECT (assembly, res, NULL);
4795 MonoReflectionModule*
4796 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4798 static MonoClass *System_Reflection_Module;
4799 MonoReflectionModule *res;
4801 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4802 if (!System_Reflection_Module)
4803 System_Reflection_Module = mono_class_from_name (
4804 mono_defaults.corlib, "System.Reflection", "Module");
4805 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4808 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4810 res->fqname = mono_string_new (domain, image->name);
4811 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4812 res->scopename = mono_string_new (domain, image->module_name);
4814 mono_image_addref (image);
4816 CACHE_OBJECT (image, res, NULL);
4820 MonoReflectionModule*
4821 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4823 static MonoClass *System_Reflection_Module;
4824 MonoReflectionModule *res;
4825 MonoTableInfo *table;
4826 guint32 cols [MONO_FILE_SIZE];
4828 guint32 i, name_idx;
4831 if (!System_Reflection_Module)
4832 System_Reflection_Module = mono_class_from_name (
4833 mono_defaults.corlib, "System.Reflection", "Module");
4834 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4836 table = &image->tables [MONO_TABLE_FILE];
4837 g_assert (table_index < table->rows);
4838 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4841 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4842 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4844 // Check whenever the row has a corresponding row in the moduleref table
4845 table = &image->tables [MONO_TABLE_MODULEREF];
4846 for (i = 0; i < table->rows; ++i) {
4847 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4848 val = mono_metadata_string_heap (image, name_idx);
4849 if (strcmp (val, name) == 0)
4850 res->image = image->modules [i];
4853 res->fqname = mono_string_new (domain, name);
4854 res->name = mono_string_new (domain, name);
4855 res->scopename = mono_string_new (domain, name);
4856 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4862 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4864 if ((t1->type != t2->type) ||
4865 (t1->byref != t2->byref))
4869 case MONO_TYPE_VOID:
4870 case MONO_TYPE_BOOLEAN:
4871 case MONO_TYPE_CHAR:
4882 case MONO_TYPE_STRING:
4885 case MONO_TYPE_OBJECT:
4886 case MONO_TYPE_TYPEDBYREF:
4888 case MONO_TYPE_VALUETYPE:
4889 case MONO_TYPE_CLASS:
4890 case MONO_TYPE_SZARRAY:
4891 return t1->data.klass == t2->data.klass;
4893 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4894 case MONO_TYPE_ARRAY:
4895 if (t1->data.array->rank != t2->data.array->rank)
4897 return t1->data.array->eklass == t2->data.array->eklass;
4898 case MONO_TYPE_GENERICINST: {
4900 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4902 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4904 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4905 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4911 case MONO_TYPE_MVAR:
4912 return t1->data.generic_param == t2->data.generic_param;
4914 g_error ("implement type compare for %0x!", t1->type);
4922 mymono_metadata_type_hash (MonoType *t1)
4928 hash |= t1->byref << 6; /* do not collide with t1->type values */
4930 case MONO_TYPE_VALUETYPE:
4931 case MONO_TYPE_CLASS:
4932 case MONO_TYPE_SZARRAY:
4933 /* check if the distribution is good enough */
4934 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4936 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4941 static MonoReflectionGenericInst*
4942 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4944 static MonoClass *System_Reflection_MonoGenericInst;
4945 MonoReflectionGenericInst *res;
4946 MonoGenericInst *ginst;
4949 if (!System_Reflection_MonoGenericInst) {
4950 System_Reflection_MonoGenericInst = mono_class_from_name (
4951 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4952 g_assert (System_Reflection_MonoGenericInst);
4955 ginst = geninst->data.generic_inst;
4956 gklass = mono_class_from_mono_type (ginst->generic_type);
4958 mono_class_init (ginst->klass);
4960 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4962 res->type.type = geninst;
4963 if (gklass->wastypebuilder && gklass->reflection_info)
4964 res->generic_type = gklass->reflection_info;
4966 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4972 * mono_type_get_object:
4973 * @domain: an app domain
4976 * Return an System.MonoType object representing the type @type.
4979 mono_type_get_object (MonoDomain *domain, MonoType *type)
4981 MonoReflectionType *res;
4982 MonoClass *klass = mono_class_from_mono_type (type);
4984 mono_domain_lock (domain);
4985 if (!domain->type_hash)
4986 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4987 (GCompareFunc)mymono_metadata_type_equal);
4988 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4989 mono_domain_unlock (domain);
4992 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4993 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4994 mono_g_hash_table_insert (domain->type_hash, type, res);
4995 mono_domain_unlock (domain);
4998 if (klass->reflection_info && !klass->wastypebuilder) {
4999 //g_assert_not_reached ();
5000 /* should this be considered an error condition? */
5002 mono_domain_unlock (domain);
5003 return klass->reflection_info;
5006 mono_class_init (klass);
5007 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5009 mono_g_hash_table_insert (domain->type_hash, type, res);
5010 mono_domain_unlock (domain);
5015 * mono_method_get_object:
5016 * @domain: an app domain
5018 * @refclass: the reflected type (can be NULL)
5020 * Return an System.Reflection.MonoMethod object representing the method @method.
5022 MonoReflectionMethod*
5023 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5026 * We use the same C representation for methods and constructors, but the type
5027 * name in C# is different.
5031 MonoReflectionMethod *ret;
5034 refclass = method->klass;
5036 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5037 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5038 cname = "MonoCMethod";
5040 cname = "MonoMethod";
5041 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5043 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5044 ret->method = method;
5045 ret->name = mono_string_new (domain, method->name);
5046 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5047 CACHE_OBJECT (method, ret, refclass);
5052 * mono_field_get_object:
5053 * @domain: an app domain
5057 * Return an System.Reflection.MonoField object representing the field @field
5060 MonoReflectionField*
5061 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5063 MonoReflectionField *res;
5066 CHECK_OBJECT (MonoReflectionField *, field, klass);
5067 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5068 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5071 res->name = mono_string_new (domain, field->name);
5072 res->attrs = field->type->attrs;
5073 res->type = mono_type_get_object (domain, field->type);
5074 CACHE_OBJECT (field, res, klass);
5079 * mono_property_get_object:
5080 * @domain: an app domain
5082 * @property: a property
5084 * Return an System.Reflection.MonoProperty object representing the property @property
5087 MonoReflectionProperty*
5088 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5090 MonoReflectionProperty *res;
5093 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5094 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5095 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5097 res->property = property;
5098 CACHE_OBJECT (property, res, klass);
5103 * mono_event_get_object:
5104 * @domain: an app domain
5108 * Return an System.Reflection.MonoEvent object representing the event @event
5111 MonoReflectionEvent*
5112 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5114 MonoReflectionEvent *res;
5117 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5118 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5119 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5122 CACHE_OBJECT (event, res, klass);
5127 * mono_param_get_objects:
5128 * @domain: an app domain
5131 * Return an System.Reflection.ParameterInfo array object representing the parameters
5132 * in the method @method.
5135 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5137 static MonoClass *System_Reflection_ParameterInfo;
5138 MonoArray *res = NULL;
5139 MonoReflectionMethod *member = NULL;
5140 MonoReflectionParameter *param = NULL;
5144 if (!System_Reflection_ParameterInfo)
5145 System_Reflection_ParameterInfo = mono_class_from_name (
5146 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5148 if (!method->signature->param_count)
5149 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5151 /* Note: the cache is based on the address of the signature into the method
5152 * since we already cache MethodInfos with the method as keys.
5154 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5156 member = mono_method_get_object (domain, method, NULL);
5157 names = g_new (char *, method->signature->param_count);
5158 mono_method_get_param_names (method, (const char **) names);
5160 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5161 for (i = 0; i < method->signature->param_count; ++i) {
5162 param = (MonoReflectionParameter *)mono_object_new (domain,
5163 System_Reflection_ParameterInfo);
5164 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5165 param->DefaultValueImpl = NULL; /* FIXME */
5166 param->MemberImpl = (MonoObject*)member;
5167 param->NameImpl = mono_string_new (domain, names [i]);
5168 param->PositionImpl = i;
5169 param->AttrsImpl = method->signature->params [i]->attrs;
5170 mono_array_set (res, gpointer, i, param);
5173 CACHE_OBJECT (&(method->signature), res, NULL);
5178 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5182 memset (assembly, 0, sizeof (MonoAssemblyName));
5184 assembly->culture = "";
5185 assembly->public_tok_value = NULL;
5187 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5190 while (*p == ' ' || *p == ',') {
5199 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5201 assembly->major = strtoul (p, &s, 10);
5202 if (s == p || *s != '.')
5205 assembly->minor = strtoul (p, &s, 10);
5206 if (s == p || *s != '.')
5209 assembly->build = strtoul (p, &s, 10);
5210 if (s == p || *s != '.')
5213 assembly->revision = strtoul (p, &s, 10);
5217 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5219 if (strncmp (p, "neutral", 7) == 0) {
5220 assembly->culture = "";
5223 assembly->culture = p;
5224 while (*p && *p != ',') {
5228 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5230 assembly->public_tok_value = p;
5231 while (*p && *p != ',') {
5235 while (*p && *p != ',')
5239 while (*p == ' ' || *p == ',') {
5253 * mono_reflection_parse_type:
5256 * Parse a type name as accepted by the GetType () method and output the info
5257 * extracted in the info structure.
5258 * the name param will be mangled, so, make a copy before passing it to this function.
5259 * The fields in info will be valid until the memory pointed to by name is valid.
5260 * Returns 0 on parse error.
5261 * See also mono_type_get_name () below.
5264 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5266 char *start, *p, *w, *last_point, *startn;
5267 int in_modifiers = 0;
5268 int isbyref = 0, rank;
5270 start = p = w = name;
5272 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5273 info->name = info->name_space = NULL;
5274 info->nested = NULL;
5275 info->modifiers = NULL;
5277 /* last_point separates the namespace from the name */
5283 *p = 0; /* NULL terminate the name */
5285 info->nested = g_list_append (info->nested, startn);
5286 /* we have parsed the nesting namespace + name */
5290 info->name_space = start;
5292 info->name = last_point + 1;
5294 info->name_space = (char *)"";
5320 info->name_space = start;
5322 info->name = last_point + 1;
5324 info->name_space = (char *)"";
5331 if (isbyref) /* only one level allowed by the spec */
5334 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5338 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5349 else if (*p != '*') /* '*' means unknown lower bound */
5355 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5367 return 0; /* missing assembly name */
5368 if (!assembly_name_to_aname (&info->assembly, p))
5375 if (info->assembly.name)
5378 *w = 0; /* terminate class name */
5379 if (!info->name || !*info->name)
5381 /* add other consistency checks */
5386 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5393 image = mono_defaults.corlib;
5396 klass = mono_class_from_name_case (image, info->name_space, info->name);
5398 klass = mono_class_from_name (image, info->name_space, info->name);
5401 for (mod = info->nested; mod; mod = mod->next) {
5404 mono_class_init (klass);
5405 nested = klass->nested_classes;
5408 klass = nested->data;
5410 if (g_strcasecmp (klass->name, mod->data) == 0)
5413 if (strcmp (klass->name, mod->data) == 0)
5417 nested = nested->next;
5424 mono_class_init (klass);
5425 for (mod = info->modifiers; mod; mod = mod->next) {
5426 modval = GPOINTER_TO_UINT (mod->data);
5427 if (!modval) { /* byref: must be last modifier */
5428 return &klass->this_arg;
5429 } else if (modval == -1) {
5430 klass = mono_ptr_class_get (&klass->byval_arg);
5431 } else { /* array rank */
5432 klass = mono_array_class_get (klass, modval);
5434 mono_class_init (klass);
5437 return &klass->byval_arg;
5441 * mono_reflection_get_type:
5442 * @image: a metadata context
5443 * @info: type description structure
5444 * @ignorecase: flag for case-insensitive string compares
5446 * Build a MonoType from the type description in @info.
5451 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5454 MonoReflectionAssembly *assembly;
5458 type = mono_reflection_get_type_internal (image, info, ignorecase);
5461 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5464 // Reconstruct the type name
5465 fullName = g_string_new ("");
5466 if (info->name_space && (info->name_space [0] != '\0'))
5467 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5469 g_string_printf (fullName, info->name);
5470 for (mod = info->nested; mod; mod = mod->next)
5471 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5474 mono_domain_try_type_resolve (
5475 mono_domain_get (), fullName->str, NULL);
5476 if (assembly && (!image || (assembly->assembly->image == image)))
5477 type = mono_reflection_get_type_internal (assembly->assembly->image,
5479 g_string_free (fullName, TRUE);
5484 * mono_reflection_type_from_name:
5486 * @image: a metadata context (can be NULL).
5488 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5489 * it defaults to get the type from @image or, if @image is NULL or loading
5490 * from it fails, uses corlib.
5494 mono_reflection_type_from_name (char *name, MonoImage *image)
5497 MonoTypeNameParse info;
5498 MonoAssembly *assembly;
5500 /*g_print ("requested type %s\n", str);*/
5501 if (!mono_reflection_parse_type (name, &info)) {
5502 g_list_free (info.modifiers);
5503 g_list_free (info.nested);
5507 if (info.assembly.name) {
5508 assembly = mono_assembly_loaded (&info.assembly);
5509 /* do we need to load if it's not already loaded? */
5511 g_list_free (info.modifiers);
5512 g_list_free (info.nested);
5516 image = assembly->image;
5517 } else if (image == NULL) {
5518 image = mono_defaults.corlib;
5521 type = mono_reflection_get_type (image, &info, FALSE);
5522 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5523 image = mono_defaults.corlib;
5524 type = mono_reflection_get_type (image, &info, FALSE);
5527 g_list_free (info.modifiers);
5528 g_list_free (info.nested);
5533 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5535 int slen, type = t->type;
5540 case MONO_TYPE_BOOLEAN: {
5541 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5546 case MONO_TYPE_CHAR:
5548 case MONO_TYPE_I2: {
5549 guint16 *val = g_malloc (sizeof (guint16));
5554 #if SIZEOF_VOID_P == 4
5560 case MONO_TYPE_I4: {
5561 guint32 *val = g_malloc (sizeof (guint32));
5566 #if SIZEOF_VOID_P == 8
5567 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5572 case MONO_TYPE_I8: {
5573 guint64 *val = g_malloc (sizeof (guint64));
5578 case MONO_TYPE_VALUETYPE:
5579 if (t->data.klass->enumtype) {
5580 type = t->data.klass->enum_basetype->type;
5583 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5586 case MONO_TYPE_STRING:
5587 if (*p == (char)0xFF) {
5591 slen = mono_metadata_decode_value (p, &p);
5593 return mono_string_new_len (mono_domain_get (), p, slen);
5594 case MONO_TYPE_CLASS: {
5597 if (*p == (char)0xFF) {
5602 slen = mono_metadata_decode_value (p, &p);
5603 n = g_memdup (p, slen + 1);
5605 t = mono_reflection_type_from_name (n, image);
5607 g_warning ("Cannot load type '%s'", n);
5611 return mono_type_get_object (mono_domain_get (), t);
5615 case MONO_TYPE_OBJECT: {
5618 MonoClass *subc = NULL;
5623 } else if (subt == 0x0E) {
5624 type = MONO_TYPE_STRING;
5626 } else if (subt == 0x55) {
5629 slen = mono_metadata_decode_value (p, &p);
5630 n = g_memdup (p, slen + 1);
5632 t = mono_reflection_type_from_name (n, image);
5634 g_warning ("Cannot load type '%s'", n);
5637 subc = mono_class_from_mono_type (t);
5638 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5639 MonoType simple_type = {{0}};
5640 simple_type.type = subt;
5641 subc = mono_class_from_mono_type (&simple_type);
5643 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5645 val = load_cattr_value (image, &subc->byval_arg, p, end);
5646 obj = mono_object_new (mono_domain_get (), subc);
5647 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5651 case MONO_TYPE_SZARRAY:
5654 guint32 i, alen, basetype;
5657 if (alen == 0xffffffff) {
5661 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5662 basetype = t->data.klass->byval_arg.type;
5667 case MONO_TYPE_BOOLEAN:
5668 for (i=0;i<alen;i++)
5670 MonoBoolean val=*p++;
5671 mono_array_set(arr,MonoBoolean,i,val);
5674 case MONO_TYPE_CHAR:
5677 for (i=0;i<alen;i++)
5679 guint16 val=read16(p);
5680 mono_array_set(arr,guint16,i,val);
5687 for (i=0;i<alen;i++)
5689 guint32 val=read32(p);
5690 mono_array_set(arr,guint32,i,val);
5697 for (i=0;i<alen;i++)
5699 guint64 val=read64(p);
5700 mono_array_set(arr,guint64,i,val);
5704 case MONO_TYPE_CLASS:
5705 case MONO_TYPE_STRING:
5706 for (i = 0; i < alen; i++) {
5707 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5708 mono_array_set (arr, gpointer, i, item);
5712 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5718 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5724 type_is_reference (MonoType *type)
5726 switch (type->type) {
5727 case MONO_TYPE_BOOLEAN:
5728 case MONO_TYPE_CHAR:
5741 case MONO_TYPE_VALUETYPE:
5749 free_param_data (MonoMethodSignature *sig, void **params) {
5751 for (i = 0; i < sig->param_count; ++i) {
5752 if (!type_is_reference (sig->params [i]))
5753 g_free (params [i]);
5758 * Find the method index in the metadata methodDef table.
5759 * Later put these three helper methods in metadata and export them.
5762 find_method_index (MonoMethod *method) {
5763 MonoClass *klass = method->klass;
5766 for (i = 0; i < klass->method.count; ++i) {
5767 if (method == klass->methods [i])
5768 return klass->method.first + 1 + i;
5774 * Find the field index in the metadata FieldDef table.
5777 find_field_index (MonoClass *klass, MonoClassField *field) {
5780 for (i = 0; i < klass->field.count; ++i) {
5781 if (field == &klass->fields [i])
5782 return klass->field.first + 1 + i;
5788 * Find the property index in the metadata Property table.
5791 find_property_index (MonoClass *klass, MonoProperty *property) {
5794 for (i = 0; i < klass->property.count; ++i) {
5795 if (property == &klass->properties [i])
5796 return klass->property.first + 1 + i;
5802 * Find the event index in the metadata Event table.
5805 find_event_index (MonoClass *klass, MonoEvent *event) {
5808 for (i = 0; i < klass->event.count; ++i) {
5809 if (event == &klass->events [i])
5810 return klass->event.first + 1 + i;
5816 create_custom_attr (MonoImage *image, MonoMethod *method,
5817 const char *data, guint32 len)
5819 const char *p = data;
5821 guint32 i, j, num_named;
5825 mono_class_init (method->klass);
5828 attr = mono_object_new (mono_domain_get (), method->klass);
5829 mono_runtime_invoke (method, attr, NULL, NULL);
5833 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5836 /*g_print ("got attr %s\n", method->klass->name);*/
5838 params = g_new (void*, method->signature->param_count);
5842 for (i = 0; i < method->signature->param_count; ++i) {
5843 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5847 attr = mono_object_new (mono_domain_get (), method->klass);
5848 mono_runtime_invoke (method, attr, params, NULL);
5849 free_param_data (method->signature, params);
5851 num_named = read16 (named);
5853 for (j = 0; j < num_named; j++) {
5855 char *name, named_type, data_type;
5856 named_type = *named++;
5857 data_type = *named++; /* type of data */
5858 if (data_type == 0x55) {
5861 type_len = mono_metadata_decode_blob_size (named, &named);
5862 type_name = g_malloc (type_len + 1);
5863 memcpy (type_name, named, type_len);
5864 type_name [type_len] = 0;
5866 /* FIXME: lookup the type and check type consistency */
5869 if (data_type == MONO_TYPE_SZARRAY)
5870 /* The spec does not mention this */
5872 name_len = mono_metadata_decode_blob_size (named, &named);
5873 name = g_malloc (name_len + 1);
5874 memcpy (name, named, name_len);
5875 name [name_len] = 0;
5877 if (named_type == 0x53) {
5878 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5879 void *val = load_cattr_value (image, field->type, named, &named);
5880 mono_field_set_value (attr, field, val);
5881 if (!type_is_reference (field->type))
5883 } else if (named_type == 0x54) {
5886 MonoType *prop_type;
5888 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5889 /* can we have more that 1 arg in a custom attr named property? */
5890 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5891 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5892 mono_property_set_value (prop, attr, pparams, NULL);
5893 if (!type_is_reference (prop_type))
5894 g_free (pparams [0]);
5903 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5910 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5911 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5912 for (i = 0; i < cinfo->num_attrs; ++i) {
5913 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5914 mono_array_set (result, gpointer, i, attr);
5920 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5922 guint32 mtoken, i, len;
5923 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5925 MonoCustomAttrInfo *ainfo;
5926 GList *tmp, *list = NULL;
5929 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5931 i = mono_metadata_custom_attrs_from_index (image, idx);
5935 while (i < ca->rows) {
5936 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5938 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5941 len = g_list_length (list);
5944 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5945 ainfo->num_attrs = len;
5946 ainfo->image = image;
5947 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5948 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5949 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5950 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5951 case CUSTOM_ATTR_TYPE_METHODDEF:
5952 mtoken |= MONO_TOKEN_METHOD_DEF;
5954 case CUSTOM_ATTR_TYPE_MEMBERREF:
5955 mtoken |= MONO_TOKEN_MEMBER_REF;
5958 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5961 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5962 if (!ainfo->attrs [i].ctor)
5963 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5964 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5965 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5966 ainfo->attrs [i].data = data;
5974 mono_custom_attrs_from_method (MonoMethod *method)
5976 MonoCustomAttrInfo *cinfo;
5979 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5981 idx = find_method_index (method);
5982 idx <<= CUSTOM_ATTR_BITS;
5983 idx |= CUSTOM_ATTR_METHODDEF;
5984 return mono_custom_attrs_from_index (method->klass->image, idx);
5988 mono_custom_attrs_from_class (MonoClass *klass)
5990 MonoCustomAttrInfo *cinfo;
5993 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5995 idx = mono_metadata_token_index (klass->type_token);
5996 idx <<= CUSTOM_ATTR_BITS;
5997 idx |= CUSTOM_ATTR_TYPEDEF;
5998 return mono_custom_attrs_from_index (klass->image, idx);
6002 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6004 MonoCustomAttrInfo *cinfo;
6007 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6009 idx = 1; /* there is only one assembly */
6010 idx <<= CUSTOM_ATTR_BITS;
6011 idx |= CUSTOM_ATTR_ASSEMBLY;
6012 return mono_custom_attrs_from_index (assembly->image, idx);
6015 static MonoCustomAttrInfo*
6016 mono_custom_attrs_from_module (MonoImage *image)
6018 MonoCustomAttrInfo *cinfo;
6021 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6023 idx = 1; /* there is only one module */
6024 idx <<= CUSTOM_ATTR_BITS;
6025 idx |= CUSTOM_ATTR_MODULE;
6026 return mono_custom_attrs_from_index (image, idx);
6030 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6032 MonoCustomAttrInfo *cinfo;
6035 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6037 idx = find_property_index (klass, property);
6038 idx <<= CUSTOM_ATTR_BITS;
6039 idx |= CUSTOM_ATTR_PROPERTY;
6040 return mono_custom_attrs_from_index (klass->image, idx);
6044 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6046 MonoCustomAttrInfo *cinfo;
6049 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6051 idx = find_event_index (klass, event);
6052 idx <<= CUSTOM_ATTR_BITS;
6053 idx |= CUSTOM_ATTR_EVENT;
6054 return mono_custom_attrs_from_index (klass->image, idx);
6058 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6060 MonoCustomAttrInfo *cinfo;
6063 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6065 idx = find_field_index (klass, field);
6066 idx <<= CUSTOM_ATTR_BITS;
6067 idx |= CUSTOM_ATTR_FIELDDEF;
6068 return mono_custom_attrs_from_index (klass->image, idx);
6072 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6075 guint32 i, idx, method_index;
6076 guint32 param_list, param_last, param_pos, found;
6078 MonoReflectionMethodAux *aux;
6080 if (method->klass->image->dynamic) {
6081 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6082 if (!aux || !aux->param_cattr)
6084 return aux->param_cattr [param];
6087 image = method->klass->image;
6088 method_index = find_method_index (method);
6089 ca = &image->tables [MONO_TABLE_METHOD];
6091 if (method->klass->generic_inst || method->klass->gen_params ||
6092 method->signature->generic_param_count) {
6093 // FIXME FIXME FIXME
6097 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6098 if (method_index == ca->rows) {
6099 ca = &image->tables [MONO_TABLE_PARAM];
6100 param_last = ca->rows + 1;
6102 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6103 ca = &image->tables [MONO_TABLE_PARAM];
6106 for (i = param_list; i < param_last; ++i) {
6107 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6108 if (param_pos == param) {
6116 idx <<= CUSTOM_ATTR_BITS;
6117 idx |= CUSTOM_ATTR_PARAMDEF;
6118 return mono_custom_attrs_from_index (image, idx);
6122 * mono_reflection_get_custom_attrs:
6123 * @obj: a reflection object handle
6125 * Return an array with all the custom attributes defined of the
6126 * reflection handle @obj. The objects are fully build.
6129 mono_reflection_get_custom_attrs (MonoObject *obj)
6133 MonoCustomAttrInfo *cinfo = NULL;
6135 MONO_ARCH_SAVE_REGS;
6137 klass = obj->vtable->klass;
6138 /* FIXME: need to handle: Module */
6139 if (klass == mono_defaults.monotype_class) {
6140 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6141 klass = mono_class_from_mono_type (rtype->type);
6142 cinfo = mono_custom_attrs_from_class (klass);
6143 } else if (strcmp ("Assembly", klass->name) == 0) {
6144 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6145 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6146 } else if (strcmp ("Module", klass->name) == 0) {
6147 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6148 cinfo = mono_custom_attrs_from_module (module->image);
6149 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6150 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6151 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6152 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6153 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6154 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6155 } else if (strcmp ("MonoField", klass->name) == 0) {
6156 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6157 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6158 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6159 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6160 cinfo = mono_custom_attrs_from_method (rmethod->method);
6161 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6162 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6163 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6164 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6165 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6166 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6167 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6168 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6169 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6170 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6171 } else { /* handle other types here... */
6172 g_error ("get custom attrs not yet supported for %s", klass->name);
6176 result = mono_custom_attrs_construct (cinfo);
6178 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6179 result = mono_array_new (mono_domain_get (), klass, 0);
6185 static MonoMethodSignature*
6186 parameters_to_signature (MonoArray *parameters) {
6187 MonoMethodSignature *sig;
6190 count = parameters? mono_array_length (parameters): 0;
6192 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6193 sig->param_count = count;
6194 sig->sentinelpos = -1; /* FIXME */
6195 for (i = 0; i < count; ++i) {
6196 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6197 sig->params [i] = pt->type;
6202 static MonoMethodSignature*
6203 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6204 MonoMethodSignature *sig;
6206 sig = parameters_to_signature (ctor->parameters);
6207 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6208 sig->ret = &mono_defaults.void_class->byval_arg;
6212 static MonoMethodSignature*
6213 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6214 MonoMethodSignature *sig;
6216 sig = parameters_to_signature (method->parameters);
6217 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6218 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6219 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6223 static MonoMethodSignature*
6224 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6225 MonoMethodSignature *sig;
6227 sig = parameters_to_signature (method->parameters);
6228 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6229 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6230 sig->generic_param_count = 0;
6235 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6237 MonoClass *klass = mono_object_class (prop);
6238 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6239 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6240 *name = mono_string_to_utf8 (pb->name);
6241 *type = pb->type->type;
6243 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6244 *name = g_strdup (p->property->name);
6245 if (p->property->get)
6246 *type = p->property->get->signature->ret;
6248 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6253 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6255 MonoClass *klass = mono_object_class (field);
6256 if (strcmp (klass->name, "FieldBuilder") == 0) {
6257 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6258 *name = mono_string_to_utf8 (fb->name);
6259 *type = fb->type->type;
6261 MonoReflectionField *f = (MonoReflectionField *)field;
6262 *name = g_strdup (f->field->name);
6263 *type = f->field->type;
6268 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6271 MonoTypeEnum simple_type;
6273 if ((p-buffer) + 10 >= *buflen) {
6276 newbuf = g_realloc (buffer, *buflen);
6277 p = newbuf + (p-buffer);
6280 argval = ((char*)arg + sizeof (MonoObject));
6281 simple_type = type->type;
6283 switch (simple_type) {
6284 case MONO_TYPE_BOOLEAN:
6289 case MONO_TYPE_CHAR:
6292 swap_with_size (p, argval, 2, 1);
6298 swap_with_size (p, argval, 4, 1);
6304 swap_with_size (p, argval, 8, 1);
6307 case MONO_TYPE_VALUETYPE:
6308 if (type->data.klass->enumtype) {
6309 simple_type = type->data.klass->enum_basetype->type;
6312 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6315 case MONO_TYPE_STRING: {
6322 str = mono_string_to_utf8 ((MonoString*)arg);
6323 slen = strlen (str);
6324 if ((p-buffer) + 10 + slen >= *buflen) {
6328 newbuf = g_realloc (buffer, *buflen);
6329 p = newbuf + (p-buffer);
6332 mono_metadata_encode_value (slen, p, &p);
6333 memcpy (p, str, slen);
6338 case MONO_TYPE_CLASS: {
6346 k = mono_object_class (arg);
6347 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6348 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6349 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6351 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6352 slen = strlen (str);
6353 if ((p-buffer) + 10 + slen >= *buflen) {
6357 newbuf = g_realloc (buffer, *buflen);
6358 p = newbuf + (p-buffer);
6361 mono_metadata_encode_value (slen, p, &p);
6362 memcpy (p, str, slen);
6367 case MONO_TYPE_SZARRAY: {
6372 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6375 len = mono_array_length ((MonoArray*)arg);
6377 *p++ = (len >> 8) & 0xff;
6378 *p++ = (len >> 16) & 0xff;
6379 *p++ = (len >> 24) & 0xff;
6381 *retbuffer = buffer;
6382 eclass = type->data.klass;
6383 for (i = 0; i < len; ++i) {
6384 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6388 /* it may be a boxed value or a Type */
6389 case MONO_TYPE_OBJECT: {
6390 MonoClass *klass = mono_object_class (arg);
6394 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6397 } else if (klass->enumtype) {
6399 } else if (klass == mono_defaults.string_class) {
6400 simple_type = MONO_TYPE_STRING;
6403 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6404 *p++ = simple_type = klass->byval_arg.type;
6407 g_error ("unhandled type in custom attr");
6409 str = type_get_qualified_name (klass->enum_basetype, NULL);
6410 slen = strlen (str);
6411 if ((p-buffer) + 10 + slen >= *buflen) {
6415 newbuf = g_realloc (buffer, *buflen);
6416 p = newbuf + (p-buffer);
6419 mono_metadata_encode_value (slen, p, &p);
6420 memcpy (p, str, slen);
6423 simple_type = klass->enum_basetype->type;
6427 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6430 *retbuffer = buffer;
6434 * mono_reflection_get_custom_attrs_blob:
6435 * @ctor: custom attribute constructor
6436 * @ctorArgs: arguments o the constructor
6442 * Creates the blob of data that needs to be saved in the metadata and that represents
6443 * the custom attributed described by @ctor, @ctorArgs etc.
6444 * Returns: a Byte array representing the blob of data.
6447 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6450 MonoMethodSignature *sig;
6455 MONO_ARCH_SAVE_REGS;
6457 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6458 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6460 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6462 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6464 p = buffer = g_malloc (buflen);
6465 /* write the prolog */
6468 for (i = 0; i < sig->param_count; ++i) {
6469 arg = mono_array_get (ctorArgs, MonoObject*, i);
6470 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6474 i += mono_array_length (properties);
6476 i += mono_array_length (fields);
6478 *p++ = (i >> 8) & 0xff;
6481 for (i = 0; i < mono_array_length (properties); ++i) {
6486 prop = mono_array_get (properties, gpointer, i);
6487 get_prop_name_and_type (prop, &pname, &ptype);
6488 *p++ = 0x54; /* PROPERTY signature */
6490 /* Preallocate a large enough buffer */
6491 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6492 char *str = type_get_qualified_name (ptype, NULL);
6498 len += strlen (pname);
6500 if ((p-buffer) + 20 + len >= buflen) {
6504 newbuf = g_realloc (buffer, buflen);
6505 p = newbuf + (p-buffer);
6509 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6510 char *str = type_get_qualified_name (ptype, NULL);
6511 int slen = strlen (str);
6515 * This seems to be optional...
6518 mono_metadata_encode_value (slen, p, &p);
6519 memcpy (p, str, slen);
6523 mono_metadata_encode_value (ptype->type, p, &p);
6524 if (ptype->type == MONO_TYPE_SZARRAY)
6525 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6527 len = strlen (pname);
6528 mono_metadata_encode_value (len, p, &p);
6529 memcpy (p, pname, len);
6531 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6538 for (i = 0; i < mono_array_length (fields); ++i) {
6543 field = mono_array_get (fields, gpointer, i);
6544 get_field_name_and_type (field, &fname, &ftype);
6545 *p++ = 0x53; /* FIELD signature */
6546 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6547 char *str = type_get_qualified_name (ftype, NULL);
6548 int slen = strlen (str);
6549 if ((p-buffer) + 10 + slen >= buflen) {
6553 newbuf = g_realloc (buffer, buflen);
6554 p = newbuf + (p-buffer);
6559 * This seems to be optional...
6562 mono_metadata_encode_value (slen, p, &p);
6563 memcpy (p, str, slen);
6567 mono_metadata_encode_value (ftype->type, p, &p);
6569 len = strlen (fname);
6570 mono_metadata_encode_value (len, p, &p);
6571 memcpy (p, fname, len);
6573 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6578 g_assert (p - buffer <= buflen);
6579 buflen = p - buffer;
6580 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6581 p = mono_array_addr (result, char, 0);
6582 memcpy (p, buffer, buflen);
6584 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6590 * mono_reflection_setup_internal_class:
6591 * @tb: a TypeBuilder object
6593 * Creates a MonoClass that represents the TypeBuilder.
6594 * This is a trick that lets us simplify a lot of reflection code
6595 * (and will allow us to support Build and Run assemblies easier).
6598 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6600 MonoClass *klass, *parent;
6602 MONO_ARCH_SAVE_REGS;
6604 klass = g_new0 (MonoClass, 1);
6606 klass->image = &tb->module->dynamic_image->image;
6609 /* check so we can compile corlib correctly */
6610 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6611 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6612 parent = tb->parent->type->data.klass;
6614 parent = my_mono_class_from_mono_type (tb->parent->type);
6618 klass->inited = 1; /* we lie to the runtime */
6619 klass->name = mono_string_to_utf8 (tb->name);
6620 klass->name_space = mono_string_to_utf8 (tb->nspace);
6621 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6622 klass->flags = tb->attrs;
6624 klass->element_class = klass;
6625 klass->reflection_info = tb; /* need to pin. */
6627 /* Put into cache so mono_class_get () will find it */
6628 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6631 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6632 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6636 mono_class_setup_parent (klass, parent);
6637 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6638 const char *old_n = klass->name;
6639 /* trick to get relative numbering right when compiling corlib */
6640 klass->name = "BuildingObject";
6641 mono_class_setup_parent (klass, mono_defaults.object_class);
6642 klass->name = old_n;
6644 mono_class_setup_mono_type (klass);
6646 mono_class_setup_supertypes (klass);
6649 * FIXME: handle interfaces.
6652 tb->type.type = &klass->byval_arg;
6654 if (tb->nesting_type) {
6655 g_assert (tb->nesting_type->type);
6656 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6659 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6663 * mono_reflection_setup_generic_class:
6664 * @tb: a TypeBuilder object
6666 * Setup the generic class after all generic parameters have been added.
6669 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6674 MONO_ARCH_SAVE_REGS;
6676 klass = my_mono_class_from_mono_type (tb->type.type);
6678 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6680 if (klass->gen_params || (count == 0))
6683 klass->num_gen_params = count;
6684 klass->gen_params = g_new0 (MonoGenericParam, count);
6686 for (i = 0; i < count; i++) {
6687 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6688 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6693 * mono_reflection_create_internal_class:
6694 * @tb: a TypeBuilder object
6696 * Actually create the MonoClass that is associated with the TypeBuilder.
6699 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6703 MONO_ARCH_SAVE_REGS;
6705 klass = my_mono_class_from_mono_type (tb->type.type);
6707 if (klass->enumtype && klass->enum_basetype == NULL) {
6708 MonoReflectionFieldBuilder *fb;
6710 g_assert (tb->fields != NULL);
6711 g_assert (mono_array_length (tb->fields) >= 1);
6713 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6715 klass->enum_basetype = fb->type->type;
6716 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6717 if (!klass->element_class)
6718 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6719 klass->instance_size = klass->element_class->instance_size;
6720 klass->size_inited = 1;
6722 * this is almost safe to do with enums and it's needed to be able
6723 * to create objects of the enum type (for use in SetConstant).
6725 /* FIXME: Does this mean enums can't have method overrides ? */
6726 mono_class_setup_vtable (klass, NULL, 0);
6730 static MonoMarshalSpec*
6731 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6732 MonoReflectionMarshal *minfo)
6734 MonoMarshalSpec *res;
6736 res = g_new0 (MonoMarshalSpec, 1);
6737 res->native = minfo->type;
6739 switch (minfo->type) {
6740 case MONO_NATIVE_LPARRAY:
6741 res->data.array_data.elem_type = minfo->eltype;
6742 res->data.array_data.param_num = 0; /* Not yet */
6743 res->data.array_data.num_elem = minfo->count;
6746 case MONO_NATIVE_BYVALTSTR:
6747 case MONO_NATIVE_BYVALARRAY:
6748 res->data.array_data.num_elem = minfo->count;
6751 case MONO_NATIVE_CUSTOM:
6752 if (minfo->marshaltyperef)
6753 res->data.custom_data.custom_name =
6754 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6756 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6767 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6768 ReflectionMethodBuilder *rmb,
6769 MonoMethodSignature *sig)
6772 MonoMethodNormal *pm;
6773 MonoMarshalSpec **specs;
6774 MonoReflectionMethodAux *method_aux;
6777 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6778 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6779 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6782 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6784 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6786 pm = (MonoMethodNormal*)m;
6789 m->flags = rmb->attrs;
6790 m->iflags = rmb->iattrs;
6791 m->name = mono_string_to_utf8 (rmb->name);
6795 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6797 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6798 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6801 m->signature->pinvoke = 1;
6802 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6804 m->signature->pinvoke = 1;
6806 } else if (!m->klass->dummy &&
6807 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6808 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6809 MonoMethodHeader *header;
6811 gint32 max_stack, i;
6812 gint32 num_locals = 0;
6813 gint32 num_clauses = 0;
6817 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6818 code_size = rmb->ilgen->code_len;
6819 max_stack = rmb->ilgen->max_stack;
6820 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6821 if (rmb->ilgen->ex_handlers)
6822 num_clauses = method_count_clauses (rmb->ilgen);
6825 code = mono_array_addr (rmb->code, guint8, 0);
6826 code_size = mono_array_length (rmb->code);
6827 /* we probably need to run a verifier on the code... */
6837 header = g_malloc0 (sizeof (MonoMethodHeader) +
6838 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6839 header->code_size = code_size;
6840 header->code = g_malloc (code_size);
6841 memcpy ((char*)header->code, code, code_size);
6842 header->max_stack = max_stack;
6843 header->init_locals = rmb->init_locals;
6844 header->num_locals = num_locals;
6846 for (i = 0; i < num_locals; ++i) {
6847 MonoReflectionLocalBuilder *lb =
6848 mono_array_get (rmb->ilgen->locals,
6849 MonoReflectionLocalBuilder*, i);
6851 header->locals [i] = g_new0 (MonoType, 1);
6852 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6855 header->num_clauses = num_clauses;
6857 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6862 if (rmb->generic_params) {
6863 int count = mono_array_length (rmb->generic_params);
6864 header->gen_params = g_new0 (MonoGenericParam, count);
6865 for (i = 0; i < count; i++) {
6866 MonoReflectionGenericParam *gp =
6867 mono_array_get (rmb->generic_params,
6868 MonoReflectionGenericParam*, i);
6870 header->gen_params [i] = *gp->type.type->data.generic_param;
6874 pm->header = header;
6878 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6881 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6883 for (i = 0; i < rmb->nrefs; ++i)
6884 mw->data = g_list_append (mw->data, rmb->refs [i]);
6889 /* Parameter names */
6892 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6893 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6894 for (i = 0; i <= m->signature->param_count; ++i) {
6895 MonoReflectionParamBuilder *pb;
6896 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6898 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6900 if (!method_aux->param_cattr)
6901 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6902 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6908 /* Parameter marshalling */
6911 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6912 MonoReflectionParamBuilder *pb;
6913 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6914 if (pb->marshal_info) {
6916 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6917 specs [pb->position] =
6918 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6922 if (specs != NULL) {
6924 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6925 method_aux->param_marshall = specs;
6928 if (klass->image->dynamic && method_aux)
6929 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6935 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6937 ReflectionMethodBuilder rmb;
6938 MonoMethodSignature *sig;
6940 sig = ctor_builder_to_signature (mb);
6942 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6944 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6945 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6947 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6948 /* ilgen is no longer needed */
6956 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6958 ReflectionMethodBuilder rmb;
6959 MonoMethodSignature *sig;
6961 sig = method_builder_to_signature (mb);
6963 reflection_methodbuilder_from_method_builder (&rmb, mb);
6965 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6966 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6968 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6969 /* ilgen is no longer needed */
6975 static MonoClassField*
6976 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6978 MonoClassField *field;
6985 field = g_new0 (MonoClassField, 1);
6987 field->name = mono_string_to_utf8 (fb->name);
6989 /* FIXME: handle type modifiers */
6990 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6991 field->type->attrs = fb->attrs;
6993 field->type = fb->type->type;
6995 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6996 field->data = mono_array_addr (fb->rva_data, char, 0);
6997 if (fb->offset != -1)
6998 field->offset = fb->offset;
6999 field->parent = klass;
7001 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7003 if (fb->def_value) {
7004 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7005 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7006 field->def_value = g_new0 (MonoConstant, 1);
7007 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7008 /* Copy the data from the blob since it might get realloc-ed */
7009 p = assembly->blob.data + idx;
7010 len = mono_metadata_decode_blob_size (p, &p2);
7012 field->def_value->value = g_malloc (len);
7013 memcpy (field->def_value->value, p, len);
7020 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7024 MonoReflectionTypeBuilder *tb = NULL;
7025 MonoGenericInst *ginst;
7030 klass = mono_class_from_mono_type (type->type);
7031 if (!klass->gen_params && !klass->generic_inst &&
7032 !(klass->nested_in && klass->nested_in->gen_params))
7035 mono_loader_lock ();
7037 domain = mono_object_domain (type);
7039 ginst = g_new0 (MonoGenericInst, 1);
7041 if (!klass->generic_inst) {
7042 ginst->type_argc = type_argc;
7043 ginst->type_argv = types;
7045 for (i = 0; i < ginst->type_argc; ++i) {
7046 if (!ginst->is_open)
7047 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7050 ginst->generic_type = &klass->byval_arg;
7052 MonoGenericInst *kginst = klass->generic_inst;
7054 ginst->type_argc = kginst->type_argc;
7055 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7057 for (i = 0; i < ginst->type_argc; i++) {
7058 MonoType *t = kginst->type_argv [i];
7060 if (t->type == MONO_TYPE_VAR)
7061 t = types [t->data.generic_param->num];
7063 if (!ginst->is_open)
7064 ginst->is_open = mono_class_is_open_constructed_type (t);
7066 ginst->type_argv [i] = t;
7069 ginst->generic_type = kginst->generic_type;
7072 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7075 mono_loader_unlock ();
7079 ginst->context = g_new0 (MonoGenericContext, 1);
7080 ginst->context->ginst = ginst;
7082 geninst = g_new0 (MonoType, 1);
7083 geninst->type = MONO_TYPE_GENERICINST;
7084 geninst->data.generic_inst = ginst;
7086 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7087 tb = (MonoReflectionTypeBuilder *) type;
7089 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7090 ginst->is_dynamic = TRUE;
7091 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7092 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7093 MonoReflectionType *rgt = rgi->generic_type;
7095 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7096 tb = (MonoReflectionTypeBuilder *) rgt;
7098 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7099 ginst->is_dynamic = TRUE;
7101 icount = klass->interface_count;
7103 ginst->ifaces = g_new0 (MonoType *, icount);
7104 ginst->count_ifaces = icount;
7106 for (i = 0; i < icount; i++) {
7107 MonoReflectionType *itype;
7110 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7112 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7113 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7114 if (!ginst->ifaces [i])
7115 ginst->ifaces [i] = itype->type;
7118 mono_class_create_generic (ginst);
7120 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7122 mono_loader_unlock ();
7128 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7130 MonoClass *klass, *pklass = NULL;
7131 MonoReflectionType *parent = NULL;
7133 MonoReflectionTypeBuilder *tb = NULL;
7134 MonoGenericInst *ginst;
7137 domain = mono_object_domain (type);
7138 klass = mono_class_from_mono_type (type->type);
7140 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7141 tb = (MonoReflectionTypeBuilder *) type;
7144 parent = tb->parent;
7145 pklass = mono_class_from_mono_type (parent->type);
7148 pklass = klass->parent;
7150 parent = mono_type_get_object (domain, &pklass->byval_arg);
7153 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7157 ginst = geninst->data.generic_inst;
7159 if (pklass && pklass->generic_inst)
7160 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7165 MonoReflectionMethod*
7166 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7168 MonoMethod *method, *inflated;
7169 MonoReflectionMethodBuilder *mb = NULL;
7170 MonoGenericMethod *gmethod;
7171 MonoGenericContext *context;
7174 MONO_ARCH_SAVE_REGS;
7175 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7176 MonoReflectionTypeBuilder *tb;
7179 mb = (MonoReflectionMethodBuilder *) rmethod;
7180 tb = (MonoReflectionTypeBuilder *) mb->type;
7181 klass = mono_class_from_mono_type (tb->type.type);
7183 method = methodbuilder_to_mono_method (klass, mb);
7185 method = rmethod->method;
7187 count = method->signature->generic_param_count;
7188 if (count != mono_array_length (types))
7191 gmethod = g_new0 (MonoGenericMethod, 1);
7192 gmethod->mtype_argc = count;
7193 gmethod->mtype_argv = g_new0 (MonoType *, count);
7194 for (i = 0; i < count; i++) {
7195 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7196 gmethod->mtype_argv [i] = garg->type;
7199 context = g_new0 (MonoGenericContext, 1);
7200 context->ginst = method->klass->generic_inst;
7201 context->gmethod = gmethod;
7203 inflated = mono_class_inflate_generic_method (method, context, NULL);
7205 return mono_method_get_object (
7206 mono_object_domain (rmethod), inflated, NULL);
7210 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7212 MonoGenericMethod *gmethod;
7213 MonoGenericInst *ginst;
7214 MonoGenericContext *context;
7217 ginst = type->type.type->data.generic_inst;
7219 gmethod = g_new0 (MonoGenericMethod, 1);
7220 gmethod->reflection_info = obj;
7222 gmethod->mtype_argc = method->signature->generic_param_count;
7223 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7225 for (i = 0; i < gmethod->mtype_argc; i++) {
7226 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7227 MonoGenericParam *gparam = &mn->header->gen_params [i];
7229 g_assert (gparam->pklass);
7230 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7233 context = g_new0 (MonoGenericContext, 1);
7234 context->ginst = ginst;
7235 context->gmethod = gmethod;
7237 return mono_class_inflate_generic_method (method, context, ginst->klass);
7241 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7246 klass = mono_class_from_mono_type (type->type.type);
7248 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7249 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7250 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7251 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7252 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7253 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7254 method = ((MonoReflectionMethod *) obj)->method;
7256 method = NULL; /* prevent compiler warning */
7257 g_assert_not_reached ();
7260 return inflate_mono_method (type, method, obj);
7264 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7265 MonoArray *methods, MonoArray *ctors,
7266 MonoArray *fields, MonoArray *properties,
7269 MonoGenericInst *ginst;
7270 MonoDynamicGenericInst *dginst;
7271 MonoClass *klass, *gklass, *pklass;
7274 MONO_ARCH_SAVE_REGS;
7276 klass = mono_class_from_mono_type (type->type.type);
7277 ginst = type->type.type->data.generic_inst;
7279 if (ginst->initialized)
7282 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7284 gklass = mono_class_from_mono_type (ginst->generic_type);
7285 mono_class_init (gklass);
7288 pklass = mono_class_from_mono_type (ginst->parent);
7290 pklass = gklass->parent;
7292 mono_class_setup_parent (klass, pklass);
7294 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7295 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7296 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7297 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7298 dginst->count_events = events ? mono_array_length (events) : 0;
7300 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7301 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7302 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7303 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7304 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7306 for (i = 0; i < dginst->count_methods; i++) {
7307 MonoObject *obj = mono_array_get (methods, gpointer, i);
7309 dginst->methods [i] = inflate_method (type, obj);
7312 for (i = 0; i < dginst->count_ctors; i++) {
7313 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7315 dginst->ctors [i] = inflate_method (type, obj);
7318 for (i = 0; i < dginst->count_fields; i++) {
7319 MonoObject *obj = mono_array_get (fields, gpointer, i);
7320 MonoClassField *field;
7322 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7323 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7324 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7325 field = ((MonoReflectionField *) obj)->field;
7327 field = NULL; /* prevent compiler warning */
7328 g_assert_not_reached ();
7331 dginst->fields [i] = *field;
7332 dginst->fields [i].generic_type = field->type;
7333 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7336 for (i = 0; i < dginst->count_properties; i++) {
7337 MonoObject *obj = mono_array_get (properties, gpointer, i);
7338 MonoProperty *property = &dginst->properties [i];
7340 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7341 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7343 property->parent = klass;
7344 property->attrs = pb->attrs;
7345 property->name = mono_string_to_utf8 (pb->name);
7347 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7349 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7350 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7351 *property = *((MonoReflectionProperty *) obj)->property;
7354 property->get = inflate_mono_method (type, property->get, NULL);
7356 property->set = inflate_mono_method (type, property->set, NULL);
7358 g_assert_not_reached ();
7361 for (i = 0; i < dginst->count_events; i++) {
7362 MonoObject *obj = mono_array_get (events, gpointer, i);
7363 MonoEvent *event = &dginst->events [i];
7365 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7366 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7368 event->parent = klass;
7369 event->attrs = eb->attrs;
7370 event->name = mono_string_to_utf8 (eb->name);
7372 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7373 if (eb->remove_method)
7374 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7375 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7376 *event = *((MonoReflectionEvent *) obj)->event;
7379 event->add = inflate_mono_method (type, event->add, NULL);
7381 event->remove = inflate_mono_method (type, event->remove, NULL);
7383 g_assert_not_reached ();
7386 ginst->initialized = TRUE;
7390 ensure_runtime_vtable (MonoClass *klass)
7392 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7393 int i, num, j, onum;
7394 MonoMethod **overrides;
7396 if (!tb || klass->wastypebuilder)
7399 ensure_runtime_vtable (klass->parent);
7401 num = tb->ctors? mono_array_length (tb->ctors): 0;
7402 num += tb->num_methods;
7403 klass->method.count = num;
7404 klass->methods = g_new (MonoMethod*, num);
7405 num = tb->ctors? mono_array_length (tb->ctors): 0;
7406 for (i = 0; i < num; ++i)
7407 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7408 num = tb->num_methods;
7410 for (i = 0; i < num; ++i)
7411 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7413 klass->wastypebuilder = TRUE;
7414 if (tb->interfaces) {
7415 klass->interface_count = mono_array_length (tb->interfaces);
7416 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7417 for (i = 0; i < klass->interface_count; ++i) {
7418 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7419 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7423 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7424 for (i = 0; i < klass->method.count; ++i)
7425 klass->methods [i]->slot = i;
7430 for (i = 0; i < tb->num_methods; ++i) {
7431 MonoReflectionMethodBuilder *mb =
7432 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7433 if (mb->override_method)
7438 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7442 for (i = 0; i < tb->num_methods; ++i) {
7443 MonoReflectionMethodBuilder *mb =
7444 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7445 if (mb->override_method) {
7446 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7447 overrides [onum * 2] =
7448 mb->override_method->method;
7449 overrides [onum * 2 + 1] =
7452 g_assert (mb->mhandle);
7459 mono_class_setup_vtable (klass, overrides, onum);
7463 typebuilder_setup_fields (MonoClass *klass)
7465 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7466 MonoReflectionFieldBuilder *fb;
7467 MonoClassField *field;
7472 klass->field.count = tb->num_fields;
7473 klass->field.first = 0;
7474 klass->field.last = klass->field.count;
7476 if (!klass->field.count)
7479 klass->fields = g_new0 (MonoClassField, klass->field.count);
7481 for (i = 0; i < klass->field.count; ++i) {
7482 fb = mono_array_get (tb->fields, gpointer, i);
7483 field = &klass->fields [i];
7484 field->name = mono_string_to_utf8 (fb->name);
7486 /* FIXME: handle type modifiers */
7487 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7488 field->type->attrs = fb->attrs;
7490 field->type = fb->type->type;
7492 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7493 field->data = mono_array_addr (fb->rva_data, char, 0);
7494 if (fb->offset != -1)
7495 field->offset = fb->offset;
7496 field->parent = klass;
7498 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7500 if (fb->def_value) {
7501 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7502 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7503 field->def_value = g_new0 (MonoConstant, 1);
7504 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7505 /* Copy the data from the blob since it might get realloc-ed */
7506 p = assembly->blob.data + idx;
7507 len = mono_metadata_decode_blob_size (p, &p2);
7509 field->def_value->value = g_malloc (len);
7510 memcpy (field->def_value->value, p, len);
7513 mono_class_layout_fields (klass);
7517 typebuilder_setup_properties (MonoClass *klass)
7519 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7520 MonoReflectionPropertyBuilder *pb;
7523 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7524 klass->property.first = 0;
7525 klass->property.last = klass->property.count;
7527 klass->properties = g_new0 (MonoProperty, klass->property.count);
7528 for (i = 0; i < klass->property.count; ++i) {
7529 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7530 klass->properties [i].parent = klass;
7531 klass->properties [i].attrs = pb->attrs;
7532 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7534 klass->properties [i].get = pb->get_method->mhandle;
7536 klass->properties [i].set = pb->set_method->mhandle;
7540 MonoReflectionEvent *
7541 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7543 MonoEvent *event = g_new0 (MonoEvent, 1);
7547 klass = my_mono_class_from_mono_type (tb->type.type);
7549 event->parent = klass;
7550 event->attrs = eb->attrs;
7551 event->name = mono_string_to_utf8 (eb->name);
7553 event->add = eb->add_method->mhandle;
7554 if (eb->remove_method)
7555 event->remove = eb->remove_method->mhandle;
7556 if (eb->raise_method)
7557 event->raise = eb->raise_method->mhandle;
7559 if (eb->other_methods) {
7560 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7561 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7562 MonoReflectionMethodBuilder *mb =
7563 mono_array_get (eb->other_methods,
7564 MonoReflectionMethodBuilder*, j);
7565 event->other [j] = mb->mhandle;
7569 return mono_event_get_object (mono_object_domain (tb), klass, event);
7573 typebuilder_setup_events (MonoClass *klass)
7575 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7576 MonoReflectionEventBuilder *eb;
7579 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7580 klass->event.first = 0;
7581 klass->event.last = klass->event.count;
7583 klass->events = g_new0 (MonoEvent, klass->event.count);
7584 for (i = 0; i < klass->event.count; ++i) {
7585 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7586 klass->events [i].parent = klass;
7587 klass->events [i].attrs = eb->attrs;
7588 klass->events [i].name = mono_string_to_utf8 (eb->name);
7590 klass->events [i].add = eb->add_method->mhandle;
7591 if (eb->remove_method)
7592 klass->events [i].remove = eb->remove_method->mhandle;
7593 if (eb->raise_method)
7594 klass->events [i].raise = eb->raise_method->mhandle;
7596 if (eb->other_methods) {
7597 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7598 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7599 MonoReflectionMethodBuilder *mb =
7600 mono_array_get (eb->other_methods,
7601 MonoReflectionMethodBuilder*, j);
7602 klass->events [i].other [j] = mb->mhandle;
7609 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7612 MonoReflectionType* res;
7614 MONO_ARCH_SAVE_REGS;
7616 klass = my_mono_class_from_mono_type (tb->type.type);
7618 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7621 * Fields to set in klass:
7622 * the various flags: delegate/unicode/contextbound etc.
7625 klass->flags = tb->attrs;
7627 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7628 /* No need to fully construct the type */
7629 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7631 /* enums are done right away */
7632 if (!klass->enumtype)
7633 ensure_runtime_vtable (klass);
7635 /* fields and object layout */
7636 if (klass->parent) {
7637 if (!klass->parent->size_inited)
7638 mono_class_init (klass->parent);
7639 klass->instance_size += klass->parent->instance_size;
7640 klass->class_size += klass->parent->class_size;
7641 klass->min_align = klass->parent->min_align;
7643 klass->instance_size = sizeof (MonoObject);
7644 klass->min_align = 1;
7647 /* FIXME: handle packing_size and instance_size */
7648 typebuilder_setup_fields (klass);
7650 typebuilder_setup_properties (klass);
7652 typebuilder_setup_events (klass);
7654 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7655 /* with enums res == tb: need to fix that. */
7656 if (!klass->enumtype)
7657 g_assert (res != (MonoReflectionType*)tb);
7662 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7664 MonoGenericParam *param;
7667 MONO_ARCH_SAVE_REGS;
7669 param = g_new0 (MonoGenericParam, 1);
7671 param->method = NULL;
7672 param->name = mono_string_to_utf8 (gparam->name);
7673 param->num = gparam->index;
7675 image = &gparam->tbuilder->module->dynamic_image->image;
7676 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7678 param->pklass->reflection_info = gparam;
7680 gparam->type.type = g_new0 (MonoType, 1);
7681 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7682 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7683 gparam->type.type->data.generic_param = param;
7687 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7689 MonoDynamicImage *assembly = sig->module->dynamic_image;
7690 guint32 na = mono_array_length (sig->arguments);
7695 MONO_ARCH_SAVE_REGS;
7697 p = buf = g_malloc (10 + na * 10);
7699 mono_metadata_encode_value (0x07, p, &p);
7700 mono_metadata_encode_value (na, p, &p);
7701 for (i = 0; i < na; ++i) {
7702 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7703 encode_reflection_type (assembly, type, p, &p);
7707 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7708 p = mono_array_addr (result, char, 0);
7709 memcpy (p, buf, buflen);
7716 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7718 MonoDynamicImage *assembly = sig->module->dynamic_image;
7719 guint32 na = mono_array_length (sig->arguments);
7724 MONO_ARCH_SAVE_REGS;
7726 p = buf = g_malloc (10 + na * 10);
7728 mono_metadata_encode_value (0x06, p, &p);
7729 for (i = 0; i < na; ++i) {
7730 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7731 encode_reflection_type (assembly, type, p, &p);
7735 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7736 p = mono_array_addr (result, char, 0);
7737 memcpy (p, buf, buflen);
7744 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7746 ReflectionMethodBuilder rmb;
7747 MonoMethodSignature *sig;
7750 sig = dynamic_method_to_signature (mb);
7752 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7755 * Resolve references.
7757 rmb.nrefs = mb->nrefs;
7758 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7759 for (i = 0; i < mb->nrefs; ++i) {
7760 gpointer ref = resolve_object (mb->module->image,
7761 mono_array_get (mb->refs, MonoObject*, i));
7764 mono_raise_exception (mono_get_exception_type_load (NULL));
7771 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7775 /* ilgen is no longer needed */
7780 * mono_reflection_lookup_dynamic_token:
7782 * Finish the Builder object pointed to by TOKEN and return the corresponding
7783 * runtime structure.
7786 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7788 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7791 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7794 return resolve_object (image, obj);
7798 resolve_object (MonoImage *image, MonoObject *obj)
7800 gpointer result = NULL;
7802 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7803 result = mono_string_intern ((MonoString*)obj);
7806 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7807 MonoReflectionType *tb = (MonoReflectionType*)obj;
7808 result = mono_class_from_mono_type (tb->type);
7811 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7812 result = ((MonoReflectionMethod*)obj)->method;
7815 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7816 result = ((MonoReflectionMethod*)obj)->method;
7819 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7820 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7821 result = mb->mhandle;
7823 /* Type is not yet created */
7824 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7826 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7829 * Hopefully this has been filled in by calling CreateType() on the
7833 * TODO: This won't work if the application finishes another
7834 * TypeBuilder instance instead of this one.
7836 result = mb->mhandle;
7839 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7840 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7842 result = cb->mhandle;
7844 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7846 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7847 result = cb->mhandle;
7850 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7851 result = ((MonoReflectionField*)obj)->field;
7854 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7855 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7856 result = fb->handle;
7859 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7861 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7862 result = fb->handle;
7865 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7866 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7869 klass = tb->type.type->data.klass;
7870 if (klass->wastypebuilder) {
7871 /* Already created */
7875 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7876 result = tb->type.type->data.klass;
7880 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7881 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7882 MonoMethodSignature *sig;
7885 if (helper->arguments)
7886 nargs = mono_array_length (helper->arguments);
7890 sig = mono_metadata_signature_alloc (image, nargs);
7891 sig->explicit_this = helper->call_conv & 64;
7892 sig->hasthis = helper->call_conv & 32;
7894 if (helper->call_conv == 0) /* unmanaged */
7895 sig->call_convention = helper->unmanaged_call_conv - 1;
7897 if (helper->call_conv & 0x02)
7898 sig->call_convention = MONO_CALL_VARARG;
7900 sig->call_convention = MONO_CALL_DEFAULT;
7902 sig->param_count = nargs;
7903 /* TODO: Copy type ? */
7904 sig->ret = helper->return_type->type;
7905 for (i = 0; i < nargs; ++i) {
7906 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7907 sig->params [i] = rt->type;
7913 g_print (obj->vtable->klass->name);
7914 g_assert_not_reached ();