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);
742 if (lb->type->type->pinned)
743 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
745 encode_reflection_type (assembly, lb->type, p, &p);
747 g_assert (p - buf < size);
748 mono_metadata_encode_value (p-buf, b, &b);
749 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
752 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
758 method_count_clauses (MonoReflectionILGen *ilgen)
760 guint32 num_clauses = 0;
763 MonoILExceptionInfo *ex_info;
764 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
765 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
766 if (ex_info->handlers)
767 num_clauses += mono_array_length (ex_info->handlers);
775 static MonoExceptionClause*
776 method_encode_clauses (MonoDynamicImage *assembly,
777 MonoReflectionILGen *ilgen, guint32 num_clauses)
779 MonoExceptionClause *clauses;
780 MonoExceptionClause *clause;
781 MonoILExceptionInfo *ex_info;
782 MonoILExceptionBlock *ex_block;
783 guint32 finally_start;
784 int i, j, clause_index;;
786 clauses = g_new0 (MonoExceptionClause, num_clauses);
789 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
790 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
791 finally_start = ex_info->start + ex_info->len;
792 g_assert (ex_info->handlers);
793 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
794 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
795 clause = &(clauses [clause_index]);
797 clause->flags = ex_block->type;
798 clause->try_offset = ex_info->start;
800 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
801 clause->try_len = finally_start - ex_info->start;
803 clause->try_len = ex_info->len;
804 clause->handler_offset = ex_block->start;
805 clause->handler_len = ex_block->len;
806 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
807 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
808 if (ex_block->extype) {
809 mono_g_hash_table_insert (assembly->tokens,
810 GUINT_TO_POINTER (clause->token_or_filter),
813 finally_start = ex_block->start + ex_block->len;
823 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
829 gint32 num_locals = 0;
830 gint32 num_exception = 0;
833 char fat_header [12];
836 guint32 local_sig = 0;
837 guint32 header_size = 12;
840 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
841 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
842 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
843 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
847 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
849 code = mb->ilgen->code;
850 code_size = mb->ilgen->code_len;
851 max_stack = mb->ilgen->max_stack;
852 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
853 if (mb->ilgen->ex_handlers)
854 num_exception = method_count_clauses (mb->ilgen);
858 char *name = mono_string_to_utf8 (mb->name);
859 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
860 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
863 mono_raise_exception (exception);
866 code_size = mono_array_length (code);
867 max_stack = 8; /* we probably need to run a verifier on the code... */
870 /* check for exceptions, maxstack, locals */
871 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
873 if (code_size < 64 && !(code_size & 1)) {
874 flags = (code_size << 2) | 0x2;
875 } else if (code_size < 32 && (code_size & 1)) {
876 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
880 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
881 /* add to the fixup todo list */
882 if (mb->ilgen && mb->ilgen->num_token_fixups)
883 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
884 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
885 return assembly->text_rva + idx;
889 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
891 * FIXME: need to set also the header size in fat_flags.
892 * (and more sects and init locals flags)
896 fat_flags |= METHOD_HEADER_MORE_SECTS;
898 fat_flags |= METHOD_HEADER_INIT_LOCALS;
899 fat_header [0] = fat_flags;
900 fat_header [1] = (header_size / 4 ) << 4;
901 shortp = (guint16*)(fat_header + 2);
902 *shortp = GUINT16_TO_LE (max_stack);
903 intp = (guint32*)(fat_header + 4);
904 *intp = GUINT32_TO_LE (code_size);
905 intp = (guint32*)(fat_header + 8);
906 *intp = GUINT32_TO_LE (local_sig);
907 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
908 /* add to the fixup todo list */
909 if (mb->ilgen && mb->ilgen->num_token_fixups)
910 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
912 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
914 unsigned char sheader [4];
915 MonoExceptionClause clause;
916 MonoILExceptionInfo * ex_info;
917 MonoILExceptionBlock * ex_block;
920 stream_data_align (&assembly->code);
921 /* always use fat format for now */
922 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
923 num_exception *= sizeof (MonoExceptionClause);
924 num_exception += 4; /* include the size of the header */
925 sheader [1] = num_exception & 0xff;
926 sheader [2] = (num_exception >> 8) & 0xff;
927 sheader [3] = (num_exception >> 16) & 0xff;
928 mono_image_add_stream_data (&assembly->code, sheader, 4);
929 /* fat header, so we are already aligned */
931 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
932 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
933 if (ex_info->handlers) {
934 int finally_start = ex_info->start + ex_info->len;
935 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
936 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
937 clause.flags = GUINT32_TO_LE (ex_block->type);
938 clause.try_offset = GUINT32_TO_LE (ex_info->start);
939 /* need fault, too, probably */
940 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
941 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
943 clause.try_len = GUINT32_TO_LE (ex_info->len);
944 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
945 clause.handler_len = GUINT32_TO_LE (ex_block->len);
946 finally_start = ex_block->start + ex_block->len;
947 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
948 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
949 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
950 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
951 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
952 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
955 g_error ("No clauses for ex info block %d", i);
959 return assembly->text_rva + idx;
963 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
966 MonoDynamicTable *table;
969 table = &assembly->tables [table_idx];
971 g_assert (col < table->columns);
973 values = table->values + table->columns;
974 for (i = 1; i <= table->rows; ++i) {
975 if (values [col] == token)
977 values += table->columns;
982 static GHashTable *dynamic_custom_attrs = NULL;
984 static MonoCustomAttrInfo*
985 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
988 MonoCustomAttrInfo *ainfo;
989 MonoReflectionCustomAttr *cattr;
993 /* FIXME: check in assembly the Run flag is set */
995 count = mono_array_length (cattrs);
997 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
999 ainfo->image = image;
1000 ainfo->num_attrs = count;
1001 for (i = 0; i < count; ++i) {
1002 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1003 ainfo->attrs [i].ctor = cattr->ctor->method;
1004 /* FIXME: might want to memdup the data here */
1005 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1006 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1013 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1015 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1020 if (!dynamic_custom_attrs)
1021 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1023 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1027 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1029 /* they are cached, so we don't free them */
1030 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1036 * idx is the table index of the object
1037 * type is one of CUSTOM_ATTR_*
1040 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1042 MonoDynamicTable *table;
1043 MonoReflectionCustomAttr *cattr;
1045 guint32 count, i, token;
1047 char *p = blob_size;
1049 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1052 count = mono_array_length (cattrs);
1053 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1054 table->rows += count;
1055 alloc_table (table, table->rows);
1056 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1057 idx <<= CUSTOM_ATTR_BITS;
1059 for (i = 0; i < count; ++i) {
1060 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1061 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1062 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1063 type = mono_metadata_token_index (token);
1064 type <<= CUSTOM_ATTR_TYPE_BITS;
1065 switch (mono_metadata_token_table (token)) {
1066 case MONO_TABLE_METHOD:
1067 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1069 case MONO_TABLE_MEMBERREF:
1070 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1073 g_warning ("got wrong token in custom attr");
1076 values [MONO_CUSTOM_ATTR_TYPE] = type;
1078 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1079 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1080 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1081 values += MONO_CUSTOM_ATTR_SIZE;
1087 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1088 MonoArray *permissions)
1090 MonoDynamicTable *table;
1092 guint32 count, i, idx;
1093 MonoReflectionPermissionSet *perm;
1098 count = mono_array_length (permissions);
1099 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1100 table->rows += count;
1101 alloc_table (table, table->rows);
1103 for (i = 0; i < mono_array_length (permissions); ++i) {
1104 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1106 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1108 idx = mono_metadata_token_index (parent_token);
1109 idx <<= HAS_DECL_SECURITY_BITS;
1110 switch (mono_metadata_token_table (parent_token)) {
1111 case MONO_TABLE_TYPEDEF:
1112 idx |= HAS_DECL_SECURITY_TYPEDEF;
1114 case MONO_TABLE_METHOD:
1115 idx |= HAS_DECL_SECURITY_METHODDEF;
1117 case MONO_TABLE_ASSEMBLY:
1118 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1121 g_assert_not_reached ();
1124 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1125 values [MONO_DECL_SECURITY_PARENT] = idx;
1126 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1133 * Fill in the MethodDef and ParamDef tables for a method.
1134 * This is used for both normal methods and constructors.
1137 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1139 MonoDynamicTable *table;
1144 /* room in this table is already allocated */
1145 table = &assembly->tables [MONO_TABLE_METHOD];
1146 *mb->table_idx = table->next_idx ++;
1147 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1148 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1149 name = mono_string_to_utf8 (mb->name);
1150 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1152 values [MONO_METHOD_FLAGS] = mb->attrs;
1153 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1154 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1155 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1157 table = &assembly->tables [MONO_TABLE_PARAM];
1158 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1160 mono_image_add_decl_security (assembly,
1161 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1165 MonoDynamicTable *mtable;
1168 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1169 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1172 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1173 if (mono_array_get (mb->pinfo, gpointer, i))
1176 table->rows += count;
1177 alloc_table (table, table->rows);
1178 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1179 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1180 MonoReflectionParamBuilder *pb;
1181 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1182 values [MONO_PARAM_FLAGS] = pb->attrs;
1183 values [MONO_PARAM_SEQUENCE] = i;
1184 if (pb->name != NULL) {
1185 name = mono_string_to_utf8 (pb->name);
1186 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1190 values [MONO_PARAM_NAME] = 0;
1191 values += MONO_PARAM_SIZE;
1192 if (pb->marshal_info) {
1194 alloc_table (mtable, mtable->rows);
1195 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1196 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1197 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1199 pb->table_idx = table->next_idx++;
1206 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1207 MonoReflectionMethodBuilder *mb)
1209 rmb->ilgen = mb->ilgen;
1210 rmb->rtype = mb->rtype;
1211 rmb->parameters = mb->parameters;
1212 rmb->generic_params = mb->generic_params;
1213 rmb->pinfo = mb->pinfo;
1214 rmb->attrs = mb->attrs;
1215 rmb->iattrs = mb->iattrs;
1216 rmb->call_conv = mb->call_conv;
1217 rmb->code = mb->code;
1218 rmb->type = mb->type;
1219 rmb->name = mb->name;
1220 rmb->table_idx = &mb->table_idx;
1221 rmb->init_locals = mb->init_locals;
1222 rmb->return_modreq = mb->return_modreq;
1223 rmb->return_modopt = mb->return_modopt;
1224 rmb->param_modreq = mb->param_modreq;
1225 rmb->param_modopt = mb->param_modopt;
1226 rmb->permissions = mb->permissions;
1227 rmb->mhandle = mb->mhandle;
1233 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1234 MonoReflectionCtorBuilder *mb)
1236 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1238 rmb->ilgen = mb->ilgen;
1239 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1240 rmb->parameters = mb->parameters;
1241 rmb->generic_params = NULL;
1242 rmb->pinfo = mb->pinfo;
1243 rmb->attrs = mb->attrs;
1244 rmb->iattrs = mb->iattrs;
1245 rmb->call_conv = mb->call_conv;
1247 rmb->type = mb->type;
1248 rmb->name = mono_string_new (mono_domain_get (), name);
1249 rmb->table_idx = &mb->table_idx;
1250 rmb->init_locals = mb->init_locals;
1251 rmb->return_modreq = NULL;
1252 rmb->return_modopt = NULL;
1253 rmb->param_modreq = mb->param_modreq;
1254 rmb->param_modopt = mb->param_modopt;
1255 rmb->permissions = mb->permissions;
1256 rmb->mhandle = mb->mhandle;
1262 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1263 MonoReflectionDynamicMethod *mb)
1265 rmb->ilgen = mb->ilgen;
1266 rmb->rtype = mb->rtype;
1267 rmb->parameters = mb->parameters;
1268 rmb->generic_params = NULL;
1270 rmb->attrs = mb->attrs;
1272 rmb->call_conv = mb->call_conv;
1275 rmb->name = mb->name;
1276 rmb->table_idx = NULL;
1277 rmb->init_locals = mb->init_locals;
1278 rmb->return_modreq = NULL;
1279 rmb->return_modopt = NULL;
1280 rmb->param_modreq = NULL;
1281 rmb->param_modopt = NULL;
1282 rmb->permissions = NULL;
1283 rmb->mhandle = mb->mhandle;
1289 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1291 MonoDynamicTable *table;
1294 ReflectionMethodBuilder rmb;
1297 reflection_methodbuilder_from_method_builder (&rmb, mb);
1299 mono_image_basic_method (&rmb, assembly);
1301 if (mb->dll) { /* It's a P/Invoke method */
1303 int charset = mb->charset & 0xf;
1304 int lasterr = mb->charset & 0x40;
1305 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1307 alloc_table (table, table->rows);
1308 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1309 /* map CharSet values to on-disk values */
1311 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1312 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1313 name = mono_string_to_utf8 (mb->dllentry);
1314 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1316 name = mono_string_to_utf8 (mb->dll);
1317 moduleref = string_heap_insert (&assembly->sheap, name);
1319 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1320 table = &assembly->tables [MONO_TABLE_MODULEREF];
1322 alloc_table (table, table->rows);
1323 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1324 values [MONO_IMPLMAP_SCOPE] = table->rows;
1328 if (mb->override_method) {
1329 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1331 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1333 alloc_table (table, table->rows);
1334 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1335 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1336 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1337 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1338 switch (mono_metadata_token_table (tok)) {
1339 case MONO_TABLE_MEMBERREF:
1340 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1342 case MONO_TABLE_METHOD:
1343 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1346 g_assert_not_reached ();
1348 values [MONO_METHODIMPL_DECLARATION] = tok;
1351 if (mb->generic_params) {
1352 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1353 table->rows += mono_array_length (mb->generic_params);
1354 alloc_table (table, table->rows);
1355 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1356 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1358 mono_image_get_generic_param_info (
1359 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1366 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1368 ReflectionMethodBuilder rmb;
1370 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1372 mono_image_basic_method (&rmb, assembly);
1376 type_get_fully_qualified_name (MonoType *type) {
1377 char *name, *result;
1381 name = mono_type_get_name (type);
1382 klass = my_mono_class_from_mono_type (type);
1383 ta = klass->image->assembly;
1385 /* missing public key */
1386 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1387 name, ta->aname.name,
1388 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1389 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
1395 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1399 klass = my_mono_class_from_mono_type (type);
1400 ta = klass->image->assembly;
1401 if (ta == ass || klass->image == mono_defaults.corlib)
1402 return mono_type_get_name (type);
1404 return type_get_fully_qualified_name (type);
1408 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1410 char blob_size [64];
1411 char *b = blob_size;
1416 if (!assembly->save)
1419 p = buf = g_malloc (64);
1421 mono_metadata_encode_value (0x06, p, &p);
1422 /* encode custom attributes before the type */
1423 encode_type (assembly, type, p, &p);
1424 g_assert (p-buf < 64);
1425 mono_metadata_encode_value (p-buf, b, &b);
1426 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1432 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1434 char blob_size [64];
1435 char *b = blob_size;
1440 p = buf = g_malloc (64);
1442 mono_metadata_encode_value (0x06, p, &p);
1443 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1444 /* encode custom attributes before the type */
1445 encode_reflection_type (assembly, fb->type, p, &p);
1446 g_assert (p-buf < 64);
1447 mono_metadata_encode_value (p-buf, b, &b);
1448 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1454 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1455 char blob_size [64];
1456 char *b = blob_size;
1459 guint32 idx = 0, len = 0, dummy = 0;
1461 p = buf = g_malloc (64);
1463 *ret_type = MONO_TYPE_CLASS;
1465 box_val = (char*)&dummy;
1467 box_val = ((char*)val) + sizeof (MonoObject);
1468 *ret_type = val->vtable->klass->byval_arg.type;
1471 switch (*ret_type) {
1472 case MONO_TYPE_BOOLEAN:
1477 case MONO_TYPE_CHAR:
1492 case MONO_TYPE_VALUETYPE:
1493 if (val->vtable->klass->enumtype) {
1494 *ret_type = val->vtable->klass->enum_basetype->type;
1497 g_error ("we can't encode valuetypes");
1498 case MONO_TYPE_CLASS:
1500 case MONO_TYPE_STRING: {
1501 MonoString *str = (MonoString*)val;
1502 /* there is no signature */
1503 len = str->length * 2;
1504 mono_metadata_encode_value (len, b, &b);
1505 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1507 char *swapped = g_malloc (2 * mono_string_length (str));
1508 const char *p = (const char*)mono_string_chars (str);
1510 swap_with_size (swapped, p, 2, mono_string_length (str));
1511 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1515 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1522 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1525 /* there is no signature */
1526 mono_metadata_encode_value (len, b, &b);
1527 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1528 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1529 swap_with_size (blob_size, box_val, len, 1);
1530 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1532 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1540 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1541 char blob_size [64];
1542 char *b = blob_size;
1543 char *p, *buf, *str;
1544 guint32 idx, len, bufsize = 256;
1546 p = buf = g_malloc (bufsize);
1548 switch (minfo->type) {
1549 case MONO_NATIVE_BYVALTSTR:
1550 case MONO_NATIVE_BYVALARRAY:
1551 mono_metadata_encode_value (minfo->type, p, &p);
1552 mono_metadata_encode_value (minfo->count, p, &p);
1554 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1555 case MONO_NATIVE_CUSTOM:
1556 mono_metadata_encode_value (minfo->type, p, &p);
1558 str = mono_string_to_utf8 (minfo->guid);
1560 mono_metadata_encode_value (len, p, &p);
1561 memcpy (p, str, len);
1565 mono_metadata_encode_value (0, p, &p);
1567 if (minfo->marshaltype) {
1568 str = mono_string_to_utf8 (minfo->marshaltype);
1570 mono_metadata_encode_value (len, p, &p);
1571 if (p + len >= buf + bufsize) {
1574 buf = g_realloc (buf, bufsize);
1577 memcpy (p, str, len);
1581 mono_metadata_encode_value (0, p, &p);
1583 if (minfo->marshaltyperef) {
1584 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1586 mono_metadata_encode_value (len, p, &p);
1587 if (p + len >= buf + bufsize) {
1590 buf = g_realloc (buf, bufsize);
1593 memcpy (p, str, len);
1597 mono_metadata_encode_value (0, p, &p);
1599 if (minfo->mcookie) {
1600 str = mono_string_to_utf8 (minfo->mcookie);
1602 mono_metadata_encode_value (len, p, &p);
1603 if (p + len >= buf + bufsize) {
1606 buf = g_realloc (buf, bufsize);
1609 memcpy (p, str, len);
1613 mono_metadata_encode_value (0, p, &p);
1617 mono_metadata_encode_value (minfo->type, p, &p);
1621 mono_metadata_encode_value (len, b, &b);
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1628 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1630 MonoDynamicTable *table;
1634 /* maybe this fixup should be done in the C# code */
1635 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1636 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1637 table = &assembly->tables [MONO_TABLE_FIELD];
1638 fb->table_idx = table->next_idx ++;
1639 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1640 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1641 name = mono_string_to_utf8 (fb->name);
1642 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1644 values [MONO_FIELD_FLAGS] = fb->attrs;
1645 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1647 if (fb->offset != -1) {
1648 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1650 alloc_table (table, table->rows);
1651 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1652 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1653 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1655 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1656 guint32 field_type = 0;
1657 table = &assembly->tables [MONO_TABLE_CONSTANT];
1659 alloc_table (table, table->rows);
1660 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1661 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1662 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1663 values [MONO_CONSTANT_TYPE] = field_type;
1664 values [MONO_CONSTANT_PADDING] = 0;
1666 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1668 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1670 alloc_table (table, table->rows);
1671 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1672 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1674 * We store it in the code section because it's simpler for now.
1677 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1679 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1680 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1682 if (fb->marshal_info) {
1683 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1685 alloc_table (table, table->rows);
1686 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1687 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1688 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1693 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1697 char *b = blob_size;
1698 guint32 nparams = 0;
1699 MonoReflectionMethodBuilder *mb = fb->get_method;
1700 MonoReflectionMethodBuilder *smb = fb->set_method;
1701 guint32 idx, i, size;
1703 if (mb && mb->parameters)
1704 nparams = mono_array_length (mb->parameters);
1705 if (!mb && smb && smb->parameters)
1706 nparams = mono_array_length (smb->parameters) - 1;
1707 size = 24 + nparams * 10;
1708 buf = p = g_malloc (size);
1711 mono_metadata_encode_value (nparams, p, &p);
1713 encode_reflection_type (assembly, mb->rtype, p, &p);
1714 for (i = 0; i < nparams; ++i) {
1715 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1716 encode_reflection_type (assembly, pt, p, &p);
1719 /* the property type is the last param */
1720 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1721 for (i = 0; i < nparams; ++i) {
1722 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1723 encode_reflection_type (assembly, pt, p, &p);
1727 g_assert (p - buf < size);
1728 mono_metadata_encode_value (p-buf, b, &b);
1729 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1735 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1737 MonoDynamicTable *table;
1740 guint num_methods = 0;
1744 * we need to set things in the following tables:
1745 * PROPERTYMAP (info already filled in _get_type_info ())
1746 * PROPERTY (rows already preallocated in _get_type_info ())
1747 * METHOD (method info already done with the generic method code)
1750 table = &assembly->tables [MONO_TABLE_PROPERTY];
1751 pb->table_idx = table->next_idx ++;
1752 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1753 name = mono_string_to_utf8 (pb->name);
1754 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1756 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1757 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1759 /* FIXME: we still don't handle 'other' methods */
1760 if (pb->get_method) num_methods ++;
1761 if (pb->set_method) num_methods ++;
1763 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1764 table->rows += num_methods;
1765 alloc_table (table, table->rows);
1767 if (pb->get_method) {
1768 semaidx = table->next_idx ++;
1769 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1770 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1771 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1772 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1774 if (pb->set_method) {
1775 semaidx = table->next_idx ++;
1776 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1777 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1778 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1779 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1784 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1786 MonoDynamicTable *table;
1789 guint num_methods = 0;
1793 * we need to set things in the following tables:
1794 * EVENTMAP (info already filled in _get_type_info ())
1795 * EVENT (rows already preallocated in _get_type_info ())
1796 * METHOD (method info already done with the generic method code)
1799 table = &assembly->tables [MONO_TABLE_EVENT];
1800 eb->table_idx = table->next_idx ++;
1801 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1802 name = mono_string_to_utf8 (eb->name);
1803 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1805 values [MONO_EVENT_FLAGS] = eb->attrs;
1806 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1809 * FIXME: we still don't handle 'other' methods
1811 if (eb->add_method) num_methods ++;
1812 if (eb->remove_method) num_methods ++;
1813 if (eb->raise_method) num_methods ++;
1815 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1816 table->rows += num_methods;
1817 alloc_table (table, table->rows);
1819 if (eb->add_method) {
1820 semaidx = table->next_idx ++;
1821 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1822 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1823 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1824 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1826 if (eb->remove_method) {
1827 semaidx = table->next_idx ++;
1828 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1829 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1830 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1831 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1833 if (eb->raise_method) {
1834 semaidx = table->next_idx ++;
1835 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1836 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1837 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1838 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1843 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1845 static MonoClass *NewConstraintAttr;
1846 static MonoMethod *NewConstraintAttr_ctor;
1847 MonoDynamicTable *table;
1849 guint32 token, type;
1850 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1853 if (!NewConstraintAttr)
1854 NewConstraintAttr = mono_class_from_name (
1855 mono_defaults.corlib, "System.Runtime.CompilerServices",
1856 "NewConstraintAttribute");
1857 g_assert (NewConstraintAttr);
1859 if (!NewConstraintAttr_ctor) {
1862 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1863 MonoMethod *m = NewConstraintAttr->methods [i];
1865 if (strcmp (m->name, ".ctor"))
1868 NewConstraintAttr_ctor = m;
1872 g_assert (NewConstraintAttr_ctor);
1875 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1877 alloc_table (table, table->rows);
1879 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1880 owner <<= CUSTOM_ATTR_BITS;
1881 owner |= CUSTOM_ATTR_GENERICPAR;
1882 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1884 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1886 type = mono_metadata_token_index (token);
1887 type <<= CUSTOM_ATTR_TYPE_BITS;
1888 switch (mono_metadata_token_table (token)) {
1889 case MONO_TABLE_METHOD:
1890 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1892 case MONO_TABLE_MEMBERREF:
1893 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1896 g_warning ("got wrong token in custom attr");
1899 values [MONO_CUSTOM_ATTR_TYPE] = type;
1901 buf = p = g_malloc (1);
1902 mono_metadata_encode_value (4, p, &p);
1903 g_assert (p-buf == 1);
1905 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1907 values += MONO_CUSTOM_ATTR_SIZE;
1912 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1914 MonoDynamicTable *table;
1915 guint32 num_constraints, i;
1919 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1920 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1921 table->rows += num_constraints;
1922 alloc_table (table, table->rows);
1924 for (i = 0; i < num_constraints; i++) {
1925 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1927 table_idx = table->next_idx ++;
1928 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1930 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1931 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1934 if (gparam->has_ctor_constraint)
1935 encode_new_constraint (assembly, owner);
1939 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1941 MonoDynamicTable *table;
1942 MonoGenericParam *param;
1946 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1947 table_idx = table->next_idx ++;
1948 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1950 param = gparam->type.type->data.generic_param;
1952 values [MONO_GENERICPARAM_OWNER] = owner;
1953 values [MONO_GENERICPARAM_FLAGS] = param->flags;
1954 values [MONO_GENERICPARAM_NUMBER] = param->num;
1955 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1956 values [MONO_GENERICPARAM_KIND] = 0;
1957 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1959 if (gparam->constraints)
1960 encode_constraints (gparam, table_idx, assembly);
1964 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1966 MonoDynamicTable *table;
1969 guint32 cols [MONO_ASSEMBLY_SIZE];
1973 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1976 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1977 table = &assembly->tables [MONO_TABLE_MODULEREF];
1978 token = table->next_idx ++;
1980 alloc_table (table, table->rows);
1981 values = table->values + token * MONO_MODULEREF_SIZE;
1982 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1984 token <<= RESOLTION_SCOPE_BITS;
1985 token |= RESOLTION_SCOPE_MODULEREF;
1986 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1991 if (image->assembly->dynamic)
1993 memset (cols, 0, sizeof (cols));
1995 /* image->assembly->image is the manifest module */
1996 image = image->assembly->image;
1997 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2000 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2001 token = table->next_idx ++;
2003 alloc_table (table, table->rows);
2004 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2005 if (strcmp ("corlib", image->assembly_name) == 0)
2006 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
2008 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2009 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2010 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2011 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2012 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2013 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2014 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2015 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2017 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2018 guchar pubtoken [9];
2020 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2021 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2024 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2025 * This is currently only a problem with references to System.Xml (see bug#27706),
2026 * but there may be other cases that makes this necessary. Note, we need to set
2027 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
2028 * recognized by ms, yuck!
2029 * FIXME: need to add more assembly names, as needed.
2031 if (strcmp (image->assembly_name, "corlib") == 0 ||
2032 strcmp (image->assembly_name, "mscorlib") == 0 ||
2033 strcmp (image->assembly_name, "System") == 0 ||
2034 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2035 strcmp (image->assembly_name, "System.Xml") == 0 ||
2036 strcmp (image->assembly_name, "System.Data") == 0 ||
2037 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2038 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2039 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2040 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2041 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2042 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2043 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2044 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2045 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2046 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2047 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2048 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2049 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2050 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2051 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2052 strcmp (image->assembly_name, "System.Design") == 0 ||
2053 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2054 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2055 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2056 strcmp (image->assembly_name, "System.Management") == 0 ||
2057 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2058 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2059 strcmp (image->assembly_name, "System.Security") == 0 ||
2060 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2061 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2062 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2063 strcmp (image->assembly_name, "System.Web") == 0) {
2064 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2065 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2066 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2067 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2069 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2072 token <<= RESOLTION_SCOPE_BITS;
2073 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2074 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2079 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2081 MonoDynamicTable *table;
2087 char *b = blob_size;
2089 switch (type->type) {
2090 case MONO_TYPE_FNPTR:
2092 case MONO_TYPE_SZARRAY:
2093 case MONO_TYPE_ARRAY:
2095 case MONO_TYPE_MVAR:
2096 case MONO_TYPE_GENERICINST:
2097 encode_type (assembly, type, p, &p);
2099 case MONO_TYPE_CLASS:
2100 case MONO_TYPE_VALUETYPE: {
2101 MonoClass *k = mono_class_from_mono_type (type);
2102 if (!k || !k->generic_inst)
2104 encode_generic_inst (assembly, k->generic_inst, p, &p);
2111 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2112 if (assembly->save) {
2113 g_assert (p-sig < 128);
2114 mono_metadata_encode_value (p-sig, b, &b);
2115 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2116 alloc_table (table, table->rows + 1);
2117 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2118 values [MONO_TYPESPEC_SIGNATURE] = token;
2121 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2122 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2128 * Despite the name, we handle also TypeSpec (with the above helper).
2131 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2133 MonoDynamicTable *table;
2135 guint32 token, scope, enclosing;
2138 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2141 token = create_typespec (assembly, type);
2144 klass = my_mono_class_from_mono_type (type);
2146 klass = mono_class_from_mono_type (type);
2149 * If it's in the same module and not a generic type parameter:
2151 if ((klass->image == &assembly->image) &&
2152 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2153 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2154 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2155 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2159 if (klass->nested_in) {
2160 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2161 /* get the typeref idx of the enclosing type */
2162 enclosing >>= TYPEDEFORREF_BITS;
2163 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2165 scope = resolution_scope_from_image (assembly, klass->image);
2167 table = &assembly->tables [MONO_TABLE_TYPEREF];
2168 if (assembly->save) {
2169 alloc_table (table, table->rows + 1);
2170 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2171 values [MONO_TYPEREF_SCOPE] = scope;
2172 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2173 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2175 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2176 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2178 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2183 * Insert a memberef row into the metadata: the token that point to the memberref
2184 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2185 * mono_image_get_fieldref_token()).
2186 * The sig param is an index to an already built signature.
2189 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2191 MonoDynamicTable *table;
2193 guint32 token, pclass;
2196 parent = mono_image_typedef_or_ref (assembly, type);
2197 switch (parent & TYPEDEFORREF_MASK) {
2198 case TYPEDEFORREF_TYPEREF:
2199 pclass = MEMBERREF_PARENT_TYPEREF;
2201 case TYPEDEFORREF_TYPESPEC:
2202 pclass = MEMBERREF_PARENT_TYPESPEC;
2204 case TYPEDEFORREF_TYPEDEF:
2205 pclass = MEMBERREF_PARENT_TYPEDEF;
2208 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2211 /* extract the index */
2212 parent >>= TYPEDEFORREF_BITS;
2214 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2216 if (assembly->save) {
2217 alloc_table (table, table->rows + 1);
2218 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2219 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2220 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2221 values [MONO_MEMBERREF_SIGNATURE] = sig;
2224 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2231 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2235 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2238 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2239 method->name, method_encode_signature (assembly, method->signature));
2240 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2245 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2248 ReflectionMethodBuilder rmb;
2250 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2254 reflection_methodbuilder_from_method_builder (&rmb, mb);
2256 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2257 mono_string_to_utf8 (rmb.name),
2258 method_builder_encode_signature (assembly, &rmb));
2259 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2264 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2267 ReflectionMethodBuilder rmb;
2269 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2273 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2275 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2276 mono_string_to_utf8 (rmb.name),
2277 method_builder_encode_signature (assembly, &rmb));
2278 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2283 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2288 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2291 g_assert (f->field->parent);
2292 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2293 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2294 f->field->name, fieldref_encode_signature (assembly, type));
2295 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2300 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2305 guint32 nparams = gmethod->mtype_argc;
2306 guint32 size = 10 + nparams * 10;
2309 char *b = blob_size;
2311 if (!assembly->save)
2314 p = buf = g_malloc (size);
2316 * FIXME: vararg, explicit_this, differenc call_conv values...
2318 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2319 mono_metadata_encode_value (nparams, p, &p);
2321 for (i = 0; i < nparams; i++)
2322 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2325 g_assert (p - buf < size);
2326 mono_metadata_encode_value (p-buf, b, &b);
2327 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2333 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2335 MonoDynamicTable *table;
2337 guint32 token, mtoken = 0, sig;
2338 MonoMethodInflated *imethod;
2339 MonoMethod *declaring;
2341 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2343 g_assert (method->signature->is_inflated);
2344 imethod = (MonoMethodInflated *) method;
2345 declaring = imethod->declaring;
2347 sig = method_encode_signature (assembly, declaring->signature);
2348 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2349 declaring->name, sig);
2351 if (!declaring->signature->generic_param_count)
2354 switch (mono_metadata_token_table (mtoken)) {
2355 case MONO_TABLE_MEMBERREF:
2356 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2358 case MONO_TABLE_METHOD:
2359 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2362 g_assert_not_reached ();
2365 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2367 if (assembly->save) {
2368 alloc_table (table, table->rows + 1);
2369 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2370 values [MONO_METHODSPEC_METHOD] = mtoken;
2371 values [MONO_METHODSPEC_SIGNATURE] = sig;
2374 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2381 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2383 MonoMethodInflated *imethod;
2386 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2390 g_assert (m->signature->is_inflated);
2391 imethod = (MonoMethodInflated *) m;
2393 if (imethod->declaring->signature->generic_param_count)
2394 token = method_encode_methodspec (assembly, m);
2396 guint32 sig = method_encode_signature (
2397 assembly, imethod->declaring->signature);
2398 token = mono_image_get_memberref_token (
2399 assembly, &m->klass->byval_arg, m->name, sig);
2402 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2407 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2409 MonoDynamicTable *table;
2416 char *b = blob_size;
2419 g_assert (tb->generic_params);
2420 klass = mono_class_from_mono_type (tb->type.type);
2422 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2423 encode_type (assembly, &klass->byval_arg, p, &p);
2425 count = mono_array_length (tb->generic_params);
2426 mono_metadata_encode_value (count, p, &p);
2427 for (i = 0; i < count; i++) {
2428 MonoReflectionGenericParam *gparam;
2430 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2432 encode_type (assembly, gparam->type.type, p, &p);
2435 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2436 if (assembly->save) {
2437 g_assert (p-sig < 128);
2438 mono_metadata_encode_value (p-sig, b, &b);
2439 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2440 alloc_table (table, table->rows + 1);
2441 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2442 values [MONO_TYPESPEC_SIGNATURE] = token;
2445 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2446 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2452 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2454 MonoDynamicTable *table;
2457 guint32 token, pclass, parent, sig;
2460 klass = mono_class_from_mono_type (fb->typeb->type);
2461 name = mono_string_to_utf8 (fb->name);
2463 sig = fieldref_encode_signature (assembly, fb->type->type);
2465 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2466 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2468 pclass = MEMBERREF_PARENT_TYPESPEC;
2469 parent >>= TYPEDEFORREF_BITS;
2471 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2473 if (assembly->save) {
2474 alloc_table (table, table->rows + 1);
2475 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2476 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2477 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2478 values [MONO_MEMBERREF_SIGNATURE] = sig;
2481 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2488 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2496 char *b = blob_size;
2498 if (!assembly->save)
2502 g_assert (helper->type == 2);
2504 if (helper->arguments)
2505 nargs = mono_array_length (helper->arguments);
2509 size = 10 + (nargs * 10);
2511 p = buf = g_malloc (size);
2513 /* Encode calling convention */
2514 /* Change Any to Standard */
2515 if ((helper->call_conv & 0x03) == 0x03)
2516 helper->call_conv = 0x01;
2517 /* explicit_this implies has_this */
2518 if (helper->call_conv & 0x40)
2519 helper->call_conv &= 0x20;
2521 if (helper->call_conv == 0) /* Unmanaged */
2522 *p = helper->unmanaged_call_conv - 1;
2525 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2526 if (helper->call_conv & 0x02) /* varargs */
2531 mono_metadata_encode_value (nargs, p, &p);
2532 encode_reflection_type (assembly, helper->return_type, p, &p);
2533 for (i = 0; i < nargs; ++i) {
2534 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2535 encode_reflection_type (assembly, pt, p, &p);
2538 g_assert (p - buf < size);
2539 mono_metadata_encode_value (p-buf, b, &b);
2540 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2547 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2550 MonoDynamicTable *table;
2553 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2554 idx = table->next_idx ++;
2556 alloc_table (table, table->rows);
2557 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2559 values [MONO_STAND_ALONE_SIGNATURE] =
2560 mono_reflection_encode_sighelper (assembly, helper);
2566 reflection_cc_to_file (int call_conv) {
2567 switch (call_conv & 0x3) {
2569 case 1: return MONO_CALL_DEFAULT;
2570 case 2: return MONO_CALL_VARARG;
2572 g_assert_not_reached ();
2579 MonoMethodSignature *sig;
2585 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2590 MonoMethodSignature *sig;
2593 name = mono_string_to_utf8 (m->name);
2594 nparams = mono_array_length (m->parameters);
2595 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2597 sig->call_convention = reflection_cc_to_file (m->call_conv);
2598 sig->param_count = nparams;
2599 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2600 for (i = 0; i < nparams; ++i) {
2601 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2602 sig->params [i] = t->type;
2605 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2607 if (strcmp (name, am->name) == 0 &&
2608 mono_metadata_type_equal (am->parent, m->parent->type) &&
2609 mono_metadata_signature_equal (am->sig, sig)) {
2612 m->table_idx = am->token & 0xffffff;
2616 am = g_new0 (ArrayMethod, 1);
2619 am->parent = m->parent->type;
2620 am->token = mono_image_get_memberref_token (assembly, am->parent,
2621 name, method_encode_signature (assembly, sig));
2622 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2623 m->table_idx = am->token & 0xffffff;
2628 * Insert into the metadata tables all the info about the TypeBuilder tb.
2629 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2632 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2634 MonoDynamicTable *table;
2636 int i, is_object = 0, is_system = 0;
2639 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2640 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2641 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2642 n = mono_string_to_utf8 (tb->name);
2643 if (strcmp (n, "Object") == 0)
2645 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2647 n = mono_string_to_utf8 (tb->nspace);
2648 if (strcmp (n, "System") == 0)
2650 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2652 if (tb->parent && !(is_system && is_object) &&
2653 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2654 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2656 values [MONO_TYPEDEF_EXTENDS] = 0;
2657 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2658 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2661 * if we have explicitlayout or sequentiallayouts, output data in the
2662 * ClassLayout table.
2664 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2665 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2667 alloc_table (table, table->rows);
2668 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2669 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2670 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2671 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2674 /* handle interfaces */
2675 if (tb->interfaces) {
2676 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2678 table->rows += mono_array_length (tb->interfaces);
2679 alloc_table (table, table->rows);
2680 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2681 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2682 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2683 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2684 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2685 values += MONO_INTERFACEIMPL_SIZE;
2689 /* handle generic parameters */
2690 if (tb->generic_params) {
2691 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2692 table->rows += mono_array_length (tb->generic_params);
2693 alloc_table (table, table->rows);
2694 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2695 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2697 mono_image_get_generic_param_info (
2698 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2704 table = &assembly->tables [MONO_TABLE_FIELD];
2705 table->rows += tb->num_fields;
2706 alloc_table (table, table->rows);
2707 for (i = 0; i < tb->num_fields; ++i)
2708 mono_image_get_field_info (
2709 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2712 /* handle constructors */
2714 table = &assembly->tables [MONO_TABLE_METHOD];
2715 table->rows += mono_array_length (tb->ctors);
2716 alloc_table (table, table->rows);
2717 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2718 mono_image_get_ctor_info (domain,
2719 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2722 /* handle methods */
2724 table = &assembly->tables [MONO_TABLE_METHOD];
2725 table->rows += tb->num_methods;
2726 alloc_table (table, table->rows);
2727 for (i = 0; i < tb->num_methods; ++i)
2728 mono_image_get_method_info (
2729 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2732 /* Do the same with properties etc.. */
2733 if (tb->events && mono_array_length (tb->events)) {
2734 table = &assembly->tables [MONO_TABLE_EVENT];
2735 table->rows += mono_array_length (tb->events);
2736 alloc_table (table, table->rows);
2737 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2739 alloc_table (table, table->rows);
2740 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2741 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2742 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2743 for (i = 0; i < mono_array_length (tb->events); ++i)
2744 mono_image_get_event_info (
2745 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2747 if (tb->properties && mono_array_length (tb->properties)) {
2748 table = &assembly->tables [MONO_TABLE_PROPERTY];
2749 table->rows += mono_array_length (tb->properties);
2750 alloc_table (table, table->rows);
2751 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2753 alloc_table (table, table->rows);
2754 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2755 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2756 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2757 for (i = 0; i < mono_array_length (tb->properties); ++i)
2758 mono_image_get_property_info (
2759 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2762 mono_image_add_decl_security (assembly,
2763 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2767 MonoDynamicTable *ntable;
2769 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2770 ntable->rows += mono_array_length (tb->subtypes);
2771 alloc_table (ntable, ntable->rows);
2772 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2774 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2775 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2777 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2778 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2779 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2780 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2781 mono_string_to_utf8 (tb->name), tb->table_idx,
2782 ntable->next_idx, ntable->rows);*/
2783 values += MONO_NESTED_CLASS_SIZE;
2790 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2794 g_ptr_array_add (types, type);
2796 if (!type->subtypes)
2799 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2800 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2801 collect_types (types, subtype);
2806 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2807 MonoReflectionTypeBuilder **type2)
2809 if ((*type1)->table_idx < (*type2)->table_idx)
2812 if ((*type1)->table_idx > (*type2)->table_idx)
2819 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2824 for (i = 0; i < mono_array_length (pinfo); ++i) {
2825 MonoReflectionParamBuilder *pb;
2826 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2829 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2834 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2837 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2839 for (i = 0; i < tb->num_fields; ++i) {
2840 MonoReflectionFieldBuilder* fb;
2841 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2842 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2846 for (i = 0; i < mono_array_length (tb->events); ++i) {
2847 MonoReflectionEventBuilder* eb;
2848 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2849 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2852 if (tb->properties) {
2853 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2854 MonoReflectionPropertyBuilder* pb;
2855 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2856 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2860 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2861 MonoReflectionCtorBuilder* cb;
2862 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2863 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2864 params_add_cattrs (assembly, cb->pinfo);
2869 for (i = 0; i < tb->num_methods; ++i) {
2870 MonoReflectionMethodBuilder* mb;
2871 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2872 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2873 params_add_cattrs (assembly, mb->pinfo);
2878 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2879 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2884 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2887 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2889 /* no types in the module */
2893 for (i = 0; i < mb->num_types; ++i)
2894 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2898 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2899 MonoDynamicImage *assembly)
2901 MonoDynamicTable *table;
2905 char *b = blob_size;
2908 table = &assembly->tables [MONO_TABLE_FILE];
2910 alloc_table (table, table->rows);
2911 values = table->values + table->next_idx * MONO_FILE_SIZE;
2912 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2913 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2914 if (module->image->dynamic) {
2915 /* This depends on the fact that the main module is emitted last */
2916 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2917 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2921 path = g_strdup (module->image->name);
2923 mono_sha1_get_digest_from_file (path, hash);
2926 mono_metadata_encode_value (20, b, &b);
2927 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2928 mono_image_add_stream_data (&assembly->blob, hash, 20);
2933 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2935 MonoDynamicTable *table;
2939 table = &assembly->tables [MONO_TABLE_MODULE];
2940 mb->table_idx = table->next_idx ++;
2941 name = mono_string_to_utf8 (mb->module.name);
2942 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2944 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2947 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2948 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2949 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2953 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2954 guint32 module_index, guint32 parent_index,
2955 MonoDynamicImage *assembly)
2957 MonoDynamicTable *table;
2961 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2962 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2965 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2967 alloc_table (table, table->rows);
2968 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2970 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2971 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2972 if (klass->nested_in)
2973 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2975 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2976 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2977 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2979 res = table->next_idx;
2983 /* Emit nested types */
2984 if (klass->nested_classes) {
2987 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2988 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2995 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2996 guint32 module_index, guint32 parent_index,
2997 MonoDynamicImage *assembly)
3002 klass = mono_class_from_mono_type (tb->type.type);
3004 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3006 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3007 parent_index, assembly);
3011 * We need to do this ourselves since klass->nested_classes is not set up.
3014 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3015 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3020 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3021 guint32 module_index,
3022 MonoDynamicImage *assembly)
3024 MonoImage *image = module->image;
3028 t = &image->tables [MONO_TABLE_TYPEDEF];
3030 for (i = 0; i < t->rows; ++i) {
3031 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3033 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3034 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3038 #define align_pointer(base,p)\
3040 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3042 (p) += 4 - (__diff & 3);\
3046 compare_semantics (const void *a, const void *b)
3048 const guint32 *a_values = a;
3049 const guint32 *b_values = b;
3050 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3053 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3057 compare_custom_attrs (const void *a, const void *b)
3059 const guint32 *a_values = a;
3060 const guint32 *b_values = b;
3062 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3066 compare_field_marshal (const void *a, const void *b)
3068 const guint32 *a_values = a;
3069 const guint32 *b_values = b;
3071 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3075 compare_nested (const void *a, const void *b)
3077 const guint32 *a_values = a;
3078 const guint32 *b_values = b;
3080 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3084 * build_compressed_metadata() fills in the blob of data that represents the
3085 * raw metadata as it will be saved in the PE file. The five streams are output
3086 * and the metadata tables are comnpressed from the guint32 array representation,
3087 * to the compressed on-disk format.
3090 build_compressed_metadata (MonoDynamicImage *assembly)
3092 MonoDynamicTable *table;
3094 guint64 valid_mask = 0;
3095 guint64 sorted_mask;
3096 guint32 heapt_size = 0;
3097 guint32 meta_size = 256; /* allow for header and other stuff */
3098 guint32 table_offset;
3099 guint32 ntables = 0;
3108 MonoDynamicStream *stream;
3111 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3112 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3113 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3114 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3115 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3117 /* tables that are sorted */
3118 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3119 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3120 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3121 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3122 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3123 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3125 /* Compute table sizes */
3126 /* the MonoImage has already been created in mono_image_basic_init() */
3127 meta = &assembly->image;
3129 /* Setup the info used by compute_sizes () */
3130 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3131 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3132 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3134 meta_size += assembly->blob.index;
3135 meta_size += assembly->guid.index;
3136 meta_size += assembly->sheap.index;
3137 meta_size += assembly->us.index;
3139 for (i=0; i < 64; ++i)
3140 meta->tables [i].rows = assembly->tables [i].rows;
3142 for (i = 0; i < 64; i++){
3143 if (meta->tables [i].rows == 0)
3145 valid_mask |= (guint64)1 << i;
3147 meta->tables [i].row_size = mono_metadata_compute_size (
3148 meta, i, &meta->tables [i].size_bitfield);
3149 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3151 heapt_size += 24; /* #~ header size */
3152 heapt_size += ntables * 4;
3153 meta_size += heapt_size;
3154 meta->raw_metadata = g_malloc0 (meta_size);
3155 p = meta->raw_metadata;
3156 /* the metadata signature */
3157 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3158 /* version numbers and 4 bytes reserved */
3159 int16val = (guint16*)p;
3160 *int16val++ = GUINT16_TO_LE (1);
3161 *int16val = GUINT16_TO_LE (1);
3163 /* version string */
3164 int32val = (guint32*)p;
3165 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3167 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3168 p += GUINT32_FROM_LE (*int32val);
3169 align_pointer (meta->raw_metadata, p);
3170 int16val = (guint16*)p;
3171 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3172 *int16val = GUINT16_TO_LE (5); /* number of streams */
3176 * write the stream info.
3178 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3179 table_offset += 3; table_offset &= ~3;
3181 assembly->tstream.index = heapt_size;
3182 for (i = 0; i < 5; ++i) {
3183 int32val = (guint32*)p;
3184 stream_desc [i].stream->offset = table_offset;
3185 *int32val++ = GUINT32_TO_LE (table_offset);
3186 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3187 table_offset += GUINT32_FROM_LE (*int32val);
3188 table_offset += 3; table_offset &= ~3;
3190 strcpy (p, stream_desc [i].name);
3191 p += strlen (stream_desc [i].name) + 1;
3192 align_pointer (meta->raw_metadata, p);
3195 * now copy the data, the table stream header and contents goes first.
3197 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3198 p = meta->raw_metadata + assembly->tstream.offset;
3199 int32val = (guint32*)p;
3200 *int32val = GUINT32_TO_LE (0); /* reserved */
3202 *p++ = 1; /* version */
3204 if (meta->idx_string_wide)
3206 if (meta->idx_guid_wide)
3208 if (meta->idx_blob_wide)
3211 *p++ = 0; /* reserved */
3212 int64val = (guint64*)p;
3213 *int64val++ = GUINT64_TO_LE (valid_mask);
3214 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3216 int32val = (guint32*)p;
3217 for (i = 0; i < 64; i++){
3218 if (meta->tables [i].rows == 0)
3220 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3222 p = (unsigned char*)int32val;
3224 /* sort the tables that still need sorting */
3225 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3227 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3228 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3230 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3231 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3233 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3234 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3236 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3238 /* compress the tables */
3239 for (i = 0; i < 64; i++){
3242 guint32 bitfield = meta->tables [i].size_bitfield;
3243 if (!meta->tables [i].rows)
3245 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3246 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3247 meta->tables [i].base = p;
3248 for (row = 1; row <= meta->tables [i].rows; ++row) {
3249 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3250 for (col = 0; col < assembly->tables [i].columns; ++col) {
3251 switch (mono_metadata_table_size (bitfield, col)) {
3253 *p++ = values [col];
3256 *p++ = values [col] & 0xff;
3257 *p++ = (values [col] >> 8) & 0xff;
3260 *p++ = values [col] & 0xff;
3261 *p++ = (values [col] >> 8) & 0xff;
3262 *p++ = (values [col] >> 16) & 0xff;
3263 *p++ = (values [col] >> 24) & 0xff;
3266 g_assert_not_reached ();
3270 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3273 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3274 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3275 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3276 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3277 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3279 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3283 * Some tables in metadata need to be sorted according to some criteria, but
3284 * when methods and fields are first created with reflection, they may be assigned a token
3285 * that doesn't correspond to the final token they will get assigned after the sorting.
3286 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3287 * with the reflection objects that represent them. Once all the tables are set up, the
3288 * reflection objects will contains the correct table index. fixup_method() will fixup the
3289 * tokens for the method with ILGenerator @ilgen.
3292 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3293 guint32 code_idx = GPOINTER_TO_UINT (value);
3294 MonoReflectionILTokenInfo *iltoken;
3295 MonoReflectionFieldBuilder *field;
3296 MonoReflectionCtorBuilder *ctor;
3297 MonoReflectionMethodBuilder *method;
3298 MonoReflectionTypeBuilder *tb;
3299 MonoReflectionArrayMethod *am;
3301 unsigned char *target;
3303 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3304 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3305 target = assembly->code.data + code_idx + iltoken->code_pos;
3306 switch (target [3]) {
3307 case MONO_TABLE_FIELD:
3308 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3309 field = (MonoReflectionFieldBuilder *)iltoken->member;
3310 idx = field->table_idx;
3311 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3312 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3313 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3315 g_assert_not_reached ();
3318 case MONO_TABLE_METHOD:
3319 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3320 method = (MonoReflectionMethodBuilder *)iltoken->member;
3321 idx = method->table_idx;
3322 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3323 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3324 idx = ctor->table_idx;
3325 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3326 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3327 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3328 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3330 g_assert_not_reached ();
3333 case MONO_TABLE_TYPEDEF:
3334 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3335 g_assert_not_reached ();
3336 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3337 idx = tb->table_idx;
3339 case MONO_TABLE_MEMBERREF:
3340 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3341 am = (MonoReflectionArrayMethod*)iltoken->member;
3342 idx = am->table_idx;
3343 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3344 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3345 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3346 g_assert (m->klass->generic_inst);
3348 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3350 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3351 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3352 g_assert (f->generic_type);
3355 g_assert_not_reached ();
3358 case MONO_TABLE_METHODSPEC:
3359 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3360 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3361 g_assert (m->signature->generic_param_count);
3364 g_assert_not_reached ();
3368 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3370 target [0] = idx & 0xff;
3371 target [1] = (idx >> 8) & 0xff;
3372 target [2] = (idx >> 16) & 0xff;
3379 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3380 * value is not known when the table is emitted.
3383 fixup_cattrs (MonoDynamicImage *assembly)
3385 MonoDynamicTable *table;
3387 guint32 type, i, idx, token;
3390 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3392 for (i = 0; i < table->rows; ++i) {
3393 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3395 type = values [MONO_CUSTOM_ATTR_TYPE];
3396 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3397 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3398 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3399 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3402 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3403 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3404 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3405 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3412 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3414 MonoDynamicTable *table;
3418 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3420 alloc_table (table, table->rows);
3421 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3422 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3423 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3424 name = mono_string_to_utf8 (rsrc->name);
3425 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3427 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3432 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3434 MonoDynamicTable *table;
3438 char *b = blob_size;
3440 guint32 idx, offset;
3442 if (rsrc->filename) {
3443 name = mono_string_to_utf8 (rsrc->filename);
3444 sname = g_path_get_basename (name);
3446 table = &assembly->tables [MONO_TABLE_FILE];
3448 alloc_table (table, table->rows);
3449 values = table->values + table->next_idx * MONO_FILE_SIZE;
3450 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3451 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3454 mono_sha1_get_digest_from_file (name, hash);
3455 mono_metadata_encode_value (20, b, &b);
3456 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3457 mono_image_add_stream_data (&assembly->blob, hash, 20);
3459 idx = table->next_idx++;
3461 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3464 offset = mono_array_length (rsrc->data);
3465 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3466 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3467 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3468 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3472 * The entry should be emitted into the MANIFESTRESOURCE table of
3473 * the main module, but that needs to reference the FILE table
3474 * which isn't emitted yet.
3481 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3485 set_version_from_string (MonoString *version, guint32 *values)
3487 gchar *ver, *p, *str;
3490 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3491 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3492 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3493 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3496 ver = str = mono_string_to_utf8 (version);
3497 for (i = 0; i < 4; ++i) {
3498 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3504 /* handle Revision and Build */
3514 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3518 char *b = blob_size;
3523 len = mono_array_length (pkey);
3524 mono_metadata_encode_value (len, b, &b);
3525 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3526 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3528 /* need to get the actual value from the key type... */
3529 assembly->strong_name_size = 128;
3530 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3536 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3538 MonoDynamicTable *table;
3539 MonoDynamicImage *assembly;
3540 MonoReflectionAssemblyBuilder *assemblyb;
3545 guint32 module_index;
3547 assemblyb = moduleb->assemblyb;
3548 assembly = moduleb->dynamic_image;
3549 domain = mono_object_domain (assemblyb);
3551 /* Emit ASSEMBLY table */
3552 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3553 alloc_table (table, 1);
3554 values = table->values + MONO_ASSEMBLY_SIZE;
3555 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3556 name = mono_string_to_utf8 (assemblyb->name);
3557 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3559 if (assemblyb->culture) {
3560 name = mono_string_to_utf8 (assemblyb->culture);
3561 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3564 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3566 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3567 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3568 set_version_from_string (assemblyb->version, values);
3570 /* Emit FILE + EXPORTED_TYPE table */
3572 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3574 MonoReflectionModuleBuilder *file_module =
3575 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3576 if (file_module != moduleb) {
3577 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3579 if (file_module->types) {
3580 for (j = 0; j < file_module->num_types; ++j) {
3581 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3582 mono_image_fill_export_table (domain, tb, module_index, 0,
3588 if (assemblyb->loaded_modules) {
3589 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3590 MonoReflectionModule *file_module =
3591 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3592 mono_image_fill_file_table (domain, file_module, assembly);
3594 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3598 /* Emit MANIFESTRESOURCE table */
3600 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3602 MonoReflectionModuleBuilder *file_module =
3603 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3604 /* The table for the main module is emitted later */
3605 if (file_module != moduleb) {
3607 if (file_module->resources) {
3608 int len = mono_array_length (file_module->resources);
3609 for (j = 0; j < len; ++j) {
3610 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3611 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3619 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3620 * for the modulebuilder @moduleb.
3621 * At the end of the process, method and field tokens are fixed up and the
3622 * on-disk compressed metadata representation is created.
3625 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3627 MonoDynamicTable *table;
3628 MonoDynamicImage *assembly;
3629 MonoReflectionAssemblyBuilder *assemblyb;
3634 assemblyb = moduleb->assemblyb;
3635 assembly = moduleb->dynamic_image;
3636 domain = mono_object_domain (assemblyb);
3638 if (assembly->text_rva)
3641 assembly->text_rva = START_TEXT_RVA;
3643 if (moduleb->is_main) {
3644 mono_image_emit_manifest (moduleb);
3647 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3648 table->rows = 1; /* .<Module> */
3650 alloc_table (table, table->rows);
3652 * Set the first entry.
3654 values = table->values + table->columns;
3655 values [MONO_TYPEDEF_FLAGS] = 0;
3656 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3657 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3658 values [MONO_TYPEDEF_EXTENDS] = 0;
3659 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3660 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3663 * handle global methods
3664 * FIXME: test what to do when global methods are defined in multiple modules.
3666 if (moduleb->global_methods) {
3667 table = &assembly->tables [MONO_TABLE_METHOD];
3668 table->rows += mono_array_length (moduleb->global_methods);
3669 alloc_table (table, table->rows);
3670 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3671 mono_image_get_method_info (
3672 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3674 if (moduleb->global_fields) {
3675 table = &assembly->tables [MONO_TABLE_FIELD];
3676 table->rows += mono_array_length (moduleb->global_fields);
3677 alloc_table (table, table->rows);
3678 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3679 mono_image_get_field_info (
3680 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3683 table = &assembly->tables [MONO_TABLE_MODULE];
3684 alloc_table (table, 1);
3685 mono_image_fill_module_table (domain, moduleb, assembly);
3689 /* Collect all types into a list sorted by their table_idx */
3690 GPtrArray *types = g_ptr_array_new ();
3693 for (i = 0; i < moduleb->num_types; ++i) {
3694 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3695 collect_types (types, type);
3698 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3699 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3700 table->rows += types->len;
3701 alloc_table (table, table->rows);
3703 for (i = 0; i < types->len; ++i) {
3704 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3705 mono_image_get_type_info (domain, type, assembly);
3707 g_ptr_array_free (types, TRUE);
3711 * table->rows is already set above and in mono_image_fill_module_table.
3713 /* add all the custom attributes at the end, once all the indexes are stable */
3714 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3716 module_add_cattrs (assembly, moduleb);
3719 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3720 fixup_cattrs (assembly);
3724 * mono_image_insert_string:
3725 * @module: module builder object
3728 * Insert @str into the user string stream of @module.
3731 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3733 MonoDynamicImage *assembly;
3738 MONO_ARCH_SAVE_REGS;
3740 if (!module->dynamic_image)
3741 mono_image_module_basic_init (module);
3743 assembly = module->dynamic_image;
3745 if (assembly->save) {
3746 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3747 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3748 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3750 char *swapped = g_malloc (2 * mono_string_length (str));
3751 const char *p = (const char*)mono_string_chars (str);
3753 swap_with_size (swapped, p, 2, mono_string_length (str));
3754 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3758 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3760 mono_image_add_stream_data (&assembly->us, "", 1);
3763 idx = assembly->us.index ++;
3765 mono_g_hash_table_insert (assembly->tokens,
3766 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3768 return MONO_TOKEN_STRING | idx;
3772 * mono_image_create_token:
3773 * @assembly: a dynamic assembly
3776 * Get a token to insert in the IL code stream for the given MemberInfo.
3777 * @obj can be one of:
3778 * ConstructorBuilder
3788 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3793 klass = obj->vtable->klass;
3794 if (strcmp (klass->name, "MethodBuilder") == 0) {
3795 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3797 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3798 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3800 token = mono_image_get_methodbuilder_token (assembly, mb);
3801 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3803 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3804 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3806 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3807 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3809 token = mono_image_get_ctorbuilder_token (assembly, mb);
3810 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3812 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3813 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3814 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3815 if (tb->generic_params) {
3816 token = mono_image_get_generic_field_token (assembly, fb);
3818 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3821 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3822 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3823 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3825 else if (strcmp (klass->name, "MonoType") == 0 ||
3826 strcmp (klass->name, "MonoGenericParam") == 0) {
3827 MonoReflectionType *tb = (MonoReflectionType *)obj;
3828 token = mono_metadata_token_from_dor (
3829 mono_image_typedef_or_ref (assembly, tb->type));
3831 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3832 MonoReflectionType *tb = (MonoReflectionType *)obj;
3833 token = mono_metadata_token_from_dor (
3834 mono_image_typedef_or_ref (assembly, tb->type));
3836 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3837 strcmp (klass->name, "MonoMethod") == 0) {
3838 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3839 if (m->method->signature->is_inflated) {
3840 token = mono_image_get_methodspec_token (assembly, m->method);
3841 } else if (m->method->signature->generic_param_count) {
3842 g_assert_not_reached ();
3843 } else if ((m->method->klass->image == &assembly->image) &&
3844 !m->method->klass->generic_inst) {
3845 static guint32 method_table_idx = 0xffffff;
3847 * Each token should have a unique index, but the indexes are
3848 * assigned by managed code, so we don't know about them. An
3849 * easy solution is to count backwards...
3851 method_table_idx --;
3852 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3854 token = mono_image_get_methodref_token (assembly, m->method);
3855 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3857 else if (strcmp (klass->name, "MonoField") == 0) {
3858 MonoReflectionField *f = (MonoReflectionField *)obj;
3859 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3860 static guint32 field_table_idx = 0xffffff;
3862 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3864 token = mono_image_get_fieldref_token (assembly, f);
3865 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3867 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3868 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3869 token = mono_image_get_array_token (assembly, m);
3871 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3872 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3873 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3876 g_error ("requested token for %s\n", klass->name);
3878 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3885 guint32 import_lookup_table;
3889 guint32 import_address_table_rva;
3897 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3899 static MonoDynamicImage*
3900 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3901 char *assembly_name, char *module_name)
3903 static const guchar entrycode [16] = {0xff, 0x25, 0};
3904 MonoDynamicImage *image;
3908 * We need to use the current ms version or the ms runtime it won't find
3909 * the support dlls. D'oh!
3910 * const char *version = "mono-" VERSION;
3912 const char *version = "v1.0.3705";
3915 image = GC_MALLOC (sizeof (MonoDynamicImage));
3917 image = g_new0 (MonoDynamicImage, 1);
3920 /* keep in sync with image.c */
3921 image->image.name = assembly_name;
3922 image->image.assembly_name = image->image.name; /* they may be different */
3923 image->image.module_name = module_name;
3924 image->image.version = g_strdup (version);
3925 image->image.dynamic = TRUE;
3927 image->image.references = g_new0 (MonoAssembly*, 1);
3928 image->image.references [0] = NULL;
3930 mono_image_init (&image->image);
3932 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3933 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3934 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3935 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3936 image->handleref = g_hash_table_new (NULL, NULL);
3937 image->tokens = mono_g_hash_table_new (NULL, NULL);
3938 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3939 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3941 string_heap_init (&image->sheap);
3942 mono_image_add_stream_data (&image->us, "", 1);
3943 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3944 /* import tables... */
3945 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3946 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3947 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3948 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3949 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3950 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3951 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3952 stream_data_align (&image->code);
3954 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3956 for (i=0; i < 64; ++i) {
3957 image->tables [i].next_idx = 1;
3958 image->tables [i].columns = table_sizes [i];
3961 image->image.assembly = (MonoAssembly*)assembly;
3962 image->run = assembly->run;
3963 image->save = assembly->save;
3969 * mono_image_basic_init:
3970 * @assembly: an assembly builder object
3972 * Create the MonoImage that represents the assembly builder and setup some
3973 * of the helper hash table and the basic metadata streams.
3976 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3978 MonoDynamicAssembly *assembly;
3979 MonoDynamicImage *image;
3981 MONO_ARCH_SAVE_REGS;
3983 if (assemblyb->dynamic_assembly)
3987 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3989 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3992 assembly->assembly.dynamic = TRUE;
3993 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3994 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3995 if (assemblyb->culture)
3996 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3998 assembly->assembly.aname.culture = g_strdup ("");
4000 assembly->run = assemblyb->access != 2;
4001 assembly->save = assemblyb->access != 1;
4003 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4004 assembly->assembly.aname.name = image->image.name;
4005 assembly->assembly.image = &image->image;
4007 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4008 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4012 calc_section_size (MonoDynamicImage *assembly)
4016 /* alignment constraints */
4017 assembly->code.index += 3;
4018 assembly->code.index &= ~3;
4019 assembly->meta_size += 3;
4020 assembly->meta_size &= ~3;
4021 assembly->resources.index += 3;
4022 assembly->resources.index &= ~3;
4024 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4025 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4028 if (assembly->win32_res) {
4029 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4031 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4032 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4036 assembly->sections [MONO_SECTION_RELOC].size = 12;
4037 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4047 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4051 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4053 ResTreeNode *t1 = (ResTreeNode*)a;
4054 ResTreeNode *t2 = (ResTreeNode*)b;
4056 return t1->id - t2->id;
4060 * resource_tree_create:
4062 * Organize the resources into a resource tree.
4064 static ResTreeNode *
4065 resource_tree_create (MonoArray *win32_resources)
4067 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4071 tree = g_new0 (ResTreeNode, 1);
4073 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4074 MonoReflectionWin32Resource *win32_res =
4075 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4079 lang_node = g_new0 (ResTreeNode, 1);
4080 lang_node->id = win32_res->lang_id;
4081 lang_node->win32_res = win32_res;
4083 /* Create type node if neccesary */
4085 for (l = tree->children; l; l = l->next)
4086 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4087 type_node = (ResTreeNode*)l->data;
4092 type_node = g_new0 (ResTreeNode, 1);
4093 type_node->id = win32_res->res_type;
4096 * The resource types have to be sorted otherwise
4097 * Windows Explorer can't display the version information.
4099 tree->children = g_slist_insert_sorted (tree->children, type_node,
4100 resource_tree_compare_by_id);
4103 /* Create res node if neccesary */
4105 for (l = type_node->children; l; l = l->next)
4106 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4107 res_node = (ResTreeNode*)l->data;
4112 res_node = g_new0 (ResTreeNode, 1);
4113 res_node->id = win32_res->res_id;
4114 type_node->children = g_slist_append (type_node->children, res_node);
4117 res_node->children = g_slist_append (res_node->children, lang_node);
4124 * resource_tree_encode:
4126 * Encode the resource tree into the format used in the PE file.
4129 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4132 MonoPEResourceDir dir;
4133 MonoPEResourceDirEntry dir_entry;
4134 MonoPEResourceDataEntry data_entry;
4138 * For the format of the resource directory, see the article
4139 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4143 memset (&dir, 0, sizeof (dir));
4144 memset (&dir_entry, 0, sizeof (dir_entry));
4145 memset (&data_entry, 0, sizeof (data_entry));
4147 g_assert (sizeof (dir) == 16);
4148 g_assert (sizeof (dir_entry) == 8);
4149 g_assert (sizeof (data_entry) == 16);
4151 node->offset = p - begin;
4153 /* IMAGE_RESOURCE_DIRECTORY */
4154 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4156 memcpy (p, &dir, sizeof (dir));
4159 /* Reserve space for entries */
4161 p += sizeof (dir_entry) * dir.res_id_entries;
4163 /* Write children */
4164 for (l = node->children; l; l = l->next) {
4165 ResTreeNode *child = (ResTreeNode*)l->data;
4167 if (child->win32_res) {
4169 child->offset = p - begin;
4171 /* IMAGE_RESOURCE_DATA_ENTRY */
4172 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4173 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4175 memcpy (p, &data_entry, sizeof (data_entry));
4176 p += sizeof (data_entry);
4178 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4179 p += data_entry.rde_size;
4182 resource_tree_encode (child, begin, p, &p);
4185 /* IMAGE_RESOURCE_ENTRY */
4186 for (l = node->children; l; l = l->next) {
4187 ResTreeNode *child = (ResTreeNode*)l->data;
4188 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4190 dir_entry.is_dir = child->win32_res ? 0 : 1;
4191 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4193 memcpy (entries, &dir_entry, sizeof (dir_entry));
4194 entries += sizeof (dir_entry);
4201 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4206 MonoReflectionWin32Resource *win32_res;
4209 if (!assemblyb->win32_resources)
4213 * Resources are stored in a three level tree inside the PE file.
4214 * - level one contains a node for each type of resource
4215 * - level two contains a node for each resource
4216 * - level three contains a node for each instance of a resource for a
4217 * specific language.
4220 tree = resource_tree_create (assemblyb->win32_resources);
4222 /* Estimate the size of the encoded tree */
4224 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4225 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4226 size += mono_array_length (win32_res->res_data);
4228 /* Directory structure */
4229 size += mono_array_length (assemblyb->win32_resources) * 256;
4230 p = buf = g_malloc (size);
4232 resource_tree_encode (tree, p, p, &p);
4234 g_assert (p - buf < size);
4236 assembly->win32_res = g_malloc (p - buf);
4237 assembly->win32_res_size = p - buf;
4238 memcpy (assembly->win32_res, buf, p - buf);
4244 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4246 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4249 p += sizeof (MonoPEResourceDir);
4250 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4251 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4252 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4253 if (dir_entry->is_dir)
4254 fixup_resource_directory (res_section, child, rva);
4256 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4257 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4260 p += sizeof (MonoPEResourceDirEntry);
4265 * mono_image_create_pefile:
4266 * @mb: a module builder object
4268 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4269 * assembly->pefile where it can be easily retrieved later in chunks.
4272 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4273 MonoMSDOSHeader *msdos;
4274 MonoDotNetHeader *header;
4275 MonoSectionTable *section;
4276 MonoCLIHeader *cli_header;
4277 guint32 size, image_size, virtual_base, text_offset;
4278 guint32 header_start, section_start, file_offset, virtual_offset;
4279 MonoDynamicImage *assembly;
4280 MonoReflectionAssemblyBuilder *assemblyb;
4281 MonoDynamicStream *pefile;
4283 guint32 *rva, value;
4286 static const unsigned char msheader[] = {
4287 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4288 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4291 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4292 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4293 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4294 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4297 assemblyb = mb->assemblyb;
4299 mono_image_basic_init (assemblyb);
4300 assembly = mb->dynamic_image;
4302 /* already created */
4303 if (assembly->pefile.index)
4306 mono_image_build_metadata (mb);
4308 if (mb->is_main && assemblyb->resources) {
4309 int len = mono_array_length (assemblyb->resources);
4310 for (i = 0; i < len; ++i)
4311 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4314 if (mb->resources) {
4315 int len = mono_array_length (mb->resources);
4316 for (i = 0; i < len; ++i)
4317 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4320 build_compressed_metadata (assembly);
4323 assembly_add_win32_resources (assembly, assemblyb);
4325 nsections = calc_section_size (assembly);
4327 pefile = &assembly->pefile;
4329 /* The DOS header and stub */
4330 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4331 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4333 /* the dotnet header */
4334 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4336 /* the section tables */
4337 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4339 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4340 virtual_offset = VIRT_ALIGN;
4343 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4344 if (!assembly->sections [i].size)
4347 file_offset += FILE_ALIGN - 1;
4348 file_offset &= ~(FILE_ALIGN - 1);
4349 virtual_offset += VIRT_ALIGN - 1;
4350 virtual_offset &= ~(VIRT_ALIGN - 1);
4352 assembly->sections [i].offset = file_offset;
4353 assembly->sections [i].rva = virtual_offset;
4355 file_offset += assembly->sections [i].size;
4356 virtual_offset += assembly->sections [i].size;
4357 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4360 file_offset += FILE_ALIGN - 1;
4361 file_offset &= ~(FILE_ALIGN - 1);
4362 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4364 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4366 /* back-patch info */
4367 msdos = (MonoMSDOSHeader*)pefile->data;
4368 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4369 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4370 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4372 header = (MonoDotNetHeader*)(pefile->data + header_start);
4373 header->pesig [0] = 'P';
4374 header->pesig [1] = 'E';
4376 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4377 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4378 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4379 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4380 if (assemblyb->pekind == 1) {
4382 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4385 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4388 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4390 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4391 header->pe.pe_major = 6;
4392 header->pe.pe_minor = 0;
4393 size = assembly->sections [MONO_SECTION_TEXT].size;
4394 size += FILE_ALIGN - 1;
4395 size &= ~(FILE_ALIGN - 1);
4396 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4397 size = assembly->sections [MONO_SECTION_RSRC].size;
4398 size += FILE_ALIGN - 1;
4399 size &= ~(FILE_ALIGN - 1);
4400 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4401 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4402 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4403 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4404 /* pe_rva_entry_point always at the beginning of the text section */
4405 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4407 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4408 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4409 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4410 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4411 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4412 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4413 size = section_start;
4414 size += FILE_ALIGN - 1;
4415 size &= ~(FILE_ALIGN - 1);
4416 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4418 size += VIRT_ALIGN - 1;
4419 size &= ~(VIRT_ALIGN - 1);
4420 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4423 // Translate the PEFileKind value to the value expected by the Windows loader
4426 short kind = assemblyb->pekind;
4429 // PEFileKinds.ConsoleApplication == 2
4430 // PEFileKinds.WindowApplication == 3
4433 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4434 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4440 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4442 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4443 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4444 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4445 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4446 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4447 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4449 /* fill data directory entries */
4451 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4452 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4454 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4455 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4457 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4458 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4459 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4460 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4461 /* patch imported function RVA name */
4462 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4463 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4465 /* the import table */
4466 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4467 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4468 /* patch imported dll RVA name and other entries in the dir */
4469 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4470 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4471 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4472 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4473 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4474 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4476 p = (assembly->code.data + assembly->ilt_offset);
4477 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4478 *p++ = (value) & 0xff;
4479 *p++ = (value >> 8) & (0xff);
4480 *p++ = (value >> 16) & (0xff);
4481 *p++ = (value >> 24) & (0xff);
4483 /* the CLI header info */
4484 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4485 cli_header->ch_size = GUINT32_FROM_LE (72);
4486 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4487 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4488 if (assemblyb->entry_point) {
4489 guint32 table_idx = 0;
4490 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4491 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4492 table_idx = methodb->table_idx;
4495 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4496 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4499 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4500 /* The embedded managed resources */
4501 text_offset = assembly->text_rva + assembly->code.index;
4502 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4503 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4504 text_offset += assembly->resources.index;
4505 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4506 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4507 text_offset += assembly->meta_size;
4508 if (assembly->strong_name_size) {
4509 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4510 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4511 text_offset += assembly->strong_name_size;
4514 /* write the section tables and section content */
4515 section = (MonoSectionTable*)(pefile->data + section_start);
4516 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4517 static const char *section_names [] = {
4518 ".text", ".rsrc", ".reloc"
4520 if (!assembly->sections [i].size)
4522 strcpy (section->st_name, section_names [i]);
4523 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4524 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4525 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4526 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4527 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4528 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4529 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4531 case MONO_SECTION_TEXT:
4532 /* patch entry point */
4533 p = (assembly->code.data + 2);
4534 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4535 *p++ = (value) & 0xff;
4536 *p++ = (value >> 8) & 0xff;
4537 *p++ = (value >> 16) & 0xff;
4538 *p++ = (value >> 24) & 0xff;
4540 text_offset = assembly->sections [i].offset;
4541 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4542 text_offset += assembly->code.index;
4543 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4544 text_offset += assembly->resources.index;
4545 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4546 text_offset += assembly->meta_size;
4547 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4549 g_free (assembly->image.raw_metadata);
4551 case MONO_SECTION_RELOC:
4552 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4553 *rva = GUINT32_FROM_LE (assembly->text_rva);
4555 *rva = GUINT32_FROM_LE (12);
4557 data16 = (guint16*)rva;
4559 * the entrypoint is always at the start of the text section
4560 * 3 is IMAGE_REL_BASED_HIGHLOW
4561 * 2 is patch_size_rva - text_rva
4563 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4565 *data16 = 0; /* terminate */
4567 case MONO_SECTION_RSRC:
4568 if (assembly->win32_res) {
4569 text_offset = assembly->sections [i].offset;
4571 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4572 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4574 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4578 g_assert_not_reached ();
4583 /* check that the file is properly padded */
4586 FILE *f = fopen ("mypetest.exe", "w");
4587 fwrite (pefile->data, pefile->index, 1, f);
4593 MonoReflectionModule *
4594 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4598 MonoImageOpenStatus status;
4599 MonoDynamicAssembly *assembly;
4601 name = mono_string_to_utf8 (fileName);
4603 image = mono_image_open (name, &status);
4606 if (status == MONO_IMAGE_ERROR_ERRNO)
4607 exc = mono_get_exception_file_not_found (fileName);
4609 exc = mono_get_exception_bad_image_format (name);
4611 mono_raise_exception (exc);
4616 assembly = ab->dynamic_assembly;
4617 image->assembly = (MonoAssembly*)assembly;
4619 mono_assembly_load_references (image, &status);
4621 mono_image_close (image);
4622 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4625 return mono_module_get_object (mono_domain_get (), image);
4629 * We need to return always the same object for MethodInfo, FieldInfo etc..
4630 * but we need to consider the reflected type.
4631 * type uses a different hash, since it uses custom hash/equal functions.
4636 MonoClass *refclass;
4640 reflected_equal (gconstpointer a, gconstpointer b) {
4641 const ReflectedEntry *ea = a;
4642 const ReflectedEntry *eb = b;
4644 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4648 reflected_hash (gconstpointer a) {
4649 const ReflectedEntry *ea = a;
4650 return GPOINTER_TO_UINT (ea->item);
4653 #define CHECK_OBJECT(t,p,k) \
4659 mono_domain_lock (domain); \
4660 if (!domain->refobject_hash) \
4661 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4662 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4663 mono_domain_unlock (domain); \
4669 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4671 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4674 #define CACHE_OBJECT(p,o,k) \
4676 ReflectedEntry *e = ALLOC_REFENTRY; \
4678 e->refclass = (k); \
4679 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4680 mono_domain_unlock (domain); \
4684 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4686 /* this is done only once */
4687 mono_domain_lock (domain);
4688 CACHE_OBJECT (assembly, res, NULL);
4692 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4694 /* this is done only once */
4695 mono_domain_lock (domain);
4696 CACHE_OBJECT (module, res, NULL);
4700 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4702 MonoDynamicImage *image = moduleb->dynamic_image;
4703 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4706 * FIXME: we already created an image in mono_image_basic_init (), but
4707 * we don't know which module it belongs to, since that is only
4708 * determined at assembly save time.
4710 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4711 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4713 moduleb->module.image = &image->image;
4714 moduleb->dynamic_image = image;
4715 register_module (mono_object_domain (moduleb), moduleb, image);
4720 * mono_assembly_get_object:
4721 * @domain: an app domain
4722 * @assembly: an assembly
4724 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4726 MonoReflectionAssembly*
4727 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4729 static MonoClass *System_Reflection_Assembly;
4730 MonoReflectionAssembly *res;
4732 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4733 if (!System_Reflection_Assembly)
4734 System_Reflection_Assembly = mono_class_from_name (
4735 mono_defaults.corlib, "System.Reflection", "Assembly");
4736 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4737 res->assembly = assembly;
4738 CACHE_OBJECT (assembly, res, NULL);
4744 MonoReflectionModule*
4745 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4747 static MonoClass *System_Reflection_Module;
4748 MonoReflectionModule *res;
4750 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4751 if (!System_Reflection_Module)
4752 System_Reflection_Module = mono_class_from_name (
4753 mono_defaults.corlib, "System.Reflection", "Module");
4754 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4757 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4759 res->fqname = mono_string_new (domain, image->name);
4760 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4761 res->scopename = mono_string_new (domain, image->module_name);
4763 mono_image_addref (image);
4765 CACHE_OBJECT (image, res, NULL);
4769 MonoReflectionModule*
4770 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4772 static MonoClass *System_Reflection_Module;
4773 MonoReflectionModule *res;
4774 MonoTableInfo *table;
4775 guint32 cols [MONO_FILE_SIZE];
4777 guint32 i, name_idx;
4780 if (!System_Reflection_Module)
4781 System_Reflection_Module = mono_class_from_name (
4782 mono_defaults.corlib, "System.Reflection", "Module");
4783 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4785 table = &image->tables [MONO_TABLE_FILE];
4786 g_assert (table_index < table->rows);
4787 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4790 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4791 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4793 // Check whenever the row has a corresponding row in the moduleref table
4794 table = &image->tables [MONO_TABLE_MODULEREF];
4795 for (i = 0; i < table->rows; ++i) {
4796 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4797 val = mono_metadata_string_heap (image, name_idx);
4798 if (strcmp (val, name) == 0)
4799 res->image = image->modules [i];
4802 res->fqname = mono_string_new (domain, name);
4803 res->name = mono_string_new (domain, name);
4804 res->scopename = mono_string_new (domain, name);
4805 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4811 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4813 if ((t1->type != t2->type) ||
4814 (t1->byref != t2->byref))
4818 case MONO_TYPE_VOID:
4819 case MONO_TYPE_BOOLEAN:
4820 case MONO_TYPE_CHAR:
4831 case MONO_TYPE_STRING:
4834 case MONO_TYPE_OBJECT:
4835 case MONO_TYPE_TYPEDBYREF:
4837 case MONO_TYPE_VALUETYPE:
4838 case MONO_TYPE_CLASS:
4839 case MONO_TYPE_SZARRAY:
4840 return t1->data.klass == t2->data.klass;
4842 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4843 case MONO_TYPE_ARRAY:
4844 if (t1->data.array->rank != t2->data.array->rank)
4846 return t1->data.array->eklass == t2->data.array->eklass;
4847 case MONO_TYPE_GENERICINST: {
4849 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4851 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4853 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4854 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4860 case MONO_TYPE_MVAR:
4861 return t1->data.generic_param == t2->data.generic_param;
4863 g_error ("implement type compare for %0x!", t1->type);
4871 mymono_metadata_type_hash (MonoType *t1)
4877 hash |= t1->byref << 6; /* do not collide with t1->type values */
4879 case MONO_TYPE_VALUETYPE:
4880 case MONO_TYPE_CLASS:
4881 case MONO_TYPE_SZARRAY:
4882 /* check if the distribution is good enough */
4883 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4885 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4890 static MonoReflectionGenericInst*
4891 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4893 static MonoClass *System_Reflection_MonoGenericInst;
4894 MonoReflectionGenericInst *res;
4895 MonoGenericInst *ginst;
4898 if (!System_Reflection_MonoGenericInst) {
4899 System_Reflection_MonoGenericInst = mono_class_from_name (
4900 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4901 g_assert (System_Reflection_MonoGenericInst);
4904 ginst = geninst->data.generic_inst;
4905 gklass = mono_class_from_mono_type (ginst->generic_type);
4907 mono_class_init (ginst->klass);
4909 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4911 res->type.type = geninst;
4912 if (gklass->wastypebuilder && gklass->reflection_info)
4913 res->generic_type = gklass->reflection_info;
4915 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4921 * mono_type_get_object:
4922 * @domain: an app domain
4925 * Return an System.MonoType object representing the type @type.
4928 mono_type_get_object (MonoDomain *domain, MonoType *type)
4930 MonoReflectionType *res;
4931 MonoClass *klass = mono_class_from_mono_type (type);
4933 mono_domain_lock (domain);
4934 if (!domain->type_hash)
4935 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4936 (GCompareFunc)mymono_metadata_type_equal);
4937 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4938 mono_domain_unlock (domain);
4941 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4942 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4943 mono_g_hash_table_insert (domain->type_hash, type, res);
4944 mono_domain_unlock (domain);
4947 if (klass->reflection_info && !klass->wastypebuilder) {
4948 //g_assert_not_reached ();
4949 /* should this be considered an error condition? */
4951 mono_domain_unlock (domain);
4952 return klass->reflection_info;
4955 mono_class_init (klass);
4956 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4958 mono_g_hash_table_insert (domain->type_hash, type, res);
4959 mono_domain_unlock (domain);
4964 * mono_method_get_object:
4965 * @domain: an app domain
4967 * @refclass: the reflected type (can be NULL)
4969 * Return an System.Reflection.MonoMethod object representing the method @method.
4971 MonoReflectionMethod*
4972 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4975 * We use the same C representation for methods and constructors, but the type
4976 * name in C# is different.
4980 MonoReflectionMethod *ret;
4983 refclass = method->klass;
4985 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4986 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4987 cname = "MonoCMethod";
4989 cname = "MonoMethod";
4990 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4992 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4993 ret->method = method;
4994 ret->name = mono_string_new (domain, method->name);
4995 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4996 CACHE_OBJECT (method, ret, refclass);
5001 * mono_field_get_object:
5002 * @domain: an app domain
5006 * Return an System.Reflection.MonoField object representing the field @field
5009 MonoReflectionField*
5010 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5012 MonoReflectionField *res;
5015 CHECK_OBJECT (MonoReflectionField *, field, klass);
5016 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5017 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5020 res->name = mono_string_new (domain, field->name);
5021 res->attrs = field->type->attrs;
5022 res->type = mono_type_get_object (domain, field->type);
5023 CACHE_OBJECT (field, res, klass);
5028 * mono_property_get_object:
5029 * @domain: an app domain
5031 * @property: a property
5033 * Return an System.Reflection.MonoProperty object representing the property @property
5036 MonoReflectionProperty*
5037 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5039 MonoReflectionProperty *res;
5042 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5043 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5044 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5046 res->property = property;
5047 CACHE_OBJECT (property, res, klass);
5052 * mono_event_get_object:
5053 * @domain: an app domain
5057 * Return an System.Reflection.MonoEvent object representing the event @event
5060 MonoReflectionEvent*
5061 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5063 MonoReflectionEvent *res;
5066 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5067 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5068 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5071 CACHE_OBJECT (event, res, klass);
5076 * mono_param_get_objects:
5077 * @domain: an app domain
5080 * Return an System.Reflection.ParameterInfo array object representing the parameters
5081 * in the method @method.
5084 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5086 static MonoClass *System_Reflection_ParameterInfo;
5087 MonoArray *res = NULL;
5088 MonoReflectionMethod *member = NULL;
5089 MonoReflectionParameter *param = NULL;
5093 if (!System_Reflection_ParameterInfo)
5094 System_Reflection_ParameterInfo = mono_class_from_name (
5095 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5097 if (!method->signature->param_count)
5098 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5100 /* Note: the cache is based on the address of the signature into the method
5101 * since we already cache MethodInfos with the method as keys.
5103 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5105 member = mono_method_get_object (domain, method, NULL);
5106 names = g_new (char *, method->signature->param_count);
5107 mono_method_get_param_names (method, (const char **) names);
5109 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5110 for (i = 0; i < method->signature->param_count; ++i) {
5111 param = (MonoReflectionParameter *)mono_object_new (domain,
5112 System_Reflection_ParameterInfo);
5113 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5114 param->DefaultValueImpl = NULL; /* FIXME */
5115 param->MemberImpl = (MonoObject*)member;
5116 param->NameImpl = mono_string_new (domain, names [i]);
5117 param->PositionImpl = i;
5118 param->AttrsImpl = method->signature->params [i]->attrs;
5119 mono_array_set (res, gpointer, i, param);
5122 CACHE_OBJECT (&(method->signature), res, NULL);
5127 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5131 memset (assembly, 0, sizeof (MonoAssemblyName));
5133 assembly->culture = "";
5135 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5138 while (*p == ' ' || *p == ',') {
5147 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5149 assembly->major = strtoul (p, &s, 10);
5150 if (s == p || *s != '.')
5153 assembly->minor = strtoul (p, &s, 10);
5154 if (s == p || *s != '.')
5157 assembly->build = strtoul (p, &s, 10);
5158 if (s == p || *s != '.')
5161 assembly->revision = strtoul (p, &s, 10);
5164 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5166 if (strncmp (p, "neutral", 7) == 0) {
5167 assembly->culture = "";
5170 assembly->culture = p;
5171 while (*p && *p != ',') {
5175 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5178 while (*s && isxdigit (*s)) {
5182 assembly->hash_len = s - p;
5183 if (!(s-p) || ((s-p) & 1))
5185 assembly->hash_value = s = p;
5186 while (*s && isxdigit (*s)) {
5188 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5191 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5196 while (*p && *p != ',')
5200 while (*p == ' ' || *p == ',') {
5214 * mono_reflection_parse_type:
5217 * Parse a type name as accepted by the GetType () method and output the info
5218 * extracted in the info structure.
5219 * the name param will be mangled, so, make a copy before passing it to this function.
5220 * The fields in info will be valid until the memory pointed to by name is valid.
5221 * Returns 0 on parse error.
5222 * See also mono_type_get_name () below.
5225 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5227 char *start, *p, *w, *last_point, *startn;
5228 int in_modifiers = 0;
5229 int isbyref = 0, rank;
5231 start = p = w = name;
5233 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5234 info->name = info->name_space = NULL;
5235 info->nested = NULL;
5236 info->modifiers = NULL;
5238 /* last_point separates the namespace from the name */
5244 *p = 0; /* NULL terminate the name */
5246 info->nested = g_list_append (info->nested, startn);
5247 /* we have parsed the nesting namespace + name */
5251 info->name_space = start;
5253 info->name = last_point + 1;
5255 info->name_space = (char *)"";
5281 info->name_space = start;
5283 info->name = last_point + 1;
5285 info->name_space = (char *)"";
5292 if (isbyref) /* only one level allowed by the spec */
5295 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5299 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5310 else if (*p != '*') /* '*' means unknown lower bound */
5316 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5328 return 0; /* missing assembly name */
5329 if (!assembly_name_to_aname (&info->assembly, p))
5336 if (info->assembly.name)
5339 *w = 0; /* terminate class name */
5340 if (!info->name || !*info->name)
5342 /* add other consistency checks */
5347 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5354 image = mono_defaults.corlib;
5357 klass = mono_class_from_name_case (image, info->name_space, info->name);
5359 klass = mono_class_from_name (image, info->name_space, info->name);
5362 for (mod = info->nested; mod; mod = mod->next) {
5365 mono_class_init (klass);
5366 nested = klass->nested_classes;
5369 klass = nested->data;
5371 if (g_strcasecmp (klass->name, mod->data) == 0)
5374 if (strcmp (klass->name, mod->data) == 0)
5378 nested = nested->next;
5385 mono_class_init (klass);
5386 for (mod = info->modifiers; mod; mod = mod->next) {
5387 modval = GPOINTER_TO_UINT (mod->data);
5388 if (!modval) { /* byref: must be last modifier */
5389 return &klass->this_arg;
5390 } else if (modval == -1) {
5391 klass = mono_ptr_class_get (&klass->byval_arg);
5392 } else { /* array rank */
5393 klass = mono_array_class_get (klass, modval);
5395 mono_class_init (klass);
5398 return &klass->byval_arg;
5402 * mono_reflection_get_type:
5403 * @image: a metadata context
5404 * @info: type description structure
5405 * @ignorecase: flag for case-insensitive string compares
5407 * Build a MonoType from the type description in @info.
5412 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5415 MonoReflectionAssembly *assembly;
5419 type = mono_reflection_get_type_internal (image, info, ignorecase);
5422 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5425 // Reconstruct the type name
5426 fullName = g_string_new ("");
5427 if (info->name_space && (info->name_space [0] != '\0'))
5428 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5430 g_string_printf (fullName, info->name);
5431 for (mod = info->nested; mod; mod = mod->next)
5432 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5435 mono_domain_try_type_resolve (
5436 mono_domain_get (), fullName->str, NULL);
5437 if (assembly && (!image || (assembly->assembly->image == image)))
5438 type = mono_reflection_get_type_internal (assembly->assembly->image,
5440 g_string_free (fullName, TRUE);
5445 * mono_reflection_type_from_name:
5447 * @image: a metadata context (can be NULL).
5449 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5450 * it defaults to get the type from @image or, if @image is NULL or loading
5451 * from it fails, uses corlib.
5455 mono_reflection_type_from_name (char *name, MonoImage *image)
5458 MonoTypeNameParse info;
5459 MonoAssembly *assembly;
5461 /*g_print ("requested type %s\n", str);*/
5462 if (!mono_reflection_parse_type (name, &info)) {
5463 g_list_free (info.modifiers);
5464 g_list_free (info.nested);
5468 if (info.assembly.name) {
5469 assembly = mono_assembly_loaded (&info.assembly);
5470 /* do we need to load if it's not already loaded? */
5472 g_list_free (info.modifiers);
5473 g_list_free (info.nested);
5477 image = assembly->image;
5478 } else if (image == NULL) {
5479 image = mono_defaults.corlib;
5482 type = mono_reflection_get_type (image, &info, FALSE);
5483 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5484 image = mono_defaults.corlib;
5485 type = mono_reflection_get_type (image, &info, FALSE);
5488 g_list_free (info.modifiers);
5489 g_list_free (info.nested);
5494 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5496 int slen, type = t->type;
5501 case MONO_TYPE_BOOLEAN: {
5502 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5507 case MONO_TYPE_CHAR:
5509 case MONO_TYPE_I2: {
5510 guint16 *val = g_malloc (sizeof (guint16));
5515 #if SIZEOF_VOID_P == 4
5521 case MONO_TYPE_I4: {
5522 guint32 *val = g_malloc (sizeof (guint32));
5527 #if SIZEOF_VOID_P == 8
5528 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5533 case MONO_TYPE_I8: {
5534 guint64 *val = g_malloc (sizeof (guint64));
5539 case MONO_TYPE_VALUETYPE:
5540 if (t->data.klass->enumtype) {
5541 type = t->data.klass->enum_basetype->type;
5544 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5547 case MONO_TYPE_STRING:
5548 if (*p == (char)0xFF) {
5552 slen = mono_metadata_decode_value (p, &p);
5554 return mono_string_new_len (mono_domain_get (), p, slen);
5555 case MONO_TYPE_CLASS: {
5558 if (*p == (char)0xFF) {
5563 slen = mono_metadata_decode_value (p, &p);
5564 n = g_memdup (p, slen + 1);
5566 t = mono_reflection_type_from_name (n, image);
5568 g_warning ("Cannot load type '%s'", n);
5572 return mono_type_get_object (mono_domain_get (), t);
5576 case MONO_TYPE_OBJECT: {
5579 MonoClass *subc = NULL;
5584 } else if (subt == 0x0E) {
5585 type = MONO_TYPE_STRING;
5587 } else if (subt == 0x55) {
5590 slen = mono_metadata_decode_value (p, &p);
5591 n = g_memdup (p, slen + 1);
5593 t = mono_reflection_type_from_name (n, image);
5595 g_warning ("Cannot load type '%s'", n);
5598 subc = mono_class_from_mono_type (t);
5599 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5600 MonoType simple_type = {{0}};
5601 simple_type.type = subt;
5602 subc = mono_class_from_mono_type (&simple_type);
5604 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5606 val = load_cattr_value (image, &subc->byval_arg, p, end);
5607 obj = mono_object_new (mono_domain_get (), subc);
5608 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5612 case MONO_TYPE_SZARRAY:
5615 guint32 i, alen, basetype;
5618 if (alen == 0xffffffff) {
5622 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5623 basetype = t->data.klass->byval_arg.type;
5628 case MONO_TYPE_BOOLEAN:
5629 for (i=0;i<alen;i++)
5631 MonoBoolean val=*p++;
5632 mono_array_set(arr,MonoBoolean,i,val);
5635 case MONO_TYPE_CHAR:
5638 for (i=0;i<alen;i++)
5640 guint16 val=read16(p);
5641 mono_array_set(arr,guint16,i,val);
5648 for (i=0;i<alen;i++)
5650 guint32 val=read32(p);
5651 mono_array_set(arr,guint32,i,val);
5658 for (i=0;i<alen;i++)
5660 guint64 val=read64(p);
5661 mono_array_set(arr,guint64,i,val);
5665 case MONO_TYPE_CLASS:
5666 case MONO_TYPE_STRING:
5667 for (i = 0; i < alen; i++) {
5668 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5669 mono_array_set (arr, gpointer, i, item);
5673 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5679 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5685 type_is_reference (MonoType *type)
5687 switch (type->type) {
5688 case MONO_TYPE_BOOLEAN:
5689 case MONO_TYPE_CHAR:
5702 case MONO_TYPE_VALUETYPE:
5710 free_param_data (MonoMethodSignature *sig, void **params) {
5712 for (i = 0; i < sig->param_count; ++i) {
5713 if (!type_is_reference (sig->params [i]))
5714 g_free (params [i]);
5719 * Find the method index in the metadata methodDef table.
5720 * Later put these three helper methods in metadata and export them.
5723 find_method_index (MonoMethod *method) {
5724 MonoClass *klass = method->klass;
5727 for (i = 0; i < klass->method.count; ++i) {
5728 if (method == klass->methods [i])
5729 return klass->method.first + 1 + i;
5735 * Find the field index in the metadata FieldDef table.
5738 find_field_index (MonoClass *klass, MonoClassField *field) {
5741 for (i = 0; i < klass->field.count; ++i) {
5742 if (field == &klass->fields [i])
5743 return klass->field.first + 1 + i;
5749 * Find the property index in the metadata Property table.
5752 find_property_index (MonoClass *klass, MonoProperty *property) {
5755 for (i = 0; i < klass->property.count; ++i) {
5756 if (property == &klass->properties [i])
5757 return klass->property.first + 1 + i;
5763 * Find the event index in the metadata Event table.
5766 find_event_index (MonoClass *klass, MonoEvent *event) {
5769 for (i = 0; i < klass->event.count; ++i) {
5770 if (event == &klass->events [i])
5771 return klass->event.first + 1 + i;
5777 create_custom_attr (MonoImage *image, MonoMethod *method,
5778 const char *data, guint32 len)
5780 const char *p = data;
5782 guint32 i, j, num_named;
5786 mono_class_init (method->klass);
5789 attr = mono_object_new (mono_domain_get (), method->klass);
5790 mono_runtime_invoke (method, attr, NULL, NULL);
5794 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5797 /*g_print ("got attr %s\n", method->klass->name);*/
5799 params = g_new (void*, method->signature->param_count);
5803 for (i = 0; i < method->signature->param_count; ++i) {
5804 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5808 attr = mono_object_new (mono_domain_get (), method->klass);
5809 mono_runtime_invoke (method, attr, params, NULL);
5810 free_param_data (method->signature, params);
5812 num_named = read16 (named);
5814 for (j = 0; j < num_named; j++) {
5816 char *name, named_type, data_type;
5817 named_type = *named++;
5818 data_type = *named++; /* type of data */
5819 if (data_type == 0x55) {
5822 type_len = mono_metadata_decode_blob_size (named, &named);
5823 type_name = g_malloc (type_len + 1);
5824 memcpy (type_name, named, type_len);
5825 type_name [type_len] = 0;
5827 /* FIXME: lookup the type and check type consistency */
5830 if (data_type == MONO_TYPE_SZARRAY)
5831 /* The spec does not mention this */
5833 name_len = mono_metadata_decode_blob_size (named, &named);
5834 name = g_malloc (name_len + 1);
5835 memcpy (name, named, name_len);
5836 name [name_len] = 0;
5838 if (named_type == 0x53) {
5839 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5840 void *val = load_cattr_value (image, field->type, named, &named);
5841 mono_field_set_value (attr, field, val);
5842 if (!type_is_reference (field->type))
5844 } else if (named_type == 0x54) {
5847 MonoType *prop_type;
5849 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5850 /* can we have more that 1 arg in a custom attr named property? */
5851 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5852 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5853 mono_property_set_value (prop, attr, pparams, NULL);
5854 if (!type_is_reference (prop_type))
5855 g_free (pparams [0]);
5864 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5871 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5872 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5873 for (i = 0; i < cinfo->num_attrs; ++i) {
5874 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5875 mono_array_set (result, gpointer, i, attr);
5881 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5883 guint32 mtoken, i, len;
5884 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5886 MonoCustomAttrInfo *ainfo;
5887 GList *tmp, *list = NULL;
5890 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5892 i = mono_metadata_custom_attrs_from_index (image, idx);
5896 while (i < ca->rows) {
5897 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5899 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5902 len = g_list_length (list);
5905 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5906 ainfo->num_attrs = len;
5907 ainfo->image = image;
5908 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5909 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5910 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5911 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5912 case CUSTOM_ATTR_TYPE_METHODDEF:
5913 mtoken |= MONO_TOKEN_METHOD_DEF;
5915 case CUSTOM_ATTR_TYPE_MEMBERREF:
5916 mtoken |= MONO_TOKEN_MEMBER_REF;
5919 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5922 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5923 if (!ainfo->attrs [i].ctor)
5924 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5925 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5926 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5927 ainfo->attrs [i].data = data;
5935 mono_custom_attrs_from_method (MonoMethod *method)
5937 MonoCustomAttrInfo *cinfo;
5940 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5942 idx = find_method_index (method);
5943 idx <<= CUSTOM_ATTR_BITS;
5944 idx |= CUSTOM_ATTR_METHODDEF;
5945 return mono_custom_attrs_from_index (method->klass->image, idx);
5949 mono_custom_attrs_from_class (MonoClass *klass)
5951 MonoCustomAttrInfo *cinfo;
5954 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5956 idx = mono_metadata_token_index (klass->type_token);
5957 idx <<= CUSTOM_ATTR_BITS;
5958 idx |= CUSTOM_ATTR_TYPEDEF;
5959 return mono_custom_attrs_from_index (klass->image, idx);
5963 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5965 MonoCustomAttrInfo *cinfo;
5968 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5970 idx = 1; /* there is only one assembly */
5971 idx <<= CUSTOM_ATTR_BITS;
5972 idx |= CUSTOM_ATTR_ASSEMBLY;
5973 return mono_custom_attrs_from_index (assembly->image, idx);
5976 static MonoCustomAttrInfo*
5977 mono_custom_attrs_from_module (MonoImage *image)
5979 MonoCustomAttrInfo *cinfo;
5982 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5984 idx = 1; /* there is only one module */
5985 idx <<= CUSTOM_ATTR_BITS;
5986 idx |= CUSTOM_ATTR_MODULE;
5987 return mono_custom_attrs_from_index (image, idx);
5991 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5993 MonoCustomAttrInfo *cinfo;
5996 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5998 idx = find_property_index (klass, property);
5999 idx <<= CUSTOM_ATTR_BITS;
6000 idx |= CUSTOM_ATTR_PROPERTY;
6001 return mono_custom_attrs_from_index (klass->image, idx);
6005 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6007 MonoCustomAttrInfo *cinfo;
6010 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6012 idx = find_event_index (klass, event);
6013 idx <<= CUSTOM_ATTR_BITS;
6014 idx |= CUSTOM_ATTR_EVENT;
6015 return mono_custom_attrs_from_index (klass->image, idx);
6019 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6021 MonoCustomAttrInfo *cinfo;
6024 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6026 idx = find_field_index (klass, field);
6027 idx <<= CUSTOM_ATTR_BITS;
6028 idx |= CUSTOM_ATTR_FIELDDEF;
6029 return mono_custom_attrs_from_index (klass->image, idx);
6033 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6036 guint32 i, idx, method_index;
6037 guint32 param_list, param_last, param_pos, found;
6039 MonoReflectionMethodAux *aux;
6041 if (method->klass->image->dynamic) {
6042 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6043 if (!aux || !aux->param_cattr)
6045 return aux->param_cattr [param];
6048 image = method->klass->image;
6049 method_index = find_method_index (method);
6050 ca = &image->tables [MONO_TABLE_METHOD];
6052 if (method->klass->generic_inst || method->klass->gen_params ||
6053 method->signature->generic_param_count) {
6054 // FIXME FIXME FIXME
6058 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6059 if (method_index == ca->rows) {
6060 ca = &image->tables [MONO_TABLE_PARAM];
6061 param_last = ca->rows + 1;
6063 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6064 ca = &image->tables [MONO_TABLE_PARAM];
6067 for (i = param_list; i < param_last; ++i) {
6068 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6069 if (param_pos == param) {
6077 idx <<= CUSTOM_ATTR_BITS;
6078 idx |= CUSTOM_ATTR_PARAMDEF;
6079 return mono_custom_attrs_from_index (image, idx);
6083 * mono_reflection_get_custom_attrs:
6084 * @obj: a reflection object handle
6086 * Return an array with all the custom attributes defined of the
6087 * reflection handle @obj. The objects are fully build.
6090 mono_reflection_get_custom_attrs (MonoObject *obj)
6094 MonoCustomAttrInfo *cinfo = NULL;
6096 MONO_ARCH_SAVE_REGS;
6098 klass = obj->vtable->klass;
6099 /* FIXME: need to handle: Module */
6100 if (klass == mono_defaults.monotype_class) {
6101 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6102 klass = mono_class_from_mono_type (rtype->type);
6103 cinfo = mono_custom_attrs_from_class (klass);
6104 } else if (strcmp ("Assembly", klass->name) == 0) {
6105 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6106 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6107 } else if (strcmp ("Module", klass->name) == 0) {
6108 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6109 cinfo = mono_custom_attrs_from_module (module->image);
6110 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6111 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6112 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6113 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6114 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6115 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6116 } else if (strcmp ("MonoField", klass->name) == 0) {
6117 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6118 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6119 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6120 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6121 cinfo = mono_custom_attrs_from_method (rmethod->method);
6122 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6123 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6124 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6125 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6126 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6127 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6128 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6129 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6130 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6131 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6132 } else { /* handle other types here... */
6133 g_error ("get custom attrs not yet supported for %s", klass->name);
6137 result = mono_custom_attrs_construct (cinfo);
6139 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6140 result = mono_array_new (mono_domain_get (), klass, 0);
6146 static MonoMethodSignature*
6147 parameters_to_signature (MonoArray *parameters) {
6148 MonoMethodSignature *sig;
6151 count = parameters? mono_array_length (parameters): 0;
6153 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6154 sig->param_count = count;
6155 sig->sentinelpos = -1; /* FIXME */
6156 for (i = 0; i < count; ++i) {
6157 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6158 sig->params [i] = pt->type;
6163 static MonoMethodSignature*
6164 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6165 MonoMethodSignature *sig;
6167 sig = parameters_to_signature (ctor->parameters);
6168 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6169 sig->ret = &mono_defaults.void_class->byval_arg;
6173 static MonoMethodSignature*
6174 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6175 MonoMethodSignature *sig;
6177 sig = parameters_to_signature (method->parameters);
6178 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6179 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6180 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6184 static MonoMethodSignature*
6185 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6186 MonoMethodSignature *sig;
6188 sig = parameters_to_signature (method->parameters);
6189 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6190 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6191 sig->generic_param_count = 0;
6196 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6198 MonoClass *klass = mono_object_class (prop);
6199 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6200 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6201 *name = mono_string_to_utf8 (pb->name);
6202 *type = pb->type->type;
6204 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6205 *name = g_strdup (p->property->name);
6206 if (p->property->get)
6207 *type = p->property->get->signature->ret;
6209 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6214 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6216 MonoClass *klass = mono_object_class (field);
6217 if (strcmp (klass->name, "FieldBuilder") == 0) {
6218 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6219 *name = mono_string_to_utf8 (fb->name);
6220 *type = fb->type->type;
6222 MonoReflectionField *f = (MonoReflectionField *)field;
6223 *name = g_strdup (f->field->name);
6224 *type = f->field->type;
6229 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6232 MonoTypeEnum simple_type;
6234 if ((p-buffer) + 10 >= *buflen) {
6237 newbuf = g_realloc (buffer, *buflen);
6238 p = newbuf + (p-buffer);
6241 argval = ((char*)arg + sizeof (MonoObject));
6242 simple_type = type->type;
6244 switch (simple_type) {
6245 case MONO_TYPE_BOOLEAN:
6250 case MONO_TYPE_CHAR:
6253 swap_with_size (p, argval, 2, 1);
6259 swap_with_size (p, argval, 4, 1);
6265 swap_with_size (p, argval, 8, 1);
6268 case MONO_TYPE_VALUETYPE:
6269 if (type->data.klass->enumtype) {
6270 simple_type = type->data.klass->enum_basetype->type;
6273 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6276 case MONO_TYPE_STRING: {
6283 str = mono_string_to_utf8 ((MonoString*)arg);
6284 slen = strlen (str);
6285 if ((p-buffer) + 10 + slen >= *buflen) {
6289 newbuf = g_realloc (buffer, *buflen);
6290 p = newbuf + (p-buffer);
6293 mono_metadata_encode_value (slen, p, &p);
6294 memcpy (p, str, slen);
6299 case MONO_TYPE_CLASS: {
6307 k = mono_object_class (arg);
6308 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6309 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6310 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6312 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6313 slen = strlen (str);
6314 if ((p-buffer) + 10 + slen >= *buflen) {
6318 newbuf = g_realloc (buffer, *buflen);
6319 p = newbuf + (p-buffer);
6322 mono_metadata_encode_value (slen, p, &p);
6323 memcpy (p, str, slen);
6328 case MONO_TYPE_SZARRAY: {
6333 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6336 len = mono_array_length ((MonoArray*)arg);
6338 *p++ = (len >> 8) & 0xff;
6339 *p++ = (len >> 16) & 0xff;
6340 *p++ = (len >> 24) & 0xff;
6342 *retbuffer = buffer;
6343 eclass = type->data.klass;
6344 for (i = 0; i < len; ++i) {
6345 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6349 /* it may be a boxed value or a Type */
6350 case MONO_TYPE_OBJECT: {
6351 MonoClass *klass = mono_object_class (arg);
6355 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6358 } else if (klass->enumtype) {
6360 } else if (klass == mono_defaults.string_class) {
6361 simple_type = MONO_TYPE_STRING;
6364 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6365 *p++ = simple_type = klass->byval_arg.type;
6368 g_error ("unhandled type in custom attr");
6370 str = type_get_qualified_name (klass->enum_basetype, NULL);
6371 slen = strlen (str);
6372 if ((p-buffer) + 10 + slen >= *buflen) {
6376 newbuf = g_realloc (buffer, *buflen);
6377 p = newbuf + (p-buffer);
6380 mono_metadata_encode_value (slen, p, &p);
6381 memcpy (p, str, slen);
6384 simple_type = klass->enum_basetype->type;
6388 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6391 *retbuffer = buffer;
6395 * mono_reflection_get_custom_attrs_blob:
6396 * @ctor: custom attribute constructor
6397 * @ctorArgs: arguments o the constructor
6403 * Creates the blob of data that needs to be saved in the metadata and that represents
6404 * the custom attributed described by @ctor, @ctorArgs etc.
6405 * Returns: a Byte array representing the blob of data.
6408 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6411 MonoMethodSignature *sig;
6416 MONO_ARCH_SAVE_REGS;
6418 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6419 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6421 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6423 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6425 p = buffer = g_malloc (buflen);
6426 /* write the prolog */
6429 for (i = 0; i < sig->param_count; ++i) {
6430 arg = mono_array_get (ctorArgs, MonoObject*, i);
6431 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6435 i += mono_array_length (properties);
6437 i += mono_array_length (fields);
6439 *p++ = (i >> 8) & 0xff;
6442 for (i = 0; i < mono_array_length (properties); ++i) {
6447 prop = mono_array_get (properties, gpointer, i);
6448 get_prop_name_and_type (prop, &pname, &ptype);
6449 *p++ = 0x54; /* PROPERTY signature */
6451 /* Preallocate a large enough buffer */
6452 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6453 char *str = type_get_qualified_name (ptype, NULL);
6459 len += strlen (pname);
6461 if ((p-buffer) + 20 + len >= buflen) {
6465 newbuf = g_realloc (buffer, buflen);
6466 p = newbuf + (p-buffer);
6470 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6471 char *str = type_get_qualified_name (ptype, NULL);
6472 int slen = strlen (str);
6476 * This seems to be optional...
6479 mono_metadata_encode_value (slen, p, &p);
6480 memcpy (p, str, slen);
6484 mono_metadata_encode_value (ptype->type, p, &p);
6485 if (ptype->type == MONO_TYPE_SZARRAY)
6486 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6488 len = strlen (pname);
6489 mono_metadata_encode_value (len, p, &p);
6490 memcpy (p, pname, len);
6492 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6499 for (i = 0; i < mono_array_length (fields); ++i) {
6504 field = mono_array_get (fields, gpointer, i);
6505 get_field_name_and_type (field, &fname, &ftype);
6506 *p++ = 0x53; /* FIELD signature */
6507 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6508 char *str = type_get_qualified_name (ftype, NULL);
6509 int slen = strlen (str);
6510 if ((p-buffer) + 10 + slen >= buflen) {
6514 newbuf = g_realloc (buffer, buflen);
6515 p = newbuf + (p-buffer);
6520 * This seems to be optional...
6523 mono_metadata_encode_value (slen, p, &p);
6524 memcpy (p, str, slen);
6528 mono_metadata_encode_value (ftype->type, p, &p);
6530 len = strlen (fname);
6531 mono_metadata_encode_value (len, p, &p);
6532 memcpy (p, fname, len);
6534 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6539 g_assert (p - buffer <= buflen);
6540 buflen = p - buffer;
6541 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6542 p = mono_array_addr (result, char, 0);
6543 memcpy (p, buffer, buflen);
6545 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6551 * mono_reflection_setup_internal_class:
6552 * @tb: a TypeBuilder object
6554 * Creates a MonoClass that represents the TypeBuilder.
6555 * This is a trick that lets us simplify a lot of reflection code
6556 * (and will allow us to support Build and Run assemblies easier).
6559 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6561 MonoClass *klass, *parent;
6563 MONO_ARCH_SAVE_REGS;
6565 klass = g_new0 (MonoClass, 1);
6567 klass->image = &tb->module->dynamic_image->image;
6570 /* check so we can compile corlib correctly */
6571 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6572 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6573 parent = tb->parent->type->data.klass;
6575 parent = my_mono_class_from_mono_type (tb->parent->type);
6579 klass->inited = 1; /* we lie to the runtime */
6580 klass->name = mono_string_to_utf8 (tb->name);
6581 klass->name_space = mono_string_to_utf8 (tb->nspace);
6582 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6583 klass->flags = tb->attrs;
6585 klass->element_class = klass;
6586 klass->reflection_info = tb; /* need to pin. */
6588 /* Put into cache so mono_class_get () will find it */
6589 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6592 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6593 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6597 mono_class_setup_parent (klass, parent);
6598 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6599 const char *old_n = klass->name;
6600 /* trick to get relative numbering right when compiling corlib */
6601 klass->name = "BuildingObject";
6602 mono_class_setup_parent (klass, mono_defaults.object_class);
6603 klass->name = old_n;
6605 mono_class_setup_mono_type (klass);
6607 mono_class_setup_supertypes (klass);
6610 * FIXME: handle interfaces.
6613 tb->type.type = &klass->byval_arg;
6615 if (tb->nesting_type) {
6616 g_assert (tb->nesting_type->type);
6617 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6620 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6624 * mono_reflection_setup_generic_class:
6625 * @tb: a TypeBuilder object
6627 * Setup the generic class after all generic parameters have been added.
6630 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6635 MONO_ARCH_SAVE_REGS;
6637 klass = my_mono_class_from_mono_type (tb->type.type);
6639 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6641 if (klass->gen_params || (count == 0))
6644 klass->num_gen_params = count;
6645 klass->gen_params = g_new0 (MonoGenericParam, count);
6647 for (i = 0; i < count; i++) {
6648 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6649 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6654 * mono_reflection_create_internal_class:
6655 * @tb: a TypeBuilder object
6657 * Actually create the MonoClass that is associated with the TypeBuilder.
6660 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6664 MONO_ARCH_SAVE_REGS;
6666 klass = my_mono_class_from_mono_type (tb->type.type);
6668 if (klass->enumtype && klass->enum_basetype == NULL) {
6669 MonoReflectionFieldBuilder *fb;
6671 g_assert (tb->fields != NULL);
6672 g_assert (mono_array_length (tb->fields) >= 1);
6674 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6676 klass->enum_basetype = fb->type->type;
6677 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6678 if (!klass->element_class)
6679 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6680 klass->instance_size = klass->element_class->instance_size;
6681 klass->size_inited = 1;
6683 * this is almost safe to do with enums and it's needed to be able
6684 * to create objects of the enum type (for use in SetConstant).
6686 /* FIXME: Does this mean enums can't have method overrides ? */
6687 mono_class_setup_vtable (klass, NULL, 0);
6691 static MonoMarshalSpec*
6692 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6693 MonoReflectionMarshal *minfo)
6695 MonoMarshalSpec *res;
6697 res = g_new0 (MonoMarshalSpec, 1);
6698 res->native = minfo->type;
6700 switch (minfo->type) {
6701 case MONO_NATIVE_LPARRAY:
6702 res->data.array_data.elem_type = minfo->eltype;
6703 res->data.array_data.param_num = 0; /* Not yet */
6704 res->data.array_data.num_elem = minfo->count;
6707 case MONO_NATIVE_BYVALTSTR:
6708 case MONO_NATIVE_BYVALARRAY:
6709 res->data.array_data.num_elem = minfo->count;
6712 case MONO_NATIVE_CUSTOM:
6713 if (minfo->marshaltyperef)
6714 res->data.custom_data.custom_name =
6715 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6717 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6728 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6729 ReflectionMethodBuilder *rmb,
6730 MonoMethodSignature *sig)
6733 MonoMethodNormal *pm;
6734 MonoMarshalSpec **specs;
6735 MonoReflectionMethodAux *method_aux;
6738 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6739 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6740 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6743 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6745 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6747 pm = (MonoMethodNormal*)m;
6750 m->flags = rmb->attrs;
6751 m->iflags = rmb->iattrs;
6752 m->name = mono_string_to_utf8 (rmb->name);
6756 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6758 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6759 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6762 m->signature->pinvoke = 1;
6763 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6765 m->signature->pinvoke = 1;
6767 } else if (!m->klass->dummy &&
6768 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6769 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6770 MonoMethodHeader *header;
6772 gint32 max_stack, i;
6773 gint32 num_locals = 0;
6774 gint32 num_clauses = 0;
6778 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6779 code_size = rmb->ilgen->code_len;
6780 max_stack = rmb->ilgen->max_stack;
6781 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6782 if (rmb->ilgen->ex_handlers)
6783 num_clauses = method_count_clauses (rmb->ilgen);
6786 code = mono_array_addr (rmb->code, guint8, 0);
6787 code_size = mono_array_length (rmb->code);
6788 /* we probably need to run a verifier on the code... */
6798 header = g_malloc0 (sizeof (MonoMethodHeader) +
6799 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6800 header->code_size = code_size;
6801 header->code = g_malloc (code_size);
6802 memcpy ((char*)header->code, code, code_size);
6803 header->max_stack = max_stack;
6804 header->init_locals = rmb->init_locals;
6805 header->num_locals = num_locals;
6807 for (i = 0; i < num_locals; ++i) {
6808 MonoReflectionLocalBuilder *lb =
6809 mono_array_get (rmb->ilgen->locals,
6810 MonoReflectionLocalBuilder*, i);
6812 header->locals [i] = g_new0 (MonoType, 1);
6813 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6816 header->num_clauses = num_clauses;
6818 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6823 if (rmb->generic_params) {
6824 int count = mono_array_length (rmb->generic_params);
6825 header->gen_params = g_new0 (MonoGenericParam, count);
6826 for (i = 0; i < count; i++) {
6827 MonoReflectionGenericParam *gp =
6828 mono_array_get (rmb->generic_params,
6829 MonoReflectionGenericParam*, i);
6831 header->gen_params [i] = *gp->type.type->data.generic_param;
6835 pm->header = header;
6839 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6842 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6844 for (i = 0; i < rmb->nrefs; ++i)
6845 mw->data = g_list_append (mw->data, rmb->refs [i]);
6850 /* Parameter names */
6853 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6854 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6855 for (i = 0; i <= m->signature->param_count; ++i) {
6856 MonoReflectionParamBuilder *pb;
6857 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6859 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6861 if (!method_aux->param_cattr)
6862 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6863 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6869 /* Parameter marshalling */
6872 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6873 MonoReflectionParamBuilder *pb;
6874 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6875 if (pb->marshal_info) {
6877 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6878 specs [pb->position] =
6879 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6883 if (specs != NULL) {
6885 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6886 method_aux->param_marshall = specs;
6889 if (klass->image->dynamic && method_aux)
6890 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6896 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6898 ReflectionMethodBuilder rmb;
6899 MonoMethodSignature *sig;
6901 sig = ctor_builder_to_signature (mb);
6903 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6905 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6906 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6908 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6909 /* ilgen is no longer needed */
6917 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6919 ReflectionMethodBuilder rmb;
6920 MonoMethodSignature *sig;
6922 sig = method_builder_to_signature (mb);
6924 reflection_methodbuilder_from_method_builder (&rmb, mb);
6926 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6927 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6929 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6930 /* ilgen is no longer needed */
6936 static MonoClassField*
6937 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6939 MonoClassField *field;
6946 field = g_new0 (MonoClassField, 1);
6948 field->name = mono_string_to_utf8 (fb->name);
6950 /* FIXME: handle type modifiers */
6951 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6952 field->type->attrs = fb->attrs;
6954 field->type = fb->type->type;
6956 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6957 field->data = mono_array_addr (fb->rva_data, char, 0);
6958 if (fb->offset != -1)
6959 field->offset = fb->offset;
6960 field->parent = klass;
6962 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6964 if (fb->def_value) {
6965 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6966 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6967 field->def_value = g_new0 (MonoConstant, 1);
6968 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6969 /* Copy the data from the blob since it might get realloc-ed */
6970 p = assembly->blob.data + idx;
6971 len = mono_metadata_decode_blob_size (p, &p2);
6973 field->def_value->value = g_malloc (len);
6974 memcpy (field->def_value->value, p, len);
6981 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
6982 MonoType **types, MonoType *nested_in)
6985 MonoReflectionTypeBuilder *tb = NULL;
6986 MonoGenericInst *ginst;
6991 klass = mono_class_from_mono_type (type->type);
6992 if (!klass->gen_params && !klass->generic_inst &&
6993 !(klass->nested_in && klass->nested_in->gen_params))
6996 mono_loader_lock ();
6998 domain = mono_object_domain (type);
7000 ginst = g_new0 (MonoGenericInst, 1);
7002 if (!klass->generic_inst) {
7003 ginst->type_argc = type_argc;
7004 ginst->type_argv = types;
7006 for (i = 0; i < ginst->type_argc; ++i) {
7007 if (!ginst->is_open)
7008 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7011 ginst->generic_type = &klass->byval_arg;
7013 MonoGenericInst *kginst = klass->generic_inst;
7015 ginst->type_argc = kginst->type_argc;
7016 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7018 for (i = 0; i < ginst->type_argc; i++) {
7019 MonoType *t = kginst->type_argv [i];
7021 if (t->type == MONO_TYPE_VAR)
7022 t = types [t->data.generic_param->num];
7024 if (!ginst->is_open)
7025 ginst->is_open = mono_class_is_open_constructed_type (t);
7027 ginst->type_argv [i] = t;
7030 ginst->generic_type = kginst->generic_type;
7033 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7036 mono_loader_unlock ();
7040 ginst->context = g_new0 (MonoGenericContext, 1);
7041 ginst->context->ginst = ginst;
7043 geninst = g_new0 (MonoType, 1);
7044 geninst->type = MONO_TYPE_GENERICINST;
7045 geninst->data.generic_inst = ginst;
7047 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7048 tb = (MonoReflectionTypeBuilder *) type;
7050 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7051 ginst->is_dynamic = TRUE;
7052 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7053 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7054 MonoReflectionType *rgt = rgi->generic_type;
7056 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7057 tb = (MonoReflectionTypeBuilder *) rgt;
7059 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7060 ginst->is_dynamic = TRUE;
7062 icount = klass->interface_count;
7064 ginst->ifaces = g_new0 (MonoType *, icount);
7065 ginst->count_ifaces = icount;
7067 for (i = 0; i < icount; i++) {
7068 MonoReflectionType *itype;
7071 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7073 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7074 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7075 if (!ginst->ifaces [i])
7076 ginst->ifaces [i] = itype->type;
7079 ginst->nested_in = nested_in;
7081 mono_class_create_generic (ginst);
7083 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7085 mono_loader_unlock ();
7091 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7093 MonoClass *klass, *pklass = NULL, *oklass = NULL;
7094 MonoReflectionType *parent = NULL, *outer = NULL;
7095 MonoType *geninst, *nested_in = NULL;
7096 MonoReflectionTypeBuilder *tb = NULL;
7097 MonoGenericInst *ginst;
7100 domain = mono_object_domain (type);
7101 klass = mono_class_from_mono_type (type->type);
7103 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7104 tb = (MonoReflectionTypeBuilder *) type;
7107 parent = tb->parent;
7108 pklass = mono_class_from_mono_type (parent->type);
7110 if (tb->nesting_type) {
7111 outer = tb->nesting_type;
7112 oklass = mono_class_from_mono_type (outer->type);
7115 pklass = klass->parent;
7117 parent = mono_type_get_object (domain, &pklass->byval_arg);
7118 oklass = klass->nested_in;
7120 outer = mono_type_get_object (domain, &oklass->byval_arg);
7124 nested_in = mono_reflection_bind_generic_parameters (outer, oklass->num_gen_params, types);
7126 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, nested_in);
7130 ginst = geninst->data.generic_inst;
7132 if (pklass && pklass->generic_inst)
7133 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7139 mono_reflection_generic_inst_get_nested_types (MonoReflectionGenericInst *type)
7141 MonoReflectionTypeBuilder *tb;
7142 MonoGenericInst *ginst;
7145 ginst = type->type.type->data.generic_inst;
7149 if (strcmp (((MonoObject *) type->generic_type)->vtable->klass->name, "TypeBuilder"))
7152 tb = (MonoReflectionTypeBuilder *) type->generic_type;
7154 ginst->count_nested = tb->subtypes ? mono_array_length (tb->subtypes) : 0;
7155 ginst->nested = g_new0 (MonoType *, ginst->count_nested);
7157 for (i = 0; i < ginst->count_nested; i++) {
7158 MonoReflectionTypeBuilder *ntype;
7162 ntype = mono_array_get (tb->subtypes, gpointer, i);
7163 ntype_argc = ntype->generic_params ? mono_array_length (ntype->generic_params) : 0;
7165 if (ntype_argc > ginst->type_argc) {
7166 ntypes = g_new0 (MonoType *, ntype_argc);
7168 for (j = 0; j < ginst->type_argc; j++)
7169 ntypes [j] = ginst->type_argv [j];
7171 for (j = ginst->type_argc; j < ntype_argc; j++) {
7172 MonoReflectionGenericParam *ngparam;
7173 MonoType *pt = g_new0 (MonoType, 1);
7175 ngparam = mono_array_get (ntype->generic_params, gpointer, j);
7177 pt->type = MONO_TYPE_VAR;
7178 pt->data.generic_param = ngparam->type.type->data.generic_param;
7183 ntypes = ginst->type_argv;
7185 ginst->nested [i] = mono_reflection_bind_generic_parameters ((MonoReflectionType *) ntype, ntype_argc, ntypes);
7189 MonoReflectionMethod*
7190 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7192 MonoMethod *method, *inflated;
7193 MonoReflectionMethodBuilder *mb = NULL;
7194 MonoGenericMethod *gmethod;
7195 MonoGenericContext *context;
7198 MONO_ARCH_SAVE_REGS;
7199 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7200 MonoReflectionTypeBuilder *tb;
7203 mb = (MonoReflectionMethodBuilder *) rmethod;
7204 tb = (MonoReflectionTypeBuilder *) mb->type;
7205 klass = mono_class_from_mono_type (tb->type.type);
7207 method = methodbuilder_to_mono_method (klass, mb);
7209 method = rmethod->method;
7211 count = method->signature->generic_param_count;
7212 if (count != mono_array_length (types))
7215 gmethod = g_new0 (MonoGenericMethod, 1);
7216 gmethod->mtype_argc = count;
7217 gmethod->mtype_argv = g_new0 (MonoType *, count);
7218 for (i = 0; i < count; i++) {
7219 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7220 gmethod->mtype_argv [i] = garg->type;
7223 context = g_new0 (MonoGenericContext, 1);
7224 context->ginst = method->klass->generic_inst;
7225 context->gmethod = gmethod;
7227 inflated = mono_class_inflate_generic_method (method, context, NULL);
7229 return mono_method_get_object (
7230 mono_object_domain (rmethod), inflated, NULL);
7234 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7236 MonoGenericMethod *gmethod;
7237 MonoGenericInst *ginst;
7238 MonoGenericContext *context;
7240 ginst = type->type.type->data.generic_inst;
7242 gmethod = g_new0 (MonoGenericMethod, 1);
7243 gmethod->reflection_info = obj;
7245 context = g_new0 (MonoGenericContext, 1);
7246 context->ginst = ginst;
7247 context->gmethod = gmethod;
7249 return mono_class_inflate_generic_method (method, context, ginst->klass);
7253 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7258 klass = mono_class_from_mono_type (type->type.type);
7260 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7261 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7262 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7263 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7264 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7265 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7266 method = ((MonoReflectionMethod *) obj)->method;
7268 method = NULL; /* prevent compiler warning */
7269 g_assert_not_reached ();
7272 return inflate_mono_method (type, method, obj);
7276 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7277 MonoArray *methods, MonoArray *ctors,
7278 MonoArray *fields, MonoArray *properties,
7281 MonoGenericInst *ginst;
7282 MonoDynamicGenericInst *dginst;
7283 MonoClass *klass, *gklass, *pklass;
7286 MONO_ARCH_SAVE_REGS;
7288 klass = mono_class_from_mono_type (type->type.type);
7289 ginst = type->type.type->data.generic_inst;
7291 if (ginst->initialized)
7294 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7296 gklass = mono_class_from_mono_type (ginst->generic_type);
7297 mono_class_init (gklass);
7300 pklass = mono_class_from_mono_type (ginst->parent);
7302 pklass = gklass->parent;
7304 mono_class_setup_parent (klass, pklass);
7306 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7307 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7308 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7309 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7310 dginst->count_events = events ? mono_array_length (events) : 0;
7312 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7313 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7314 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7315 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7316 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7318 for (i = 0; i < dginst->count_methods; i++) {
7319 MonoObject *obj = mono_array_get (methods, gpointer, i);
7321 dginst->methods [i] = inflate_method (type, obj);
7324 for (i = 0; i < dginst->count_ctors; i++) {
7325 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7327 dginst->ctors [i] = inflate_method (type, obj);
7330 for (i = 0; i < dginst->count_fields; i++) {
7331 MonoObject *obj = mono_array_get (fields, gpointer, i);
7332 MonoClassField *field;
7334 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7335 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7336 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7337 field = ((MonoReflectionField *) obj)->field;
7339 field = NULL; /* prevent compiler warning */
7340 g_assert_not_reached ();
7343 dginst->fields [i] = *field;
7344 dginst->fields [i].generic_type = field->type;
7345 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7348 for (i = 0; i < dginst->count_properties; i++) {
7349 MonoObject *obj = mono_array_get (properties, gpointer, i);
7350 MonoProperty *property = &dginst->properties [i];
7352 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7353 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7355 property->parent = klass;
7356 property->attrs = pb->attrs;
7357 property->name = mono_string_to_utf8 (pb->name);
7359 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7361 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7362 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7363 *property = *((MonoReflectionProperty *) obj)->property;
7366 property->get = inflate_mono_method (type, property->get, NULL);
7368 property->set = inflate_mono_method (type, property->set, NULL);
7370 g_assert_not_reached ();
7373 for (i = 0; i < dginst->count_events; i++) {
7374 MonoObject *obj = mono_array_get (events, gpointer, i);
7375 MonoEvent *event = &dginst->events [i];
7377 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7378 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7380 event->parent = klass;
7381 event->attrs = eb->attrs;
7382 event->name = mono_string_to_utf8 (eb->name);
7384 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7385 if (eb->remove_method)
7386 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7387 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7388 *event = *((MonoReflectionEvent *) obj)->event;
7391 event->add = inflate_mono_method (type, event->add, NULL);
7393 event->remove = inflate_mono_method (type, event->remove, NULL);
7395 g_assert_not_reached ();
7398 ginst->initialized = TRUE;
7402 ensure_runtime_vtable (MonoClass *klass)
7404 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7405 int i, num, j, onum;
7406 MonoMethod **overrides;
7408 if (!tb || klass->wastypebuilder)
7411 ensure_runtime_vtable (klass->parent);
7413 num = tb->ctors? mono_array_length (tb->ctors): 0;
7414 num += tb->num_methods;
7415 klass->method.count = num;
7416 klass->methods = g_new (MonoMethod*, num);
7417 num = tb->ctors? mono_array_length (tb->ctors): 0;
7418 for (i = 0; i < num; ++i)
7419 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7420 num = tb->num_methods;
7422 for (i = 0; i < num; ++i)
7423 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7425 klass->wastypebuilder = TRUE;
7426 if (tb->interfaces) {
7427 klass->interface_count = mono_array_length (tb->interfaces);
7428 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7429 for (i = 0; i < klass->interface_count; ++i) {
7430 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7431 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7435 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7436 for (i = 0; i < klass->method.count; ++i)
7437 klass->methods [i]->slot = i;
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)
7450 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7454 for (i = 0; i < tb->num_methods; ++i) {
7455 MonoReflectionMethodBuilder *mb =
7456 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7457 if (mb->override_method) {
7458 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7459 overrides [onum * 2] =
7460 mb->override_method->method;
7461 overrides [onum * 2 + 1] =
7464 g_assert (mb->mhandle);
7471 mono_class_setup_vtable (klass, overrides, onum);
7475 typebuilder_setup_fields (MonoClass *klass)
7477 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7478 MonoReflectionFieldBuilder *fb;
7479 MonoClassField *field;
7484 klass->field.count = tb->num_fields;
7485 klass->field.first = 0;
7486 klass->field.last = klass->field.count;
7488 if (!klass->field.count)
7491 klass->fields = g_new0 (MonoClassField, klass->field.count);
7493 for (i = 0; i < klass->field.count; ++i) {
7494 fb = mono_array_get (tb->fields, gpointer, i);
7495 field = &klass->fields [i];
7496 field->name = mono_string_to_utf8 (fb->name);
7498 /* FIXME: handle type modifiers */
7499 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7500 field->type->attrs = fb->attrs;
7502 field->type = fb->type->type;
7504 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7505 field->data = mono_array_addr (fb->rva_data, char, 0);
7506 if (fb->offset != -1)
7507 field->offset = fb->offset;
7508 field->parent = klass;
7510 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7512 if (fb->def_value) {
7513 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7514 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7515 field->def_value = g_new0 (MonoConstant, 1);
7516 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7517 /* Copy the data from the blob since it might get realloc-ed */
7518 p = assembly->blob.data + idx;
7519 len = mono_metadata_decode_blob_size (p, &p2);
7521 field->def_value->value = g_malloc (len);
7522 memcpy (field->def_value->value, p, len);
7525 mono_class_layout_fields (klass);
7529 typebuilder_setup_properties (MonoClass *klass)
7531 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7532 MonoReflectionPropertyBuilder *pb;
7535 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7536 klass->property.first = 0;
7537 klass->property.last = klass->property.count;
7539 klass->properties = g_new0 (MonoProperty, klass->property.count);
7540 for (i = 0; i < klass->property.count; ++i) {
7541 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7542 klass->properties [i].parent = klass;
7543 klass->properties [i].attrs = pb->attrs;
7544 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7546 klass->properties [i].get = pb->get_method->mhandle;
7548 klass->properties [i].set = pb->set_method->mhandle;
7552 MonoReflectionEvent *
7553 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7555 MonoEvent *event = g_new0 (MonoEvent, 1);
7559 klass = my_mono_class_from_mono_type (tb->type.type);
7561 event->parent = klass;
7562 event->attrs = eb->attrs;
7563 event->name = mono_string_to_utf8 (eb->name);
7565 event->add = eb->add_method->mhandle;
7566 if (eb->remove_method)
7567 event->remove = eb->remove_method->mhandle;
7568 if (eb->raise_method)
7569 event->raise = eb->raise_method->mhandle;
7571 if (eb->other_methods) {
7572 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7573 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7574 MonoReflectionMethodBuilder *mb =
7575 mono_array_get (eb->other_methods,
7576 MonoReflectionMethodBuilder*, j);
7577 event->other [j] = mb->mhandle;
7581 return mono_event_get_object (mono_object_domain (tb), klass, event);
7585 typebuilder_setup_events (MonoClass *klass)
7587 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7588 MonoReflectionEventBuilder *eb;
7591 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7592 klass->event.first = 0;
7593 klass->event.last = klass->event.count;
7595 klass->events = g_new0 (MonoEvent, klass->event.count);
7596 for (i = 0; i < klass->event.count; ++i) {
7597 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7598 klass->events [i].parent = klass;
7599 klass->events [i].attrs = eb->attrs;
7600 klass->events [i].name = mono_string_to_utf8 (eb->name);
7602 klass->events [i].add = eb->add_method->mhandle;
7603 if (eb->remove_method)
7604 klass->events [i].remove = eb->remove_method->mhandle;
7605 if (eb->raise_method)
7606 klass->events [i].raise = eb->raise_method->mhandle;
7608 if (eb->other_methods) {
7609 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7610 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7611 MonoReflectionMethodBuilder *mb =
7612 mono_array_get (eb->other_methods,
7613 MonoReflectionMethodBuilder*, j);
7614 klass->events [i].other [j] = mb->mhandle;
7621 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7624 MonoReflectionType* res;
7626 MONO_ARCH_SAVE_REGS;
7628 klass = my_mono_class_from_mono_type (tb->type.type);
7630 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7633 * Fields to set in klass:
7634 * the various flags: delegate/unicode/contextbound etc.
7637 klass->flags = tb->attrs;
7639 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7640 /* No need to fully construct the type */
7641 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7643 /* enums are done right away */
7644 if (!klass->enumtype)
7645 ensure_runtime_vtable (klass);
7647 /* fields and object layout */
7648 if (klass->parent) {
7649 if (!klass->parent->size_inited)
7650 mono_class_init (klass->parent);
7651 klass->instance_size += klass->parent->instance_size;
7652 klass->class_size += klass->parent->class_size;
7653 klass->min_align = klass->parent->min_align;
7655 klass->instance_size = sizeof (MonoObject);
7656 klass->min_align = 1;
7659 /* FIXME: handle packing_size and instance_size */
7660 typebuilder_setup_fields (klass);
7662 typebuilder_setup_properties (klass);
7664 typebuilder_setup_events (klass);
7666 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7667 /* with enums res == tb: need to fix that. */
7668 if (!klass->enumtype)
7669 g_assert (res != (MonoReflectionType*)tb);
7673 MonoReflectionGenericParam *
7674 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7676 static MonoClass *System_Reflection_MonoGenericParam;
7678 MonoGenericParam *param;
7679 MonoReflectionGenericParam *res;
7682 if (!System_Reflection_MonoGenericParam) {
7683 System_Reflection_MonoGenericParam = mono_class_from_name (
7684 mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7685 g_assert (System_Reflection_MonoGenericParam);
7688 param = g_new0 (MonoGenericParam, 1);
7691 tb = (MonoReflectionTypeBuilder *) mb->type;
7693 domain = mono_object_domain (tb);
7694 image = (MonoImage*)tb->module->dynamic_image;
7696 param->method = NULL;
7697 param->name = mono_string_to_utf8 (name);
7700 res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7701 res->type.type = g_new0 (MonoType, 1);
7702 res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7703 res->type.type->data.generic_param = param;
7705 res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7713 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7715 MonoGenericParam *param;
7716 MonoReflectionMethodBuilder *mb = NULL;
7717 MonoReflectionTypeBuilder *tb;
7721 param = gparam->type.type->data.generic_param;
7722 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7723 param->constraints = g_new0 (MonoClass *, count + 1);
7724 for (i = 0; i < count; i++) {
7725 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7727 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7730 if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7731 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7732 tb = (MonoReflectionTypeBuilder *) mb->type;
7734 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7736 image = (MonoImage*)tb->module->dynamic_image;
7738 param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7739 param->pklass->reflection_info = gparam;
7741 gparam->initialized = TRUE;
7745 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7747 MonoDynamicImage *assembly = sig->module->dynamic_image;
7748 guint32 na = mono_array_length (sig->arguments);
7753 MONO_ARCH_SAVE_REGS;
7755 p = buf = g_malloc (10 + na * 10);
7757 mono_metadata_encode_value (0x07, p, &p);
7758 mono_metadata_encode_value (na, p, &p);
7759 for (i = 0; i < na; ++i) {
7760 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7761 encode_reflection_type (assembly, type, p, &p);
7765 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7766 p = mono_array_addr (result, char, 0);
7767 memcpy (p, buf, buflen);
7774 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7776 MonoDynamicImage *assembly = sig->module->dynamic_image;
7777 guint32 na = mono_array_length (sig->arguments);
7782 MONO_ARCH_SAVE_REGS;
7784 p = buf = g_malloc (10 + na * 10);
7786 mono_metadata_encode_value (0x06, p, &p);
7787 for (i = 0; i < na; ++i) {
7788 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7789 encode_reflection_type (assembly, type, p, &p);
7793 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7794 p = mono_array_addr (result, char, 0);
7795 memcpy (p, buf, buflen);
7802 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7804 ReflectionMethodBuilder rmb;
7805 MonoMethodSignature *sig;
7808 sig = dynamic_method_to_signature (mb);
7810 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7813 * Resolve references.
7815 rmb.nrefs = mb->nrefs;
7816 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7817 for (i = 0; i < mb->nrefs; ++i) {
7818 gpointer ref = resolve_object (mb->module->image,
7819 mono_array_get (mb->refs, MonoObject*, i));
7822 mono_raise_exception (mono_get_exception_type_load (NULL));
7829 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7833 /* ilgen is no longer needed */
7838 * mono_reflection_lookup_dynamic_token:
7840 * Finish the Builder object pointed to by TOKEN and return the corresponding
7841 * runtime structure.
7844 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7846 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7849 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7852 return resolve_object (image, obj);
7856 resolve_object (MonoImage *image, MonoObject *obj)
7858 gpointer result = NULL;
7860 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7861 result = mono_string_intern ((MonoString*)obj);
7864 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7865 MonoReflectionType *tb = (MonoReflectionType*)obj;
7866 result = mono_class_from_mono_type (tb->type);
7869 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7870 result = ((MonoReflectionMethod*)obj)->method;
7873 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7874 result = ((MonoReflectionMethod*)obj)->method;
7877 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7878 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7879 result = mb->mhandle;
7881 /* Type is not yet created */
7882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7884 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7887 * Hopefully this has been filled in by calling CreateType() on the
7891 * TODO: This won't work if the application finishes another
7892 * TypeBuilder instance instead of this one.
7894 result = mb->mhandle;
7897 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7898 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7900 result = cb->mhandle;
7902 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7904 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7905 result = cb->mhandle;
7908 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7909 result = ((MonoReflectionField*)obj)->field;
7912 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7913 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7914 result = fb->handle;
7917 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7919 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7920 result = fb->handle;
7923 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7924 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7927 klass = tb->type.type->data.klass;
7928 if (klass->wastypebuilder) {
7929 /* Already created */
7933 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7934 result = tb->type.type->data.klass;
7938 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7939 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7940 MonoMethodSignature *sig;
7943 if (helper->arguments)
7944 nargs = mono_array_length (helper->arguments);
7948 sig = mono_metadata_signature_alloc (image, nargs);
7949 sig->explicit_this = helper->call_conv & 64;
7950 sig->hasthis = helper->call_conv & 32;
7952 if (helper->call_conv == 0) /* unmanaged */
7953 sig->call_convention = helper->unmanaged_call_conv - 1;
7955 if (helper->call_conv & 0x02)
7956 sig->call_convention = MONO_CALL_VARARG;
7958 sig->call_convention = MONO_CALL_DEFAULT;
7960 sig->param_count = nargs;
7961 /* TODO: Copy type ? */
7962 sig->ret = helper->return_type->type;
7963 for (i = 0; i < nargs; ++i) {
7964 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7965 sig->params [i] = rt->type;
7971 g_print (obj->vtable->klass->name);
7972 g_assert_not_reached ();