2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
15 #include "mono/utils/mono-digest.h"
16 #include "mono/utils/mono-membar.h"
17 #include "mono/metadata/reflection.h"
18 #include "mono/metadata/tabledefs.h"
19 #include "mono/metadata/metadata-internals.h"
20 #include <mono/metadata/profiler-private.h>
21 #include "mono/metadata/class-internals.h"
22 #include "mono/metadata/gc-internal.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/domain-internals.h"
25 #include "mono/metadata/opcodes.h"
26 #include "mono/metadata/assembly.h"
27 #include "mono/metadata/object-internals.h"
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/security-manager.h>
39 #include "mono-endian.h"
40 #include <mono/metadata/gc-internal.h>
41 #include <mono/metadata/mempool-internals.h>
44 static void* reflection_info_desc = NULL;
45 #define MOVING_GC_REGISTER(addr) do { \
46 if (!reflection_info_desc) { \
48 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
50 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
53 #define MOVING_GC_REGISTER(addr)
62 #define TEXT_OFFSET 512
63 #define CLI_H_SIZE 136
64 #define FILE_ALIGN 512
65 #define VIRT_ALIGN 8192
66 #define START_TEXT_RVA 0x00002000
69 MonoReflectionILGen *ilgen;
70 MonoReflectionType *rtype;
71 MonoArray *parameters;
72 MonoArray *generic_params;
73 MonoGenericContainer *generic_container;
79 guint32 *table_idx; /* note: it's a pointer */
83 MonoBoolean init_locals;
84 MonoBoolean skip_visibility;
85 MonoArray *return_modreq;
86 MonoArray *return_modopt;
87 MonoArray *param_modreq;
88 MonoArray *param_modopt;
89 MonoArray *permissions;
94 int charset, extra_flags, native_cc;
95 MonoString *dll, *dllentry;
96 } ReflectionMethodBuilder;
100 MonoReflectionGenericParam *gparam;
101 } GenericParamTableEntry;
103 const unsigned char table_sizes [MONO_TABLE_NUM] = {
113 MONO_INTERFACEIMPL_SIZE,
114 MONO_MEMBERREF_SIZE, /* 0x0A */
116 MONO_CUSTOM_ATTR_SIZE,
117 MONO_FIELD_MARSHAL_SIZE,
118 MONO_DECL_SECURITY_SIZE,
119 MONO_CLASS_LAYOUT_SIZE,
120 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
121 MONO_STAND_ALONE_SIGNATURE_SIZE,
125 MONO_PROPERTY_MAP_SIZE,
128 MONO_METHOD_SEMA_SIZE,
129 MONO_METHODIMPL_SIZE,
130 MONO_MODULEREF_SIZE, /* 0x1A */
136 MONO_ASSEMBLY_SIZE, /* 0x20 */
137 MONO_ASSEMBLY_PROCESSOR_SIZE,
138 MONO_ASSEMBLYOS_SIZE,
139 MONO_ASSEMBLYREF_SIZE,
140 MONO_ASSEMBLYREFPROC_SIZE,
141 MONO_ASSEMBLYREFOS_SIZE,
145 MONO_NESTED_CLASS_SIZE,
147 MONO_GENERICPARAM_SIZE, /* 0x2A */
148 MONO_METHODSPEC_SIZE,
149 MONO_GENPARCONSTRAINT_SIZE
153 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
154 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
155 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
156 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
157 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
158 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
159 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
160 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
161 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
162 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
163 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
164 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
173 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
175 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
176 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
177 static CRITICAL_SECTION reflection_mutex;
180 mono_reflection_init (void)
182 InitializeCriticalSection (&reflection_mutex);
186 sigbuffer_init (SigBuffer *buf, int size)
188 buf->buf = g_malloc (size);
190 buf->end = buf->buf + size;
194 sigbuffer_make_room (SigBuffer *buf, int size)
196 if (buf->end - buf->p < size) {
197 int new_size = buf->end - buf->buf + size + 32;
198 char *p = g_realloc (buf->buf, new_size);
199 size = buf->p - buf->buf;
202 buf->end = buf->buf + new_size;
207 sigbuffer_add_value (SigBuffer *buf, guint32 val)
209 sigbuffer_make_room (buf, 6);
210 mono_metadata_encode_value (val, buf->p, &buf->p);
214 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
216 sigbuffer_make_room (buf, 1);
222 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
224 sigbuffer_make_room (buf, size);
225 memcpy (buf->p, p, size);
230 sigbuffer_free (SigBuffer *buf)
238 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
242 image_g_malloc (MonoImage *image, guint size)
245 return mono_image_alloc (image, size);
247 return g_malloc (size);
253 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
257 image_g_malloc0 (MonoImage *image, guint size)
260 return mono_image_alloc0 (image, size);
262 return g_malloc0 (size);
266 image_strdup (MonoImage *image, const char *s)
269 return mono_image_strdup (image, s);
274 #define image_g_new(image,struct_type, n_structs) \
275 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
277 #define image_g_new0(image,struct_type, n_structs) \
278 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
282 alloc_table (MonoDynamicTable *table, guint nrows)
285 g_assert (table->columns);
286 if (nrows + 1 >= table->alloc_rows) {
287 while (nrows + 1 >= table->alloc_rows) {
288 if (table->alloc_rows == 0)
289 table->alloc_rows = 16;
291 table->alloc_rows *= 2;
294 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
299 make_room_in_stream (MonoDynamicStream *stream, int size)
301 if (size <= stream->alloc_size)
304 while (stream->alloc_size <= size) {
305 if (stream->alloc_size < 4096)
306 stream->alloc_size = 4096;
308 stream->alloc_size *= 2;
311 stream->data = g_realloc (stream->data, stream->alloc_size);
315 string_heap_insert (MonoDynamicStream *sh, const char *str)
319 gpointer oldkey, oldval;
321 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
322 return GPOINTER_TO_UINT (oldval);
324 len = strlen (str) + 1;
327 make_room_in_stream (sh, idx + len);
330 * We strdup the string even if we already copy them in sh->data
331 * so that the string pointers in the hash remain valid even if
332 * we need to realloc sh->data. We may want to avoid that later.
334 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
335 memcpy (sh->data + idx, str, len);
341 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
343 char *name = mono_string_to_utf8 (str);
345 idx = string_heap_insert (sh, name);
351 string_heap_init (MonoDynamicStream *sh)
354 sh->alloc_size = 4096;
355 sh->data = g_malloc (4096);
356 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
357 string_heap_insert (sh, "");
361 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
365 make_room_in_stream (stream, stream->index + len);
366 memcpy (stream->data + stream->index, data, len);
368 stream->index += len;
370 * align index? Not without adding an additional param that controls it since
371 * we may store a blob value in pieces.
377 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
381 make_room_in_stream (stream, stream->index + len);
382 memset (stream->data + stream->index, 0, len);
384 stream->index += len;
389 stream_data_align (MonoDynamicStream *stream)
392 guint32 count = stream->index % 4;
394 /* we assume the stream data will be aligned */
396 mono_image_add_stream_data (stream, buf, 4 - count);
400 mono_blob_entry_hash (const char* str)
404 len = mono_metadata_decode_blob_size (str, &str);
408 for (str += 1; str < end; str++)
409 h = (h << 5) - h + *str;
417 mono_blob_entry_equal (const char *str1, const char *str2) {
421 len = mono_metadata_decode_blob_size (str1, &end1);
422 len2 = mono_metadata_decode_blob_size (str2, &end2);
425 return memcmp (end1, end2, len) == 0;
429 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
433 gpointer oldkey, oldval;
435 copy = g_malloc (s1+s2);
436 memcpy (copy, b1, s1);
437 memcpy (copy + s1, b2, s2);
438 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
440 idx = GPOINTER_TO_UINT (oldval);
442 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
443 mono_image_add_stream_data (&assembly->blob, b2, s2);
444 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
450 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
454 guint32 size = buf->p - buf->buf;
456 g_assert (size <= (buf->end - buf->buf));
457 mono_metadata_encode_value (size, b, &b);
458 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
462 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
463 * dest may be misaligned.
466 swap_with_size (char *dest, const char* val, int len, int nelem) {
467 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
470 for (elem = 0; elem < nelem; ++elem) {
496 g_assert_not_reached ();
502 memcpy (dest, val, len * nelem);
507 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
511 guint32 idx = 0, len;
513 len = str->length * 2;
514 mono_metadata_encode_value (len, b, &b);
515 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
517 char *swapped = g_malloc (2 * mono_string_length (str));
518 const char *p = (const char*)mono_string_chars (str);
520 swap_with_size (swapped, p, 2, mono_string_length (str));
521 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
525 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
530 /* modified version needed to handle building corlib */
532 my_mono_class_from_mono_type (MonoType *type) {
533 switch (type->type) {
534 case MONO_TYPE_ARRAY:
536 case MONO_TYPE_SZARRAY:
537 case MONO_TYPE_GENERICINST:
538 return mono_class_from_mono_type (type);
541 g_assert (type->data.generic_param->pklass);
542 return type->data.generic_param->pklass;
544 /* should be always valid when we reach this case... */
545 return type->data.klass;
550 default_class_from_mono_type (MonoType *type)
552 switch (type->type) {
553 case MONO_TYPE_OBJECT:
554 return mono_defaults.object_class;
556 return mono_defaults.void_class;
557 case MONO_TYPE_BOOLEAN:
558 return mono_defaults.boolean_class;
560 return mono_defaults.char_class;
562 return mono_defaults.sbyte_class;
564 return mono_defaults.byte_class;
566 return mono_defaults.int16_class;
568 return mono_defaults.uint16_class;
570 return mono_defaults.int32_class;
572 return mono_defaults.uint32_class;
574 return mono_defaults.int_class;
576 return mono_defaults.uint_class;
578 return mono_defaults.int64_class;
580 return mono_defaults.uint64_class;
582 return mono_defaults.single_class;
584 return mono_defaults.double_class;
585 case MONO_TYPE_STRING:
586 return mono_defaults.string_class;
588 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
589 g_assert_not_reached ();
596 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
599 MonoGenericInst *class_inst;
604 class_inst = gclass->context.class_inst;
606 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
607 klass = gclass->container_class;
608 sigbuffer_add_value (buf, klass->byval_arg.type);
609 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
611 sigbuffer_add_value (buf, class_inst->type_argc);
612 for (i = 0; i < class_inst->type_argc; ++i)
613 encode_type (assembly, class_inst->type_argv [i], buf);
618 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
621 g_assert_not_reached ();
626 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
630 case MONO_TYPE_BOOLEAN:
644 case MONO_TYPE_STRING:
645 case MONO_TYPE_OBJECT:
646 case MONO_TYPE_TYPEDBYREF:
647 sigbuffer_add_value (buf, type->type);
650 sigbuffer_add_value (buf, type->type);
651 encode_type (assembly, type->data.type, buf);
653 case MONO_TYPE_SZARRAY:
654 sigbuffer_add_value (buf, type->type);
655 encode_type (assembly, &type->data.klass->byval_arg, buf);
657 case MONO_TYPE_VALUETYPE:
658 case MONO_TYPE_CLASS: {
659 MonoClass *k = mono_class_from_mono_type (type);
661 if (k->generic_container) {
662 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
663 encode_generic_class (assembly, gclass, buf);
666 * Make sure we use the correct type.
668 sigbuffer_add_value (buf, k->byval_arg.type);
670 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
671 * otherwise two typerefs could point to the same type, leading to
672 * verification errors.
674 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
678 case MONO_TYPE_ARRAY:
679 sigbuffer_add_value (buf, type->type);
680 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
681 sigbuffer_add_value (buf, type->data.array->rank);
682 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
683 sigbuffer_add_value (buf, 0);
685 case MONO_TYPE_GENERICINST:
686 encode_generic_class (assembly, type->data.generic_class, buf);
690 sigbuffer_add_value (buf, type->type);
691 sigbuffer_add_value (buf, type->data.generic_param->num);
694 g_error ("need to encode type %x", type->type);
699 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
702 sigbuffer_add_value (buf, MONO_TYPE_VOID);
707 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
708 encode_type (assembly, type->type, buf);
712 g_assert_not_reached ();
717 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
722 for (i = 0; i < mono_array_length (modreq); ++i) {
723 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
724 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
725 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
729 for (i = 0; i < mono_array_length (modopt); ++i) {
730 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
731 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
732 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
738 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
742 guint32 nparams = sig->param_count;
748 sigbuffer_init (&buf, 32);
750 * FIXME: vararg, explicit_this, differenc call_conv values...
752 idx = sig->call_convention;
754 idx |= 0x20; /* hasthis */
755 if (sig->generic_param_count)
756 idx |= 0x10; /* generic */
757 sigbuffer_add_byte (&buf, idx);
758 if (sig->generic_param_count)
759 sigbuffer_add_value (&buf, sig->generic_param_count);
760 sigbuffer_add_value (&buf, nparams);
761 encode_type (assembly, sig->ret, &buf);
762 for (i = 0; i < nparams; ++i) {
763 if (i == sig->sentinelpos)
764 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
765 encode_type (assembly, sig->params [i], &buf);
767 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
768 sigbuffer_free (&buf);
773 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
776 * FIXME: reuse code from method_encode_signature().
780 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
781 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
782 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
785 sigbuffer_init (&buf, 32);
786 /* LAMESPEC: all the call conv spec is foobared */
787 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
788 if (mb->call_conv & 2)
789 idx |= 0x5; /* vararg */
790 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
791 idx |= 0x20; /* hasthis */
793 idx |= 0x10; /* generic */
794 sigbuffer_add_byte (&buf, idx);
796 sigbuffer_add_value (&buf, ngparams);
797 sigbuffer_add_value (&buf, nparams + notypes);
798 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
799 encode_reflection_type (assembly, mb->rtype, &buf);
800 for (i = 0; i < nparams; ++i) {
801 MonoArray *modreq = NULL;
802 MonoArray *modopt = NULL;
803 MonoReflectionType *pt;
805 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
806 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
807 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
808 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
809 encode_custom_modifiers (assembly, modreq, modopt, &buf);
810 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
811 encode_reflection_type (assembly, pt, &buf);
814 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
815 for (i = 0; i < notypes; ++i) {
816 MonoReflectionType *pt;
818 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
819 encode_reflection_type (assembly, pt, &buf);
822 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
823 sigbuffer_free (&buf);
828 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
830 MonoDynamicTable *table;
832 guint32 idx, sig_idx;
833 guint nl = mono_array_length (ilgen->locals);
837 sigbuffer_init (&buf, 32);
838 sigbuffer_add_value (&buf, 0x07);
839 sigbuffer_add_value (&buf, nl);
840 for (i = 0; i < nl; ++i) {
841 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
844 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
846 encode_reflection_type (assembly, lb->type, &buf);
848 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
849 sigbuffer_free (&buf);
851 if (assembly->standalonesig_cache == NULL)
852 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
853 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
857 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
858 idx = table->next_idx ++;
860 alloc_table (table, table->rows);
861 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
863 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
865 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
871 method_count_clauses (MonoReflectionILGen *ilgen)
873 guint32 num_clauses = 0;
876 MonoILExceptionInfo *ex_info;
877 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
878 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
879 if (ex_info->handlers)
880 num_clauses += mono_array_length (ex_info->handlers);
888 static MonoExceptionClause*
889 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
891 MonoExceptionClause *clauses;
892 MonoExceptionClause *clause;
893 MonoILExceptionInfo *ex_info;
894 MonoILExceptionBlock *ex_block;
895 guint32 finally_start;
896 int i, j, clause_index;;
898 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
901 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
902 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
903 finally_start = ex_info->start + ex_info->len;
904 if (!ex_info->handlers)
906 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
907 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
908 clause = &(clauses [clause_index]);
910 clause->flags = ex_block->type;
911 clause->try_offset = ex_info->start;
913 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
914 clause->try_len = finally_start - ex_info->start;
916 clause->try_len = ex_info->len;
917 clause->handler_offset = ex_block->start;
918 clause->handler_len = ex_block->len;
919 if (ex_block->extype) {
920 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
922 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
923 clause->data.filter_offset = ex_block->filter_offset;
925 clause->data.filter_offset = 0;
927 finally_start = ex_block->start + ex_block->len;
937 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
943 gint32 num_locals = 0;
944 gint32 num_exception = 0;
947 char fat_header [12];
950 guint32 local_sig = 0;
951 guint32 header_size = 12;
954 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
955 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
959 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
961 code = mb->ilgen->code;
962 code_size = mb->ilgen->code_len;
963 max_stack = mb->ilgen->max_stack;
964 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
965 if (mb->ilgen->ex_handlers)
966 num_exception = method_count_clauses (mb->ilgen);
970 char *name = mono_string_to_utf8 (mb->name);
971 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
972 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
975 mono_raise_exception (exception);
978 code_size = mono_array_length (code);
979 max_stack = 8; /* we probably need to run a verifier on the code... */
982 stream_data_align (&assembly->code);
984 /* check for exceptions, maxstack, locals */
985 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
987 if (code_size < 64 && !(code_size & 1)) {
988 flags = (code_size << 2) | 0x2;
989 } else if (code_size < 32 && (code_size & 1)) {
990 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
994 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
995 /* add to the fixup todo list */
996 if (mb->ilgen && mb->ilgen->num_token_fixups)
997 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
998 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
999 return assembly->text_rva + idx;
1003 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1005 * FIXME: need to set also the header size in fat_flags.
1006 * (and more sects and init locals flags)
1010 fat_flags |= METHOD_HEADER_MORE_SECTS;
1011 if (mb->init_locals)
1012 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1013 fat_header [0] = fat_flags;
1014 fat_header [1] = (header_size / 4 ) << 4;
1015 short_value = GUINT16_TO_LE (max_stack);
1016 memcpy (fat_header + 2, &short_value, 2);
1017 int_value = GUINT32_TO_LE (code_size);
1018 memcpy (fat_header + 4, &int_value, 4);
1019 int_value = GUINT32_TO_LE (local_sig);
1020 memcpy (fat_header + 8, &int_value, 4);
1021 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1022 /* add to the fixup todo list */
1023 if (mb->ilgen && mb->ilgen->num_token_fixups)
1024 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1026 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1027 if (num_exception) {
1028 unsigned char sheader [4];
1029 MonoILExceptionInfo * ex_info;
1030 MonoILExceptionBlock * ex_block;
1033 stream_data_align (&assembly->code);
1034 /* always use fat format for now */
1035 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1036 num_exception *= 6 * sizeof (guint32);
1037 num_exception += 4; /* include the size of the header */
1038 sheader [1] = num_exception & 0xff;
1039 sheader [2] = (num_exception >> 8) & 0xff;
1040 sheader [3] = (num_exception >> 16) & 0xff;
1041 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1042 /* fat header, so we are already aligned */
1044 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1045 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1046 if (ex_info->handlers) {
1047 int finally_start = ex_info->start + ex_info->len;
1048 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1050 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1052 val = GUINT32_TO_LE (ex_block->type);
1053 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1055 val = GUINT32_TO_LE (ex_info->start);
1056 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057 /* need fault, too, probably */
1058 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1059 val = GUINT32_TO_LE (finally_start - ex_info->start);
1061 val = GUINT32_TO_LE (ex_info->len);
1062 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1063 /* handler offset */
1064 val = GUINT32_TO_LE (ex_block->start);
1065 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1067 val = GUINT32_TO_LE (ex_block->len);
1068 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1069 finally_start = ex_block->start + ex_block->len;
1070 if (ex_block->extype) {
1071 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1073 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1074 val = ex_block->filter_offset;
1078 val = GUINT32_TO_LE (val);
1079 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1080 /*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",
1081 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);*/
1084 g_error ("No clauses for ex info block %d", i);
1088 return assembly->text_rva + idx;
1092 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1095 MonoDynamicTable *table;
1098 table = &assembly->tables [table_idx];
1100 g_assert (col < table->columns);
1102 values = table->values + table->columns;
1103 for (i = 1; i <= table->rows; ++i) {
1104 if (values [col] == token)
1106 values += table->columns;
1112 * LOCKING: Acquires the loader lock.
1114 static MonoCustomAttrInfo*
1115 lookup_custom_attr (MonoImage *image, gpointer member)
1117 MonoCustomAttrInfo* res;
1119 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1124 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1128 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1130 /* FIXME: Need to do more checks */
1131 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1132 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1134 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1141 static MonoCustomAttrInfo*
1142 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1144 int i, index, count, not_visible;
1145 MonoCustomAttrInfo *ainfo;
1146 MonoReflectionCustomAttr *cattr;
1150 /* FIXME: check in assembly the Run flag is set */
1152 count = mono_array_length (cattrs);
1154 /* Skip nonpublic attributes since MS.NET seems to do the same */
1155 /* FIXME: This needs to be done more globally */
1157 for (i = 0; i < count; ++i) {
1158 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1159 if (!custom_attr_visible (image, cattr))
1162 count -= not_visible;
1164 ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1166 ainfo->image = image;
1167 ainfo->num_attrs = count;
1168 ainfo->cached = alloc_img != NULL;
1170 for (i = 0; i < count; ++i) {
1171 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1172 if (custom_attr_visible (image, cattr)) {
1173 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1174 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1175 ainfo->attrs [index].ctor = cattr->ctor->method;
1176 ainfo->attrs [index].data = saved;
1177 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1186 * LOCKING: Acquires the loader lock.
1189 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1191 MonoCustomAttrInfo *ainfo, *tmp;
1193 if (!cattrs || !mono_array_length (cattrs))
1196 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1198 mono_loader_lock ();
1199 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1201 mono_custom_attrs_free (tmp);
1202 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1203 mono_loader_unlock ();
1208 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1215 * idx is the table index of the object
1216 * type is one of MONO_CUSTOM_ATTR_*
1219 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1221 MonoDynamicTable *table;
1222 MonoReflectionCustomAttr *cattr;
1224 guint32 count, i, token;
1226 char *p = blob_size;
1228 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1231 count = mono_array_length (cattrs);
1232 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1233 table->rows += count;
1234 alloc_table (table, table->rows);
1235 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1236 idx <<= MONO_CUSTOM_ATTR_BITS;
1238 for (i = 0; i < count; ++i) {
1239 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1240 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1241 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1242 type = mono_metadata_token_index (token);
1243 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1244 switch (mono_metadata_token_table (token)) {
1245 case MONO_TABLE_METHOD:
1246 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1248 case MONO_TABLE_MEMBERREF:
1249 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1252 g_warning ("got wrong token in custom attr");
1255 values [MONO_CUSTOM_ATTR_TYPE] = type;
1257 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1258 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1259 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1260 values += MONO_CUSTOM_ATTR_SIZE;
1266 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1268 MonoDynamicTable *table;
1270 guint32 count, i, idx;
1271 MonoReflectionPermissionSet *perm;
1276 count = mono_array_length (permissions);
1277 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1278 table->rows += count;
1279 alloc_table (table, table->rows);
1281 for (i = 0; i < mono_array_length (permissions); ++i) {
1282 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1284 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1286 idx = mono_metadata_token_index (parent_token);
1287 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1288 switch (mono_metadata_token_table (parent_token)) {
1289 case MONO_TABLE_TYPEDEF:
1290 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1292 case MONO_TABLE_METHOD:
1293 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1295 case MONO_TABLE_ASSEMBLY:
1296 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1299 g_assert_not_reached ();
1302 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1303 values [MONO_DECL_SECURITY_PARENT] = idx;
1304 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1311 * Fill in the MethodDef and ParamDef tables for a method.
1312 * This is used for both normal methods and constructors.
1315 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1317 MonoDynamicTable *table;
1321 /* room in this table is already allocated */
1322 table = &assembly->tables [MONO_TABLE_METHOD];
1323 *mb->table_idx = table->next_idx ++;
1324 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1325 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1326 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1327 values [MONO_METHOD_FLAGS] = mb->attrs;
1328 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1329 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1330 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1332 table = &assembly->tables [MONO_TABLE_PARAM];
1333 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1335 mono_image_add_decl_security (assembly,
1336 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1339 MonoDynamicTable *mtable;
1342 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1343 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1346 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1347 if (mono_array_get (mb->pinfo, gpointer, i))
1350 table->rows += count;
1351 alloc_table (table, table->rows);
1352 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1353 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1354 MonoReflectionParamBuilder *pb;
1355 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1356 values [MONO_PARAM_FLAGS] = pb->attrs;
1357 values [MONO_PARAM_SEQUENCE] = i;
1358 if (pb->name != NULL) {
1359 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1361 values [MONO_PARAM_NAME] = 0;
1363 values += MONO_PARAM_SIZE;
1364 if (pb->marshal_info) {
1366 alloc_table (mtable, mtable->rows);
1367 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1368 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1369 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1371 pb->table_idx = table->next_idx++;
1372 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1373 guint32 field_type = 0;
1374 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1376 alloc_table (mtable, mtable->rows);
1377 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1378 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1379 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1380 mvalues [MONO_CONSTANT_TYPE] = field_type;
1381 mvalues [MONO_CONSTANT_PADDING] = 0;
1389 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1391 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1393 rmb->ilgen = mb->ilgen;
1394 rmb->rtype = mb->rtype;
1395 rmb->parameters = mb->parameters;
1396 rmb->generic_params = mb->generic_params;
1397 rmb->generic_container = mb->generic_container;
1398 rmb->opt_types = NULL;
1399 rmb->pinfo = mb->pinfo;
1400 rmb->attrs = mb->attrs;
1401 rmb->iattrs = mb->iattrs;
1402 rmb->call_conv = mb->call_conv;
1403 rmb->code = mb->code;
1404 rmb->type = mb->type;
1405 rmb->name = mb->name;
1406 rmb->table_idx = &mb->table_idx;
1407 rmb->init_locals = mb->init_locals;
1408 rmb->skip_visibility = FALSE;
1409 rmb->return_modreq = mb->return_modreq;
1410 rmb->return_modopt = mb->return_modopt;
1411 rmb->param_modreq = mb->param_modreq;
1412 rmb->param_modopt = mb->param_modopt;
1413 rmb->permissions = mb->permissions;
1414 rmb->mhandle = mb->mhandle;
1419 rmb->charset = mb->charset;
1420 rmb->extra_flags = mb->extra_flags;
1421 rmb->native_cc = mb->native_cc;
1422 rmb->dllentry = mb->dllentry;
1428 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1430 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1432 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1434 rmb->ilgen = mb->ilgen;
1435 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1436 rmb->parameters = mb->parameters;
1437 rmb->generic_params = NULL;
1438 rmb->generic_container = NULL;
1439 rmb->opt_types = NULL;
1440 rmb->pinfo = mb->pinfo;
1441 rmb->attrs = mb->attrs;
1442 rmb->iattrs = mb->iattrs;
1443 rmb->call_conv = mb->call_conv;
1445 rmb->type = mb->type;
1446 rmb->name = mono_string_new (mono_domain_get (), name);
1447 rmb->table_idx = &mb->table_idx;
1448 rmb->init_locals = mb->init_locals;
1449 rmb->skip_visibility = FALSE;
1450 rmb->return_modreq = NULL;
1451 rmb->return_modopt = NULL;
1452 rmb->param_modreq = mb->param_modreq;
1453 rmb->param_modopt = mb->param_modopt;
1454 rmb->permissions = mb->permissions;
1455 rmb->mhandle = mb->mhandle;
1461 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1463 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1465 rmb->ilgen = mb->ilgen;
1466 rmb->rtype = mb->rtype;
1467 rmb->parameters = mb->parameters;
1468 rmb->generic_params = NULL;
1469 rmb->generic_container = NULL;
1470 rmb->opt_types = NULL;
1472 rmb->attrs = mb->attrs;
1474 rmb->call_conv = mb->call_conv;
1476 rmb->type = (MonoObject *) mb->owner;
1477 rmb->name = mb->name;
1478 rmb->table_idx = NULL;
1479 rmb->init_locals = mb->init_locals;
1480 rmb->skip_visibility = mb->skip_visibility;
1481 rmb->return_modreq = NULL;
1482 rmb->return_modopt = NULL;
1483 rmb->param_modreq = NULL;
1484 rmb->param_modopt = NULL;
1485 rmb->permissions = NULL;
1486 rmb->mhandle = mb->mhandle;
1492 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1494 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1495 MonoDynamicTable *table;
1499 if (!mb->override_method)
1502 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1504 alloc_table (table, table->rows);
1505 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1506 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1507 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1509 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1510 switch (mono_metadata_token_table (tok)) {
1511 case MONO_TABLE_MEMBERREF:
1512 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1514 case MONO_TABLE_METHOD:
1515 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1518 g_assert_not_reached ();
1520 values [MONO_METHODIMPL_DECLARATION] = tok;
1524 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1526 MonoDynamicTable *table;
1528 ReflectionMethodBuilder rmb;
1531 reflection_methodbuilder_from_method_builder (&rmb, mb);
1533 mono_image_basic_method (&rmb, assembly);
1534 mb->table_idx = *rmb.table_idx;
1536 if (mb->dll) { /* It's a P/Invoke method */
1538 /* map CharSet values to on-disk values */
1539 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1540 int extra_flags = mb->extra_flags;
1541 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1543 alloc_table (table, table->rows);
1544 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1546 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1547 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1549 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1551 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1552 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1553 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1554 table = &assembly->tables [MONO_TABLE_MODULEREF];
1556 alloc_table (table, table->rows);
1557 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1558 values [MONO_IMPLMAP_SCOPE] = table->rows;
1562 if (mb->generic_params) {
1563 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1564 table->rows += mono_array_length (mb->generic_params);
1565 alloc_table (table, table->rows);
1566 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1567 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1569 mono_image_get_generic_param_info (
1570 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1577 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1579 ReflectionMethodBuilder rmb;
1581 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1583 mono_image_basic_method (&rmb, assembly);
1584 mb->table_idx = *rmb.table_idx;
1588 type_get_fully_qualified_name (MonoType *type)
1590 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1594 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1598 klass = my_mono_class_from_mono_type (type);
1600 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1601 ta = klass->image->assembly;
1602 if (ta->dynamic || (ta == ass)) {
1603 if (klass->generic_class || klass->generic_container)
1604 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1605 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1607 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1614 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1619 if (!assembly->save)
1622 sigbuffer_init (&buf, 32);
1624 sigbuffer_add_value (&buf, 0x06);
1625 /* encode custom attributes before the type */
1626 /* FIXME: This should probably go in encode_type () */
1627 if (type->num_mods) {
1628 for (i = 0; i < type->num_mods; ++i) {
1629 if (type->modifiers [i].required)
1630 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1632 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1633 sigbuffer_add_value (&buf, type->modifiers [i].token);
1636 encode_type (assembly, type, &buf);
1637 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1638 sigbuffer_free (&buf);
1643 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1648 sigbuffer_init (&buf, 32);
1650 sigbuffer_add_value (&buf, 0x06);
1651 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1652 /* encode custom attributes before the type */
1653 encode_reflection_type (assembly, fb->type, &buf);
1654 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1655 sigbuffer_free (&buf);
1660 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1661 char blob_size [64];
1662 char *b = blob_size;
1665 guint32 idx = 0, len = 0, dummy = 0;
1667 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1668 guint32 fpa_double [2];
1673 p = buf = g_malloc (64);
1675 *ret_type = MONO_TYPE_CLASS;
1677 box_val = (char*)&dummy;
1679 box_val = ((char*)val) + sizeof (MonoObject);
1680 *ret_type = val->vtable->klass->byval_arg.type;
1683 switch (*ret_type) {
1684 case MONO_TYPE_BOOLEAN:
1689 case MONO_TYPE_CHAR:
1706 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1707 fpa_p = (guint32*)box_val;
1708 fpa_double [0] = fpa_p [1];
1709 fpa_double [1] = fpa_p [0];
1710 box_val = (char*)fpa_double;
1714 case MONO_TYPE_VALUETYPE:
1715 if (val->vtable->klass->enumtype) {
1716 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1719 g_error ("we can't encode valuetypes");
1720 case MONO_TYPE_CLASS:
1722 case MONO_TYPE_STRING: {
1723 MonoString *str = (MonoString*)val;
1724 /* there is no signature */
1725 len = str->length * 2;
1726 mono_metadata_encode_value (len, b, &b);
1727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1729 char *swapped = g_malloc (2 * mono_string_length (str));
1730 const char *p = (const char*)mono_string_chars (str);
1732 swap_with_size (swapped, p, 2, mono_string_length (str));
1733 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1737 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1743 case MONO_TYPE_GENERICINST:
1744 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1747 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1750 /* there is no signature */
1751 mono_metadata_encode_value (len, b, &b);
1752 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1753 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1754 swap_with_size (blob_size, box_val, len, 1);
1755 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1757 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1765 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1770 sigbuffer_init (&buf, 32);
1772 sigbuffer_add_value (&buf, minfo->type);
1774 switch (minfo->type) {
1775 case MONO_NATIVE_BYVALTSTR:
1776 case MONO_NATIVE_BYVALARRAY:
1777 sigbuffer_add_value (&buf, minfo->count);
1779 case MONO_NATIVE_LPARRAY:
1780 if (minfo->eltype || minfo->has_size) {
1781 sigbuffer_add_value (&buf, minfo->eltype);
1782 if (minfo->has_size) {
1783 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1784 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1786 /* LAMESPEC: ElemMult is undocumented */
1787 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1791 case MONO_NATIVE_CUSTOM:
1793 str = mono_string_to_utf8 (minfo->guid);
1795 sigbuffer_add_value (&buf, len);
1796 sigbuffer_add_mem (&buf, str, len);
1799 sigbuffer_add_value (&buf, 0);
1801 /* native type name */
1802 sigbuffer_add_value (&buf, 0);
1803 /* custom marshaler type name */
1804 if (minfo->marshaltype || minfo->marshaltyperef) {
1805 if (minfo->marshaltyperef)
1806 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1808 str = mono_string_to_utf8 (minfo->marshaltype);
1810 sigbuffer_add_value (&buf, len);
1811 sigbuffer_add_mem (&buf, str, len);
1814 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1815 sigbuffer_add_value (&buf, 0);
1817 if (minfo->mcookie) {
1818 str = mono_string_to_utf8 (minfo->mcookie);
1820 sigbuffer_add_value (&buf, len);
1821 sigbuffer_add_mem (&buf, str, len);
1824 sigbuffer_add_value (&buf, 0);
1830 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1831 sigbuffer_free (&buf);
1836 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1838 MonoDynamicTable *table;
1841 /* maybe this fixup should be done in the C# code */
1842 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1843 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1844 table = &assembly->tables [MONO_TABLE_FIELD];
1845 fb->table_idx = table->next_idx ++;
1846 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1847 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1848 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1849 values [MONO_FIELD_FLAGS] = fb->attrs;
1850 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1852 if (fb->offset != -1) {
1853 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1855 alloc_table (table, table->rows);
1856 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1857 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1858 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1860 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1861 guint32 field_type = 0;
1862 table = &assembly->tables [MONO_TABLE_CONSTANT];
1864 alloc_table (table, table->rows);
1865 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1866 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1867 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1868 values [MONO_CONSTANT_TYPE] = field_type;
1869 values [MONO_CONSTANT_PADDING] = 0;
1871 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1873 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1875 alloc_table (table, table->rows);
1876 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1877 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1879 * We store it in the code section because it's simpler for now.
1882 if (mono_array_length (fb->rva_data) >= 10)
1883 stream_data_align (&assembly->code);
1884 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1886 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1887 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1889 if (fb->marshal_info) {
1890 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1892 alloc_table (table, table->rows);
1893 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1894 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1895 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1900 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1903 guint32 nparams = 0;
1904 MonoReflectionMethodBuilder *mb = fb->get_method;
1905 MonoReflectionMethodBuilder *smb = fb->set_method;
1908 if (mb && mb->parameters)
1909 nparams = mono_array_length (mb->parameters);
1910 if (!mb && smb && smb->parameters)
1911 nparams = mono_array_length (smb->parameters) - 1;
1912 sigbuffer_init (&buf, 32);
1913 sigbuffer_add_byte (&buf, 0x08);
1914 sigbuffer_add_value (&buf, nparams);
1916 encode_reflection_type (assembly, mb->rtype, &buf);
1917 for (i = 0; i < nparams; ++i) {
1918 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1919 encode_reflection_type (assembly, pt, &buf);
1921 } else if (smb && smb->parameters) {
1922 /* the property type is the last param */
1923 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1924 for (i = 0; i < nparams; ++i) {
1925 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1926 encode_reflection_type (assembly, pt, &buf);
1929 encode_reflection_type (assembly, fb->type, &buf);
1932 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1933 sigbuffer_free (&buf);
1938 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1940 MonoDynamicTable *table;
1942 guint num_methods = 0;
1946 * we need to set things in the following tables:
1947 * PROPERTYMAP (info already filled in _get_type_info ())
1948 * PROPERTY (rows already preallocated in _get_type_info ())
1949 * METHOD (method info already done with the generic method code)
1952 table = &assembly->tables [MONO_TABLE_PROPERTY];
1953 pb->table_idx = table->next_idx ++;
1954 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1955 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1956 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1957 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1959 /* FIXME: we still don't handle 'other' methods */
1960 if (pb->get_method) num_methods ++;
1961 if (pb->set_method) num_methods ++;
1963 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1964 table->rows += num_methods;
1965 alloc_table (table, table->rows);
1967 if (pb->get_method) {
1968 semaidx = table->next_idx ++;
1969 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1970 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1971 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1972 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1974 if (pb->set_method) {
1975 semaidx = table->next_idx ++;
1976 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1977 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1978 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1979 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1984 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1986 MonoDynamicTable *table;
1988 guint num_methods = 0;
1992 * we need to set things in the following tables:
1993 * EVENTMAP (info already filled in _get_type_info ())
1994 * EVENT (rows already preallocated in _get_type_info ())
1995 * METHOD (method info already done with the generic method code)
1998 table = &assembly->tables [MONO_TABLE_EVENT];
1999 eb->table_idx = table->next_idx ++;
2000 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2001 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2002 values [MONO_EVENT_FLAGS] = eb->attrs;
2003 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2006 * FIXME: we still don't handle 'other' methods
2008 if (eb->add_method) num_methods ++;
2009 if (eb->remove_method) num_methods ++;
2010 if (eb->raise_method) num_methods ++;
2012 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2013 table->rows += num_methods;
2014 alloc_table (table, table->rows);
2016 if (eb->add_method) {
2017 semaidx = table->next_idx ++;
2018 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2019 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2020 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2021 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2023 if (eb->remove_method) {
2024 semaidx = table->next_idx ++;
2025 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2026 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2027 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2028 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2030 if (eb->raise_method) {
2031 semaidx = table->next_idx ++;
2032 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2033 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2034 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2035 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2040 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2042 MonoDynamicTable *table;
2043 guint32 num_constraints, i;
2047 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2048 num_constraints = gparam->iface_constraints ?
2049 mono_array_length (gparam->iface_constraints) : 0;
2050 table->rows += num_constraints;
2051 if (gparam->base_type)
2053 alloc_table (table, table->rows);
2055 if (gparam->base_type) {
2056 table_idx = table->next_idx ++;
2057 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2059 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2060 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2061 assembly, gparam->base_type->type);
2064 for (i = 0; i < num_constraints; i++) {
2065 MonoReflectionType *constraint = mono_array_get (
2066 gparam->iface_constraints, gpointer, i);
2068 table_idx = table->next_idx ++;
2069 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2071 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2072 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2073 assembly, constraint->type);
2078 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2080 GenericParamTableEntry *entry;
2083 * The GenericParam table must be sorted according to the `owner' field.
2084 * We need to do this sorting prior to writing the GenericParamConstraint
2085 * table, since we have to use the final GenericParam table indices there
2086 * and they must also be sorted.
2089 entry = g_new0 (GenericParamTableEntry, 1);
2090 entry->owner = owner;
2091 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2092 MOVING_GC_REGISTER (&entry->gparam);
2093 entry->gparam = gparam;
2095 g_ptr_array_add (assembly->gen_params, entry);
2099 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2101 MonoDynamicTable *table;
2102 MonoGenericParam *param;
2106 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2107 table_idx = table->next_idx ++;
2108 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2110 param = entry->gparam->type.type->data.generic_param;
2112 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2113 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2114 values [MONO_GENERICPARAM_NUMBER] = param->num;
2115 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2117 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2119 encode_constraints (entry->gparam, table_idx, assembly);
2123 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2125 MonoDynamicTable *table;
2128 guint32 cols [MONO_ASSEMBLY_SIZE];
2132 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2135 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2136 table = &assembly->tables [MONO_TABLE_MODULEREF];
2137 token = table->next_idx ++;
2139 alloc_table (table, table->rows);
2140 values = table->values + token * MONO_MODULEREF_SIZE;
2141 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2143 token <<= MONO_RESOLTION_SCOPE_BITS;
2144 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2145 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2150 if (image->assembly->dynamic)
2152 memset (cols, 0, sizeof (cols));
2154 /* image->assembly->image is the manifest module */
2155 image = image->assembly->image;
2156 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2159 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2160 token = table->next_idx ++;
2162 alloc_table (table, table->rows);
2163 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2164 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2165 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2166 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2167 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2168 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2169 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2170 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2171 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2173 if (strcmp ("", image->assembly->aname.culture)) {
2174 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2175 image->assembly->aname.culture);
2178 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2179 guchar pubtoken [9];
2181 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2182 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2184 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2186 token <<= MONO_RESOLTION_SCOPE_BITS;
2187 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2188 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2193 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2195 MonoDynamicTable *table;
2200 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2203 sigbuffer_init (&buf, 32);
2204 switch (type->type) {
2205 case MONO_TYPE_FNPTR:
2207 case MONO_TYPE_SZARRAY:
2208 case MONO_TYPE_ARRAY:
2210 case MONO_TYPE_MVAR:
2211 case MONO_TYPE_GENERICINST:
2212 encode_type (assembly, type, &buf);
2214 case MONO_TYPE_CLASS:
2215 case MONO_TYPE_VALUETYPE: {
2216 MonoClass *k = mono_class_from_mono_type (type);
2217 if (!k || !k->generic_container) {
2218 sigbuffer_free (&buf);
2221 encode_type (assembly, type, &buf);
2225 sigbuffer_free (&buf);
2229 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2230 if (assembly->save) {
2231 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2232 alloc_table (table, table->rows + 1);
2233 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2234 values [MONO_TYPESPEC_SIGNATURE] = token;
2236 sigbuffer_free (&buf);
2238 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2239 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2245 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2247 MonoDynamicTable *table;
2249 guint32 token, scope, enclosing;
2252 /* if the type requires a typespec, we must try that first*/
2253 if (try_typespec && (token = create_typespec (assembly, type)))
2255 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2258 klass = my_mono_class_from_mono_type (type);
2260 klass = mono_class_from_mono_type (type);
2263 * If it's in the same module and not a generic type parameter:
2265 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2266 (type->type != MONO_TYPE_MVAR)) {
2267 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2268 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2269 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2273 if (klass->nested_in) {
2274 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2275 /* get the typeref idx of the enclosing type */
2276 enclosing >>= MONO_TYPEDEFORREF_BITS;
2277 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2279 scope = resolution_scope_from_image (assembly, klass->image);
2281 table = &assembly->tables [MONO_TABLE_TYPEREF];
2282 if (assembly->save) {
2283 alloc_table (table, table->rows + 1);
2284 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2285 values [MONO_TYPEREF_SCOPE] = scope;
2286 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2287 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2289 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2290 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2292 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2297 * Despite the name, we handle also TypeSpec (with the above helper).
2300 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2302 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2306 * Insert a memberef row into the metadata: the token that point to the memberref
2307 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2308 * mono_image_get_fieldref_token()).
2309 * The sig param is an index to an already built signature.
2312 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2314 MonoDynamicTable *table;
2316 guint32 token, pclass;
2319 parent = mono_image_typedef_or_ref (assembly, type);
2320 switch (parent & MONO_TYPEDEFORREF_MASK) {
2321 case MONO_TYPEDEFORREF_TYPEREF:
2322 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2324 case MONO_TYPEDEFORREF_TYPESPEC:
2325 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2327 case MONO_TYPEDEFORREF_TYPEDEF:
2328 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2331 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2334 /* extract the index */
2335 parent >>= MONO_TYPEDEFORREF_BITS;
2337 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2339 if (assembly->save) {
2340 alloc_table (table, table->rows + 1);
2341 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2342 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2343 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2344 values [MONO_MEMBERREF_SIGNATURE] = sig;
2347 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2354 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2357 MonoMethodSignature *sig;
2359 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2361 if (create_typespec) {
2362 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2368 if (token && !create_typespec)
2371 g_assert (!method->is_inflated);
2374 * A methodref signature can't contain an unmanaged calling convention.
2376 sig = mono_metadata_signature_dup (mono_method_signature (method));
2377 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2378 sig->call_convention = MONO_CALL_DEFAULT;
2379 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2380 method->name, method_encode_signature (assembly, sig));
2382 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2385 if (create_typespec) {
2386 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2387 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2388 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2390 if (assembly->save) {
2393 alloc_table (table, table->rows + 1);
2394 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2395 values [MONO_METHODSPEC_METHOD] = token;
2396 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2399 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2401 /*methodspec and memberef tokens are diferent, */
2402 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2409 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2412 ReflectionMethodBuilder rmb;
2415 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2419 name = mono_string_to_utf8 (method->name);
2420 reflection_methodbuilder_from_method_builder (&rmb, method);
2423 * A methodref signature can't contain an unmanaged calling convention.
2424 * Since some flags are encoded as part of call_conv, we need to check against it.
2426 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2427 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2428 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2429 name, method_builder_encode_signature (assembly, &rmb));
2432 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2437 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2438 const gchar *name, guint32 sig)
2440 MonoDynamicTable *table;
2444 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2446 if (assembly->save) {
2447 alloc_table (table, table->rows + 1);
2448 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2449 values [MONO_MEMBERREF_CLASS] = original;
2450 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2451 values [MONO_MEMBERREF_SIGNATURE] = sig;
2454 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2461 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2465 guint32 nparams = mono_array_length (mb->generic_params);
2468 if (!assembly->save)
2471 sigbuffer_init (&buf, 32);
2473 sigbuffer_add_value (&buf, 0xa);
2474 sigbuffer_add_value (&buf, nparams);
2476 for (i = 0; i < nparams; i++) {
2477 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2478 sigbuffer_add_value (&buf, i);
2481 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2482 sigbuffer_free (&buf);
2487 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2489 MonoDynamicTable *table;
2491 guint32 token, mtoken = 0;
2493 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2497 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2499 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2500 switch (mono_metadata_token_table (mtoken)) {
2501 case MONO_TABLE_MEMBERREF:
2502 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2504 case MONO_TABLE_METHOD:
2505 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2508 g_assert_not_reached ();
2511 if (assembly->save) {
2512 alloc_table (table, table->rows + 1);
2513 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2514 values [MONO_METHODSPEC_METHOD] = mtoken;
2515 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2518 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2521 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2526 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2530 if (mb->generic_params && create_methodspec)
2531 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2533 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2537 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2538 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2543 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2546 ReflectionMethodBuilder rmb;
2549 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2553 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2555 name = mono_string_to_utf8 (rmb.name);
2556 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2557 name, method_builder_encode_signature (assembly, &rmb));
2560 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2565 is_field_on_inst (MonoClassField *field)
2567 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2571 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2574 get_field_on_inst_generic_type (MonoClassField *field)
2576 MonoDynamicGenericClass *dgclass;
2579 g_assert (is_field_on_inst (field));
2581 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2582 field_index = field - dgclass->fields;
2584 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2585 return dgclass->field_generic_types [field_index];
2589 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2593 MonoClassField *field;
2595 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2598 g_assert (f->field->parent);
2601 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2602 int index = field - field->parent->fields;
2603 type = field->parent->generic_class->container_class->fields [index].type;
2605 if (is_field_on_inst (f->field))
2606 type = get_field_on_inst_generic_type (f->field);
2608 type = f->field->type;
2610 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2611 mono_field_get_name (f->field),
2612 fieldref_encode_signature (assembly, type));
2613 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2618 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2622 MonoGenericClass *gclass;
2623 MonoDynamicGenericClass *dgclass;
2624 MonoReflectionFieldBuilder *fb = f->fb;
2627 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2630 klass = mono_class_from_mono_type (f->inst->type.type);
2631 gclass = f->inst->type.type->data.generic_class;
2632 g_assert (gclass->is_dynamic);
2633 dgclass = (MonoDynamicGenericClass *) gclass;
2635 name = mono_string_to_utf8 (fb->name);
2636 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2637 field_encode_signature (assembly, fb));
2639 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2644 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2648 MonoGenericClass *gclass;
2649 MonoDynamicGenericClass *dgclass;
2650 MonoReflectionCtorBuilder *cb = c->cb;
2651 ReflectionMethodBuilder rmb;
2654 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2656 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2659 klass = mono_class_from_mono_type (c->inst->type.type);
2660 gclass = c->inst->type.type->data.generic_class;
2661 g_assert (gclass->is_dynamic);
2662 dgclass = (MonoDynamicGenericClass *) gclass;
2664 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2666 name = mono_string_to_utf8 (rmb.name);
2668 sig = method_builder_encode_signature (assembly, &rmb);
2670 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2673 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2678 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2682 MonoGenericClass *gclass;
2683 MonoReflectionMethodBuilder *mb = m->mb;
2684 ReflectionMethodBuilder rmb;
2687 if (create_methodspec && mb->generic_params)
2689 g_assert_not_reached ();
2691 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2694 klass = mono_class_from_mono_type (m->inst->type.type);
2695 gclass = m->inst->type.type->data.generic_class;
2696 g_assert (gclass->is_dynamic);
2698 reflection_methodbuilder_from_method_builder (&rmb, mb);
2700 name = mono_string_to_utf8 (rmb.name);
2702 sig = method_builder_encode_signature (assembly, &rmb);
2704 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2707 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2712 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2716 guint32 nparams = context->method_inst->type_argc;
2719 if (!assembly->save)
2722 sigbuffer_init (&buf, 32);
2724 * FIXME: vararg, explicit_this, differenc call_conv values...
2726 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2727 sigbuffer_add_value (&buf, nparams);
2729 for (i = 0; i < nparams; i++)
2730 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2732 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2733 sigbuffer_free (&buf);
2738 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2740 MonoDynamicTable *table;
2742 guint32 token, mtoken = 0, sig;
2743 MonoMethodInflated *imethod;
2744 MonoMethod *declaring;
2746 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2748 g_assert (method->is_inflated);
2749 imethod = (MonoMethodInflated *) method;
2750 declaring = imethod->declaring;
2752 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2753 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2755 if (!mono_method_signature (declaring)->generic_param_count)
2758 switch (mono_metadata_token_table (mtoken)) {
2759 case MONO_TABLE_MEMBERREF:
2760 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2762 case MONO_TABLE_METHOD:
2763 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2766 g_assert_not_reached ();
2769 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2771 if (assembly->save) {
2772 alloc_table (table, table->rows + 1);
2773 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2774 values [MONO_METHODSPEC_METHOD] = mtoken;
2775 values [MONO_METHODSPEC_SIGNATURE] = sig;
2778 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2785 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2787 MonoMethodInflated *imethod;
2790 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2794 g_assert (method->is_inflated);
2795 imethod = (MonoMethodInflated *) method;
2797 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2798 token = method_encode_methodspec (assembly, method);
2800 guint32 sig = method_encode_signature (
2801 assembly, mono_method_signature (imethod->declaring));
2802 token = mono_image_get_memberref_token (
2803 assembly, &method->klass->byval_arg, method->name, sig);
2806 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2811 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2813 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2816 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2817 token = mono_image_get_memberref_token (
2818 assembly, &m->klass->byval_arg, m->name, sig);
2824 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2826 MonoDynamicTable *table;
2834 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2835 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2836 * Because of this, we must not insert it into the `typeref' hash table.
2839 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2843 sigbuffer_init (&buf, 32);
2845 g_assert (tb->generic_params);
2846 klass = mono_class_from_mono_type (tb->type.type);
2848 if (tb->generic_container)
2849 mono_reflection_create_generic_class (tb);
2851 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2852 g_assert (klass->generic_container);
2853 sigbuffer_add_value (&buf, klass->byval_arg.type);
2854 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2856 count = mono_array_length (tb->generic_params);
2857 sigbuffer_add_value (&buf, count);
2858 for (i = 0; i < count; i++) {
2859 MonoReflectionGenericParam *gparam;
2861 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2863 encode_type (assembly, gparam->type.type, &buf);
2866 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2868 if (assembly->save) {
2869 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2870 alloc_table (table, table->rows + 1);
2871 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2872 values [MONO_TYPESPEC_SIGNATURE] = token;
2874 sigbuffer_free (&buf);
2876 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2877 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2883 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2886 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2888 int i, count, len, pos;
2893 count += mono_array_length (modreq);
2895 count += mono_array_length (modopt);
2898 return mono_metadata_type_dup (NULL, type);
2900 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2902 memcpy (t, type, len);
2904 t->num_mods = count;
2907 for (i = 0; i < mono_array_length (modreq); ++i) {
2908 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2909 t->modifiers [pos].required = 1;
2910 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2915 for (i = 0; i < mono_array_length (modopt); ++i) {
2916 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2917 t->modifiers [pos].required = 0;
2918 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2927 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2929 MonoDynamicTable *table;
2931 MonoType *custom = NULL;
2933 guint32 token, pclass, parent, sig;
2936 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2940 klass = mono_class_from_mono_type (fb->typeb->type);
2941 name = mono_string_to_utf8 (fb->name);
2943 /* fb->type does not include the custom modifiers */
2944 /* FIXME: We should do this in one place when a fieldbuilder is created */
2945 if (fb->modreq || fb->modopt) {
2946 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2947 sig = fieldref_encode_signature (assembly, custom);
2950 sig = fieldref_encode_signature (assembly, fb->type->type);
2953 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2954 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2956 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2957 parent >>= MONO_TYPEDEFORREF_BITS;
2959 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2961 if (assembly->save) {
2962 alloc_table (table, table->rows + 1);
2963 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2964 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2965 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2966 values [MONO_MEMBERREF_SIGNATURE] = sig;
2969 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2971 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2977 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2984 if (!assembly->save)
2987 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2988 g_assert (helper->type == 2);
2990 if (helper->arguments)
2991 nargs = mono_array_length (helper->arguments);
2995 size = 10 + (nargs * 10);
2997 sigbuffer_init (&buf, 32);
2999 /* Encode calling convention */
3000 /* Change Any to Standard */
3001 if ((helper->call_conv & 0x03) == 0x03)
3002 helper->call_conv = 0x01;
3003 /* explicit_this implies has_this */
3004 if (helper->call_conv & 0x40)
3005 helper->call_conv &= 0x20;
3007 if (helper->call_conv == 0) { /* Unmanaged */
3008 idx = helper->unmanaged_call_conv - 1;
3011 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3012 if (helper->call_conv & 0x02) /* varargs */
3016 sigbuffer_add_byte (&buf, idx);
3017 sigbuffer_add_value (&buf, nargs);
3018 encode_reflection_type (assembly, helper->return_type, &buf);
3019 for (i = 0; i < nargs; ++i) {
3020 MonoArray *modreqs = NULL;
3021 MonoArray *modopts = NULL;
3022 MonoReflectionType *pt;
3024 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3025 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3026 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3027 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3029 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3030 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3031 encode_reflection_type (assembly, pt, &buf);
3033 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034 sigbuffer_free (&buf);
3040 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3043 MonoDynamicTable *table;
3046 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3047 idx = table->next_idx ++;
3049 alloc_table (table, table->rows);
3050 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3052 values [MONO_STAND_ALONE_SIGNATURE] =
3053 mono_reflection_encode_sighelper (assembly, helper);
3059 reflection_cc_to_file (int call_conv) {
3060 switch (call_conv & 0x3) {
3062 case 1: return MONO_CALL_DEFAULT;
3063 case 2: return MONO_CALL_VARARG;
3065 g_assert_not_reached ();
3072 MonoMethodSignature *sig;
3078 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3083 MonoMethodSignature *sig;
3086 name = mono_string_to_utf8 (m->name);
3087 nparams = mono_array_length (m->parameters);
3088 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3090 sig->sentinelpos = -1;
3091 sig->call_convention = reflection_cc_to_file (m->call_conv);
3092 sig->param_count = nparams;
3093 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3094 for (i = 0; i < nparams; ++i) {
3095 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3096 sig->params [i] = t->type;
3099 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3101 if (strcmp (name, am->name) == 0 &&
3102 mono_metadata_type_equal (am->parent, m->parent->type) &&
3103 mono_metadata_signature_equal (am->sig, sig)) {
3106 m->table_idx = am->token & 0xffffff;
3110 am = g_new0 (ArrayMethod, 1);
3113 am->parent = m->parent->type;
3114 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3115 method_encode_signature (assembly, sig));
3116 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3117 m->table_idx = am->token & 0xffffff;
3122 * Insert into the metadata tables all the info about the TypeBuilder tb.
3123 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3126 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3128 MonoDynamicTable *table;
3130 int i, is_object = 0, is_system = 0;
3133 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3134 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3135 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3136 n = mono_string_to_utf8 (tb->name);
3137 if (strcmp (n, "Object") == 0)
3139 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3141 n = mono_string_to_utf8 (tb->nspace);
3142 if (strcmp (n, "System") == 0)
3144 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3146 if (tb->parent && !(is_system && is_object) &&
3147 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3148 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3150 values [MONO_TYPEDEF_EXTENDS] = 0;
3152 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3153 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3156 * if we have explicitlayout or sequentiallayouts, output data in the
3157 * ClassLayout table.
3159 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3160 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3161 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3163 alloc_table (table, table->rows);
3164 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3165 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3166 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3167 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3170 /* handle interfaces */
3171 if (tb->interfaces) {
3172 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3174 table->rows += mono_array_length (tb->interfaces);
3175 alloc_table (table, table->rows);
3176 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3177 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3178 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3179 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3180 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3181 values += MONO_INTERFACEIMPL_SIZE;
3187 table = &assembly->tables [MONO_TABLE_FIELD];
3188 table->rows += tb->num_fields;
3189 alloc_table (table, table->rows);
3190 for (i = 0; i < tb->num_fields; ++i)
3191 mono_image_get_field_info (
3192 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3195 /* handle constructors */
3197 table = &assembly->tables [MONO_TABLE_METHOD];
3198 table->rows += mono_array_length (tb->ctors);
3199 alloc_table (table, table->rows);
3200 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3201 mono_image_get_ctor_info (domain,
3202 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3205 /* handle methods */
3207 table = &assembly->tables [MONO_TABLE_METHOD];
3208 table->rows += tb->num_methods;
3209 alloc_table (table, table->rows);
3210 for (i = 0; i < tb->num_methods; ++i)
3211 mono_image_get_method_info (
3212 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3215 /* Do the same with properties etc.. */
3216 if (tb->events && mono_array_length (tb->events)) {
3217 table = &assembly->tables [MONO_TABLE_EVENT];
3218 table->rows += mono_array_length (tb->events);
3219 alloc_table (table, table->rows);
3220 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3222 alloc_table (table, table->rows);
3223 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3224 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3225 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3226 for (i = 0; i < mono_array_length (tb->events); ++i)
3227 mono_image_get_event_info (
3228 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3230 if (tb->properties && mono_array_length (tb->properties)) {
3231 table = &assembly->tables [MONO_TABLE_PROPERTY];
3232 table->rows += mono_array_length (tb->properties);
3233 alloc_table (table, table->rows);
3234 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3236 alloc_table (table, table->rows);
3237 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3238 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3239 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3240 for (i = 0; i < mono_array_length (tb->properties); ++i)
3241 mono_image_get_property_info (
3242 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3245 /* handle generic parameters */
3246 if (tb->generic_params) {
3247 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3248 table->rows += mono_array_length (tb->generic_params);
3249 alloc_table (table, table->rows);
3250 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3251 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3253 mono_image_get_generic_param_info (
3254 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3258 mono_image_add_decl_security (assembly,
3259 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3262 MonoDynamicTable *ntable;
3264 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3265 ntable->rows += mono_array_length (tb->subtypes);
3266 alloc_table (ntable, ntable->rows);
3267 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3269 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3270 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3272 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3273 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3274 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3275 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3276 mono_string_to_utf8 (tb->name), tb->table_idx,
3277 ntable->next_idx, ntable->rows);*/
3278 values += MONO_NESTED_CLASS_SIZE;
3285 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3289 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3291 if (!type->subtypes)
3294 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3295 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3296 collect_types (types, subtype);
3301 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3303 if ((*type1)->table_idx < (*type2)->table_idx)
3306 if ((*type1)->table_idx > (*type2)->table_idx)
3313 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3318 for (i = 0; i < mono_array_length (pinfo); ++i) {
3319 MonoReflectionParamBuilder *pb;
3320 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3323 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3328 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3331 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3333 for (i = 0; i < tb->num_fields; ++i) {
3334 MonoReflectionFieldBuilder* fb;
3335 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3336 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3340 for (i = 0; i < mono_array_length (tb->events); ++i) {
3341 MonoReflectionEventBuilder* eb;
3342 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3343 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3346 if (tb->properties) {
3347 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3348 MonoReflectionPropertyBuilder* pb;
3349 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3350 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3354 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3355 MonoReflectionCtorBuilder* cb;
3356 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3357 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3358 params_add_cattrs (assembly, cb->pinfo);
3363 for (i = 0; i < tb->num_methods; ++i) {
3364 MonoReflectionMethodBuilder* mb;
3365 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3366 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3367 params_add_cattrs (assembly, mb->pinfo);
3372 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3373 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3378 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3382 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3384 if (moduleb->global_methods) {
3385 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3386 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3387 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3388 params_add_cattrs (assembly, mb->pinfo);
3392 if (moduleb->global_fields) {
3393 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3394 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3395 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3399 if (moduleb->types) {
3400 for (i = 0; i < moduleb->num_types; ++i)
3401 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3406 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3408 MonoDynamicTable *table;
3412 char *b = blob_size;
3415 table = &assembly->tables [MONO_TABLE_FILE];
3417 alloc_table (table, table->rows);
3418 values = table->values + table->next_idx * MONO_FILE_SIZE;
3419 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3420 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3421 if (module->image->dynamic) {
3422 /* This depends on the fact that the main module is emitted last */
3423 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3424 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3427 path = g_strdup (module->image->name);
3429 mono_sha1_get_digest_from_file (path, hash);
3432 mono_metadata_encode_value (20, b, &b);
3433 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3434 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3439 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3441 MonoDynamicTable *table;
3444 table = &assembly->tables [MONO_TABLE_MODULE];
3445 mb->table_idx = table->next_idx ++;
3446 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3447 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3450 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3451 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3452 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3453 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3457 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3458 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3460 MonoDynamicTable *table;
3464 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3465 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3468 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3470 alloc_table (table, table->rows);
3471 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3473 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3474 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3475 if (klass->nested_in)
3476 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3478 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3479 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3480 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3482 res = table->next_idx;
3486 /* Emit nested types */
3487 if (klass->ext && klass->ext->nested_classes) {
3490 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3491 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3498 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3499 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3504 klass = mono_class_from_mono_type (tb->type.type);
3506 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3508 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3509 parent_index, assembly);
3513 * We need to do this ourselves since klass->nested_classes is not set up.
3516 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3517 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3522 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3523 guint32 module_index, MonoDynamicImage *assembly)
3525 MonoImage *image = module->image;
3529 t = &image->tables [MONO_TABLE_TYPEDEF];
3531 for (i = 0; i < t->rows; ++i) {
3532 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3534 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3535 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3540 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3542 MonoDynamicTable *table;
3548 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3550 if (assemblyb->type_forwarders) {
3551 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3552 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3558 klass = mono_class_from_mono_type (t->type);
3560 scope = resolution_scope_from_image (assembly, klass->image);
3561 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3562 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3565 alloc_table (table, table->rows);
3566 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3568 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3569 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3570 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3571 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3572 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3579 #define align_pointer(base,p)\
3581 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3583 (p) += 4 - (__diff & 3);\
3587 compare_constants (const void *a, const void *b)
3589 const guint32 *a_values = a;
3590 const guint32 *b_values = b;
3591 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3595 compare_semantics (const void *a, const void *b)
3597 const guint32 *a_values = a;
3598 const guint32 *b_values = b;
3599 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3602 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3606 compare_custom_attrs (const void *a, const void *b)
3608 const guint32 *a_values = a;
3609 const guint32 *b_values = b;
3611 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3615 compare_field_marshal (const void *a, const void *b)
3617 const guint32 *a_values = a;
3618 const guint32 *b_values = b;
3620 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3624 compare_nested (const void *a, const void *b)
3626 const guint32 *a_values = a;
3627 const guint32 *b_values = b;
3629 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3633 compare_genericparam (const void *a, const void *b)
3635 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3636 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3638 if ((*b_entry)->owner == (*a_entry)->owner)
3640 (*a_entry)->gparam->type.type->data.generic_param->num -
3641 (*b_entry)->gparam->type.type->data.generic_param->num;
3643 return (*a_entry)->owner - (*b_entry)->owner;
3647 compare_declsecurity_attrs (const void *a, const void *b)
3649 const guint32 *a_values = a;
3650 const guint32 *b_values = b;
3652 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3656 compare_interface_impl (const void *a, const void *b)
3658 const guint32 *a_values = a;
3659 const guint32 *b_values = b;
3661 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3665 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3669 pad_heap (MonoDynamicStream *sh)
3671 if (sh->index & 3) {
3672 int sz = 4 - (sh->index & 3);
3673 memset (sh->data + sh->index, 0, sz);
3680 MonoDynamicStream *stream;
3684 * build_compressed_metadata() fills in the blob of data that represents the
3685 * raw metadata as it will be saved in the PE file. The five streams are output
3686 * and the metadata tables are comnpressed from the guint32 array representation,
3687 * to the compressed on-disk format.
3690 build_compressed_metadata (MonoDynamicImage *assembly)
3692 MonoDynamicTable *table;
3694 guint64 valid_mask = 0;
3695 guint64 sorted_mask;
3696 guint32 heapt_size = 0;
3697 guint32 meta_size = 256; /* allow for header and other stuff */
3698 guint32 table_offset;
3699 guint32 ntables = 0;
3705 struct StreamDesc stream_desc [5];
3707 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3708 for (i = 0; i < assembly->gen_params->len; i++){
3709 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3710 write_generic_param_entry (assembly, entry);
3713 stream_desc [0].name = "#~";
3714 stream_desc [0].stream = &assembly->tstream;
3715 stream_desc [1].name = "#Strings";
3716 stream_desc [1].stream = &assembly->sheap;
3717 stream_desc [2].name = "#US";
3718 stream_desc [2].stream = &assembly->us;
3719 stream_desc [3].name = "#Blob";
3720 stream_desc [3].stream = &assembly->blob;
3721 stream_desc [4].name = "#GUID";
3722 stream_desc [4].stream = &assembly->guid;
3724 /* tables that are sorted */
3725 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3726 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3727 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3728 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3729 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3730 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3731 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3733 /* Compute table sizes */
3734 /* the MonoImage has already been created in mono_image_basic_init() */
3735 meta = &assembly->image;
3737 /* sizes should be multiple of 4 */
3738 pad_heap (&assembly->blob);
3739 pad_heap (&assembly->guid);
3740 pad_heap (&assembly->sheap);
3741 pad_heap (&assembly->us);
3743 /* Setup the info used by compute_sizes () */
3744 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3745 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3746 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3748 meta_size += assembly->blob.index;
3749 meta_size += assembly->guid.index;
3750 meta_size += assembly->sheap.index;
3751 meta_size += assembly->us.index;
3753 for (i=0; i < MONO_TABLE_NUM; ++i)
3754 meta->tables [i].rows = assembly->tables [i].rows;
3756 for (i = 0; i < MONO_TABLE_NUM; i++){
3757 if (meta->tables [i].rows == 0)
3759 valid_mask |= (guint64)1 << i;
3761 meta->tables [i].row_size = mono_metadata_compute_size (
3762 meta, i, &meta->tables [i].size_bitfield);
3763 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3765 heapt_size += 24; /* #~ header size */
3766 heapt_size += ntables * 4;
3767 /* make multiple of 4 */
3770 meta_size += heapt_size;
3771 meta->raw_metadata = g_malloc0 (meta_size);
3772 p = (unsigned char*)meta->raw_metadata;
3773 /* the metadata signature */
3774 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3775 /* version numbers and 4 bytes reserved */
3776 int16val = (guint16*)p;
3777 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3778 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3780 /* version string */
3781 int32val = (guint32*)p;
3782 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3784 memcpy (p, meta->version, strlen (meta->version));
3785 p += GUINT32_FROM_LE (*int32val);
3786 align_pointer (meta->raw_metadata, p);
3787 int16val = (guint16*)p;
3788 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3789 *int16val = GUINT16_TO_LE (5); /* number of streams */
3793 * write the stream info.
3795 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3796 table_offset += 3; table_offset &= ~3;
3798 assembly->tstream.index = heapt_size;
3799 for (i = 0; i < 5; ++i) {
3800 int32val = (guint32*)p;
3801 stream_desc [i].stream->offset = table_offset;
3802 *int32val++ = GUINT32_TO_LE (table_offset);
3803 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3804 table_offset += GUINT32_FROM_LE (*int32val);
3805 table_offset += 3; table_offset &= ~3;
3807 strcpy ((char*)p, stream_desc [i].name);
3808 p += strlen (stream_desc [i].name) + 1;
3809 align_pointer (meta->raw_metadata, p);
3812 * now copy the data, the table stream header and contents goes first.
3814 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3815 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3816 int32val = (guint32*)p;
3817 *int32val = GUINT32_TO_LE (0); /* reserved */
3820 if (mono_framework_version () > 1) {
3821 *p++ = 2; /* version */
3824 *p++ = 1; /* version */
3828 if (meta->idx_string_wide)
3830 if (meta->idx_guid_wide)
3832 if (meta->idx_blob_wide)
3835 *p++ = 1; /* reserved */
3836 int64val = (guint64*)p;
3837 *int64val++ = GUINT64_TO_LE (valid_mask);
3838 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3840 int32val = (guint32*)p;
3841 for (i = 0; i < MONO_TABLE_NUM; i++){
3842 if (meta->tables [i].rows == 0)
3844 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3846 p = (unsigned char*)int32val;
3848 /* sort the tables that still need sorting */
3849 table = &assembly->tables [MONO_TABLE_CONSTANT];
3851 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3852 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3854 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3855 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3857 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3858 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3860 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3861 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3863 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3864 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3865 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3867 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3868 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3870 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3872 /* compress the tables */
3873 for (i = 0; i < MONO_TABLE_NUM; i++){
3876 guint32 bitfield = meta->tables [i].size_bitfield;
3877 if (!meta->tables [i].rows)
3879 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3880 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3881 meta->tables [i].base = (char*)p;
3882 for (row = 1; row <= meta->tables [i].rows; ++row) {
3883 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3884 for (col = 0; col < assembly->tables [i].columns; ++col) {
3885 switch (mono_metadata_table_size (bitfield, col)) {
3887 *p++ = values [col];
3890 *p++ = values [col] & 0xff;
3891 *p++ = (values [col] >> 8) & 0xff;
3894 *p++ = values [col] & 0xff;
3895 *p++ = (values [col] >> 8) & 0xff;
3896 *p++ = (values [col] >> 16) & 0xff;
3897 *p++ = (values [col] >> 24) & 0xff;
3900 g_assert_not_reached ();
3904 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3907 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3908 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3909 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3910 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3911 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3913 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3917 * Some tables in metadata need to be sorted according to some criteria, but
3918 * when methods and fields are first created with reflection, they may be assigned a token
3919 * that doesn't correspond to the final token they will get assigned after the sorting.
3920 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3921 * with the reflection objects that represent them. Once all the tables are set up, the
3922 * reflection objects will contains the correct table index. fixup_method() will fixup the
3923 * tokens for the method with ILGenerator @ilgen.
3926 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3928 guint32 code_idx = GPOINTER_TO_UINT (value);
3929 MonoReflectionILTokenInfo *iltoken;
3930 MonoReflectionFieldBuilder *field;
3931 MonoReflectionCtorBuilder *ctor;
3932 MonoReflectionMethodBuilder *method;
3933 MonoReflectionTypeBuilder *tb;
3934 MonoReflectionArrayMethod *am;
3936 unsigned char *target;
3938 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3939 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3940 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3941 switch (target [3]) {
3942 case MONO_TABLE_FIELD:
3943 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3944 field = (MonoReflectionFieldBuilder *)iltoken->member;
3945 idx = field->table_idx;
3946 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3947 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3948 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3950 g_assert_not_reached ();
3953 case MONO_TABLE_METHOD:
3954 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3955 method = (MonoReflectionMethodBuilder *)iltoken->member;
3956 idx = method->table_idx;
3957 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3958 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3959 idx = ctor->table_idx;
3960 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3961 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3962 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3963 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3965 g_assert_not_reached ();
3968 case MONO_TABLE_TYPEDEF:
3969 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3970 g_assert_not_reached ();
3971 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3972 idx = tb->table_idx;
3974 case MONO_TABLE_MEMBERREF:
3975 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3976 am = (MonoReflectionArrayMethod*)iltoken->member;
3977 idx = am->table_idx;
3978 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3979 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3980 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3981 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3982 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3983 g_assert (m->klass->generic_class || m->klass->generic_container);
3985 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3987 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3988 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3989 g_assert (is_field_on_inst (f));
3991 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3992 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3994 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3996 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3998 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4001 g_assert_not_reached ();
4004 case MONO_TABLE_METHODSPEC:
4005 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4006 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4007 g_assert (mono_method_signature (m)->generic_param_count);
4009 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4012 g_assert_not_reached ();
4016 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4018 target [0] = idx & 0xff;
4019 target [1] = (idx >> 8) & 0xff;
4020 target [2] = (idx >> 16) & 0xff;
4027 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4028 * value is not known when the table is emitted.
4031 fixup_cattrs (MonoDynamicImage *assembly)
4033 MonoDynamicTable *table;
4035 guint32 type, i, idx, token;
4038 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4040 for (i = 0; i < table->rows; ++i) {
4041 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4043 type = values [MONO_CUSTOM_ATTR_TYPE];
4044 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4045 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4046 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4047 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4050 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4051 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4052 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4053 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4060 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4062 MonoDynamicTable *table;
4065 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4067 alloc_table (table, table->rows);
4068 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4069 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4070 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4071 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4072 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4077 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4079 MonoDynamicTable *table;
4083 char *b = blob_size;
4085 guint32 idx, offset;
4087 if (rsrc->filename) {
4088 name = mono_string_to_utf8 (rsrc->filename);
4089 sname = g_path_get_basename (name);
4091 table = &assembly->tables [MONO_TABLE_FILE];
4093 alloc_table (table, table->rows);
4094 values = table->values + table->next_idx * MONO_FILE_SIZE;
4095 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4096 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4099 mono_sha1_get_digest_from_file (name, hash);
4100 mono_metadata_encode_value (20, b, &b);
4101 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4102 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4104 idx = table->next_idx++;
4106 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4112 data = mono_array_addr (rsrc->data, char, 0);
4113 len = mono_array_length (rsrc->data);
4119 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4120 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4121 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4122 mono_image_add_stream_data (&assembly->resources, data, len);
4126 * The entry should be emitted into the MANIFESTRESOURCE table of
4127 * the main module, but that needs to reference the FILE table
4128 * which isn't emitted yet.
4135 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4139 set_version_from_string (MonoString *version, guint32 *values)
4141 gchar *ver, *p, *str;
4144 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4145 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4146 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4147 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4150 ver = str = mono_string_to_utf8 (version);
4151 for (i = 0; i < 4; ++i) {
4152 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4158 /* handle Revision and Build */
4168 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4172 char *b = blob_size;
4177 len = mono_array_length (pkey);
4178 mono_metadata_encode_value (len, b, &b);
4179 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4180 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4182 assembly->public_key = g_malloc (len);
4183 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4184 assembly->public_key_len = len;
4186 /* Special case: check for ECMA key (16 bytes) */
4187 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4188 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4189 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4190 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4191 /* minimum key size (in 2.0) is 384 bits */
4192 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4194 /* FIXME - verifier */
4195 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4196 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4198 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4204 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4206 MonoDynamicTable *table;
4207 MonoDynamicImage *assembly;
4208 MonoReflectionAssemblyBuilder *assemblyb;
4212 guint32 module_index;
4214 assemblyb = moduleb->assemblyb;
4215 assembly = moduleb->dynamic_image;
4216 domain = mono_object_domain (assemblyb);
4218 /* Emit ASSEMBLY table */
4219 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4220 alloc_table (table, 1);
4221 values = table->values + MONO_ASSEMBLY_SIZE;
4222 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4223 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4224 if (assemblyb->culture) {
4225 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4227 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4229 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4230 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4231 set_version_from_string (assemblyb->version, values);
4233 /* Emit FILE + EXPORTED_TYPE table */
4235 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4237 MonoReflectionModuleBuilder *file_module =
4238 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4239 if (file_module != moduleb) {
4240 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4242 if (file_module->types) {
4243 for (j = 0; j < file_module->num_types; ++j) {
4244 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4245 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4250 if (assemblyb->loaded_modules) {
4251 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4252 MonoReflectionModule *file_module =
4253 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4254 mono_image_fill_file_table (domain, file_module, assembly);
4256 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4259 if (assemblyb->type_forwarders)
4260 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4262 /* Emit MANIFESTRESOURCE table */
4264 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4266 MonoReflectionModuleBuilder *file_module =
4267 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4268 /* The table for the main module is emitted later */
4269 if (file_module != moduleb) {
4271 if (file_module->resources) {
4272 int len = mono_array_length (file_module->resources);
4273 for (j = 0; j < len; ++j) {
4274 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4275 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4282 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4285 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4286 * for the modulebuilder @moduleb.
4287 * At the end of the process, method and field tokens are fixed up and the
4288 * on-disk compressed metadata representation is created.
4291 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4293 MonoDynamicTable *table;
4294 MonoDynamicImage *assembly;
4295 MonoReflectionAssemblyBuilder *assemblyb;
4301 assemblyb = moduleb->assemblyb;
4302 assembly = moduleb->dynamic_image;
4303 domain = mono_object_domain (assemblyb);
4305 if (assembly->text_rva)
4308 assembly->text_rva = START_TEXT_RVA;
4310 if (moduleb->is_main) {
4311 mono_image_emit_manifest (moduleb);
4314 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4315 table->rows = 1; /* .<Module> */
4317 alloc_table (table, table->rows);
4319 * Set the first entry.
4321 values = table->values + table->columns;
4322 values [MONO_TYPEDEF_FLAGS] = 0;
4323 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4324 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4325 values [MONO_TYPEDEF_EXTENDS] = 0;
4326 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4327 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4330 * handle global methods
4331 * FIXME: test what to do when global methods are defined in multiple modules.
4333 if (moduleb->global_methods) {
4334 table = &assembly->tables [MONO_TABLE_METHOD];
4335 table->rows += mono_array_length (moduleb->global_methods);
4336 alloc_table (table, table->rows);
4337 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4338 mono_image_get_method_info (
4339 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4341 if (moduleb->global_fields) {
4342 table = &assembly->tables [MONO_TABLE_FIELD];
4343 table->rows += mono_array_length (moduleb->global_fields);
4344 alloc_table (table, table->rows);
4345 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4346 mono_image_get_field_info (
4347 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4350 table = &assembly->tables [MONO_TABLE_MODULE];
4351 alloc_table (table, 1);
4352 mono_image_fill_module_table (domain, moduleb, assembly);
4354 /* Collect all types into a list sorted by their table_idx */
4355 types = g_ptr_array_new ();
4358 for (i = 0; i < moduleb->num_types; ++i) {
4359 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4360 collect_types (types, type);
4363 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4364 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4365 table->rows += types->len;
4366 alloc_table (table, table->rows);
4369 * Emit type names + namespaces at one place inside the string heap,
4370 * so load_class_names () needs to touch fewer pages.
4372 for (i = 0; i < types->len; ++i) {
4373 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4374 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4376 for (i = 0; i < types->len; ++i) {
4377 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4378 string_heap_insert_mstring (&assembly->sheap, tb->name);
4381 for (i = 0; i < types->len; ++i) {
4382 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4383 mono_image_get_type_info (domain, type, assembly);
4387 * table->rows is already set above and in mono_image_fill_module_table.
4389 /* add all the custom attributes at the end, once all the indexes are stable */
4390 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4392 /* CAS assembly permissions */
4393 if (assemblyb->permissions_minimum)
4394 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4395 if (assemblyb->permissions_optional)
4396 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4397 if (assemblyb->permissions_refused)
4398 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4400 module_add_cattrs (assembly, moduleb);
4403 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4405 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4406 * the final tokens and don't need another fixup pass. */
4408 if (moduleb->global_methods) {
4409 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4410 MonoReflectionMethodBuilder *mb = mono_array_get (
4411 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4412 mono_image_add_methodimpl (assembly, mb);
4416 for (i = 0; i < types->len; ++i) {
4417 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4418 if (type->methods) {
4419 for (j = 0; j < type->num_methods; ++j) {
4420 MonoReflectionMethodBuilder *mb = mono_array_get (
4421 type->methods, MonoReflectionMethodBuilder*, j);
4423 mono_image_add_methodimpl (assembly, mb);
4428 g_ptr_array_free (types, TRUE);
4430 fixup_cattrs (assembly);
4433 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4436 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4438 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4441 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4443 #ifndef DISABLE_REFLECTION_EMIT
4446 * mono_image_insert_string:
4447 * @module: module builder object
4450 * Insert @str into the user string stream of @module.
4453 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4455 MonoDynamicImage *assembly;
4460 MONO_ARCH_SAVE_REGS;
4462 if (!module->dynamic_image)
4463 mono_image_module_basic_init (module);
4465 assembly = module->dynamic_image;
4467 if (assembly->save) {
4468 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4469 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4470 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4472 char *swapped = g_malloc (2 * mono_string_length (str));
4473 const char *p = (const char*)mono_string_chars (str);
4475 swap_with_size (swapped, p, 2, mono_string_length (str));
4476 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4480 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4482 mono_image_add_stream_data (&assembly->us, "", 1);
4484 idx = assembly->us.index ++;
4487 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4489 return MONO_TOKEN_STRING | idx;
4493 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4498 klass = obj->vtable->klass;
4499 if (strcmp (klass->name, "MonoMethod") == 0) {
4500 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4501 MonoMethodSignature *sig, *old;
4502 guint32 sig_token, parent;
4505 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4507 nargs = mono_array_length (opt_param_types);
4508 old = mono_method_signature (method);
4509 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4511 sig->hasthis = old->hasthis;
4512 sig->explicit_this = old->explicit_this;
4513 sig->call_convention = old->call_convention;
4514 sig->generic_param_count = old->generic_param_count;
4515 sig->param_count = old->param_count + nargs;
4516 sig->sentinelpos = old->param_count;
4517 sig->ret = old->ret;
4519 for (i = 0; i < old->param_count; i++)
4520 sig->params [i] = old->params [i];
4522 for (i = 0; i < nargs; i++) {
4523 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4524 sig->params [old->param_count + i] = rt->type;
4527 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4528 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4529 parent >>= MONO_TYPEDEFORREF_BITS;
4531 parent <<= MONO_MEMBERREF_PARENT_BITS;
4532 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4534 sig_token = method_encode_signature (assembly, sig);
4535 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4536 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4537 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4538 ReflectionMethodBuilder rmb;
4539 guint32 parent, sig;
4542 reflection_methodbuilder_from_method_builder (&rmb, mb);
4543 rmb.opt_types = opt_param_types;
4545 sig = method_builder_encode_signature (assembly, &rmb);
4547 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4548 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4550 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4551 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4553 name = mono_string_to_utf8 (rmb.name);
4554 token = mono_image_get_varargs_method_token (
4555 assembly, parent, name, sig);
4558 g_error ("requested method token for %s\n", klass->name);
4565 * mono_image_create_token:
4566 * @assembly: a dynamic assembly
4568 * @register_token: Whenever to register the token in the assembly->tokens hash.
4570 * Get a token to insert in the IL code stream for the given MemberInfo.
4571 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4572 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4576 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4577 gboolean create_methodspec, gboolean register_token)
4582 klass = obj->vtable->klass;
4583 if (strcmp (klass->name, "MethodBuilder") == 0) {
4584 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4585 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4587 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4588 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4590 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4591 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4592 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4593 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4594 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4596 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4597 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4599 token = mono_image_get_ctorbuilder_token (assembly, mb);
4600 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4601 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4602 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4603 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4604 if (tb->generic_params) {
4605 token = mono_image_get_generic_field_token (assembly, fb);
4607 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4609 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4611 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4612 } else if (strcmp (klass->name, "MonoType") == 0) {
4613 MonoReflectionType *tb = (MonoReflectionType *)obj;
4614 MonoClass *mc = mono_class_from_mono_type (tb->type);
4615 token = mono_metadata_token_from_dor (
4616 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4617 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4618 MonoReflectionType *tb = (MonoReflectionType *)obj;
4619 token = mono_metadata_token_from_dor (
4620 mono_image_typedef_or_ref (assembly, tb->type));
4621 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4622 MonoReflectionType *tb = (MonoReflectionType *)obj;
4623 token = mono_metadata_token_from_dor (
4624 mono_image_typedef_or_ref (assembly, tb->type));
4625 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4626 strcmp (klass->name, "MonoMethod") == 0 ||
4627 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4628 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4629 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4630 if (m->method->is_inflated) {
4631 if (create_methodspec)
4632 token = mono_image_get_methodspec_token (assembly, m->method);
4634 token = mono_image_get_inflated_method_token (assembly, m->method);
4635 } else if ((m->method->klass->image == &assembly->image) &&
4636 !m->method->klass->generic_class) {
4637 static guint32 method_table_idx = 0xffffff;
4638 if (m->method->klass->wastypebuilder) {
4639 /* we use the same token as the one that was assigned
4640 * to the Methodbuilder.
4641 * FIXME: do the equivalent for Fields.
4643 token = m->method->token;
4646 * Each token should have a unique index, but the indexes are
4647 * assigned by managed code, so we don't know about them. An
4648 * easy solution is to count backwards...
4650 method_table_idx --;
4651 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4654 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4656 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4657 } else if (strcmp (klass->name, "MonoField") == 0) {
4658 MonoReflectionField *f = (MonoReflectionField *)obj;
4659 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4660 static guint32 field_table_idx = 0xffffff;
4662 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4664 token = mono_image_get_fieldref_token (assembly, f);
4666 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4667 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4668 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4669 token = mono_image_get_array_token (assembly, m);
4670 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4671 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4672 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4673 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4674 MonoReflectionType *tb = (MonoReflectionType *)obj;
4675 token = mono_metadata_token_from_dor (
4676 mono_image_typedef_or_ref (assembly, tb->type));
4677 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4678 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4679 token = mono_image_get_field_on_inst_token (assembly, f);
4680 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4681 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4682 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4683 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4684 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4685 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4687 g_error ("requested token for %s\n", klass->name);
4691 mono_image_register_token (assembly, token, obj);
4697 * mono_image_register_token:
4699 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4700 * the Module.ResolveXXXToken () methods to work.
4703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4705 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4707 /* There could be multiple MethodInfo objects with the same token */
4708 //g_assert (prev == obj);
4710 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4714 #endif /* DISABLE_REFLECTION_EMIT */
4717 guint32 import_lookup_table;
4721 guint32 import_address_table_rva;
4729 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4731 static MonoDynamicImage*
4732 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4734 static const guchar entrycode [16] = {0xff, 0x25, 0};
4735 MonoDynamicImage *image;
4738 const char *version;
4740 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4741 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4743 version = mono_get_runtime_info ()->runtime_version;
4746 image = GC_MALLOC (sizeof (MonoDynamicImage));
4748 image = g_new0 (MonoDynamicImage, 1);
4751 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4753 /*g_print ("created image %p\n", image);*/
4754 /* keep in sync with image.c */
4755 image->image.name = assembly_name;
4756 image->image.assembly_name = image->image.name; /* they may be different */
4757 image->image.module_name = module_name;
4758 image->image.version = g_strdup (version);
4759 image->image.md_version_major = 1;
4760 image->image.md_version_minor = 1;
4761 image->image.dynamic = TRUE;
4763 image->image.references = g_new0 (MonoAssembly*, 1);
4764 image->image.references [0] = NULL;
4766 mono_image_init (&image->image);
4768 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4769 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4770 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4771 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4772 image->handleref = g_hash_table_new (NULL, NULL);
4773 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4774 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4775 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4776 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4777 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4778 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4779 image->gen_params = g_ptr_array_new ();
4781 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4782 string_heap_init (&image->sheap);
4783 mono_image_add_stream_data (&image->us, "", 1);
4784 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4785 /* import tables... */
4786 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4787 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4788 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4789 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4790 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4791 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4792 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4793 stream_data_align (&image->code);
4795 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4797 for (i=0; i < MONO_TABLE_NUM; ++i) {
4798 image->tables [i].next_idx = 1;
4799 image->tables [i].columns = table_sizes [i];
4802 image->image.assembly = (MonoAssembly*)assembly;
4803 image->run = assembly->run;
4804 image->save = assembly->save;
4805 image->pe_kind = 0x1; /* ILOnly */
4806 image->machine = 0x14c; /* I386 */
4808 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4814 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4820 mono_dynamic_image_free (MonoDynamicImage *image)
4822 MonoDynamicImage *di = image;
4827 mono_g_hash_table_destroy (di->methodspec);
4829 g_hash_table_destroy (di->typespec);
4831 g_hash_table_destroy (di->typeref);
4833 g_hash_table_destroy (di->handleref);
4835 mono_g_hash_table_destroy (di->tokens);
4836 if (di->generic_def_objects)
4837 mono_g_hash_table_destroy (di->generic_def_objects);
4838 if (di->blob_cache) {
4839 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4840 g_hash_table_destroy (di->blob_cache);
4842 if (di->standalonesig_cache)
4843 g_hash_table_destroy (di->standalonesig_cache);
4844 for (list = di->array_methods; list; list = list->next) {
4845 ArrayMethod *am = (ArrayMethod *)list->data;
4850 g_list_free (di->array_methods);
4851 if (di->gen_params) {
4852 for (i = 0; i < di->gen_params->len; i++) {
4853 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4854 if (entry->gparam->type.type) {
4855 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4856 g_free ((char*)param->name);
4861 g_ptr_array_free (di->gen_params, TRUE);
4863 if (di->token_fixups)
4864 mono_g_hash_table_destroy (di->token_fixups);
4865 if (di->method_to_table_idx)
4866 g_hash_table_destroy (di->method_to_table_idx);
4867 if (di->field_to_table_idx)
4868 g_hash_table_destroy (di->field_to_table_idx);
4869 if (di->method_aux_hash)
4870 g_hash_table_destroy (di->method_aux_hash);
4871 g_free (di->strong_name);
4872 g_free (di->win32_res);
4874 g_free (di->public_key);
4876 /*g_print ("string heap destroy for image %p\n", di);*/
4877 mono_dynamic_stream_reset (&di->sheap);
4878 mono_dynamic_stream_reset (&di->code);
4879 mono_dynamic_stream_reset (&di->resources);
4880 mono_dynamic_stream_reset (&di->us);
4881 mono_dynamic_stream_reset (&di->blob);
4882 mono_dynamic_stream_reset (&di->tstream);
4883 mono_dynamic_stream_reset (&di->guid);
4884 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4885 g_free (di->tables [i].values);
4889 #ifndef DISABLE_REFLECTION_EMIT
4892 * mono_image_basic_init:
4893 * @assembly: an assembly builder object
4895 * Create the MonoImage that represents the assembly builder and setup some
4896 * of the helper hash table and the basic metadata streams.
4899 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4901 MonoDynamicAssembly *assembly;
4902 MonoDynamicImage *image;
4903 MonoDomain *domain = mono_object_domain (assemblyb);
4905 MONO_ARCH_SAVE_REGS;
4907 if (assemblyb->dynamic_assembly)
4911 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4913 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4916 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4918 assembly->assembly.ref_count = 1;
4919 assembly->assembly.dynamic = TRUE;
4920 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4921 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4922 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4923 if (assemblyb->culture)
4924 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4926 assembly->assembly.aname.culture = g_strdup ("");
4928 if (assemblyb->version) {
4929 char *vstr = mono_string_to_utf8 (assemblyb->version);
4930 char **version = g_strsplit (vstr, ".", 4);
4931 char **parts = version;
4932 assembly->assembly.aname.major = atoi (*parts++);
4933 assembly->assembly.aname.minor = atoi (*parts++);
4934 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4935 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4937 g_strfreev (version);
4940 assembly->assembly.aname.major = 0;
4941 assembly->assembly.aname.minor = 0;
4942 assembly->assembly.aname.build = 0;
4943 assembly->assembly.aname.revision = 0;
4946 assembly->run = assemblyb->access != 2;
4947 assembly->save = assemblyb->access != 1;
4949 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4950 image->initial_image = TRUE;
4951 assembly->assembly.aname.name = image->image.name;
4952 assembly->assembly.image = &image->image;
4954 mono_domain_assemblies_lock (domain);
4955 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4956 mono_domain_assemblies_unlock (domain);
4958 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4960 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4962 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4965 #endif /* DISABLE_REFLECTION_EMIT */
4968 calc_section_size (MonoDynamicImage *assembly)
4972 /* alignment constraints */
4973 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4974 g_assert ((assembly->code.index % 4) == 0);
4975 assembly->meta_size += 3;
4976 assembly->meta_size &= ~3;
4977 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4978 g_assert ((assembly->resources.index % 4) == 0);
4980 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4981 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4984 if (assembly->win32_res) {
4985 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4987 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4988 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4992 assembly->sections [MONO_SECTION_RELOC].size = 12;
4993 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5003 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5007 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5009 ResTreeNode *t1 = (ResTreeNode*)a;
5010 ResTreeNode *t2 = (ResTreeNode*)b;
5012 return t1->id - t2->id;
5016 * resource_tree_create:
5018 * Organize the resources into a resource tree.
5020 static ResTreeNode *
5021 resource_tree_create (MonoArray *win32_resources)
5023 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5027 tree = g_new0 (ResTreeNode, 1);
5029 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5030 MonoReflectionWin32Resource *win32_res =
5031 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5035 /* FIXME: BUG: this stores managed references in unmanaged memory */
5036 lang_node = g_new0 (ResTreeNode, 1);
5037 lang_node->id = win32_res->lang_id;
5038 lang_node->win32_res = win32_res;
5040 /* Create type node if neccesary */
5042 for (l = tree->children; l; l = l->next)
5043 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5044 type_node = (ResTreeNode*)l->data;
5049 type_node = g_new0 (ResTreeNode, 1);
5050 type_node->id = win32_res->res_type;
5053 * The resource types have to be sorted otherwise
5054 * Windows Explorer can't display the version information.
5056 tree->children = g_slist_insert_sorted (tree->children,
5057 type_node, resource_tree_compare_by_id);
5060 /* Create res node if neccesary */
5062 for (l = type_node->children; l; l = l->next)
5063 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5064 res_node = (ResTreeNode*)l->data;
5069 res_node = g_new0 (ResTreeNode, 1);
5070 res_node->id = win32_res->res_id;
5071 type_node->children = g_slist_append (type_node->children, res_node);
5074 res_node->children = g_slist_append (res_node->children, lang_node);
5081 * resource_tree_encode:
5083 * Encode the resource tree into the format used in the PE file.
5086 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5089 MonoPEResourceDir dir;
5090 MonoPEResourceDirEntry dir_entry;
5091 MonoPEResourceDataEntry data_entry;
5093 guint32 res_id_entries;
5096 * For the format of the resource directory, see the article
5097 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5101 memset (&dir, 0, sizeof (dir));
5102 memset (&dir_entry, 0, sizeof (dir_entry));
5103 memset (&data_entry, 0, sizeof (data_entry));
5105 g_assert (sizeof (dir) == 16);
5106 g_assert (sizeof (dir_entry) == 8);
5107 g_assert (sizeof (data_entry) == 16);
5109 node->offset = p - begin;
5111 /* IMAGE_RESOURCE_DIRECTORY */
5112 res_id_entries = g_slist_length (node->children);
5113 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5115 memcpy (p, &dir, sizeof (dir));
5118 /* Reserve space for entries */
5120 p += sizeof (dir_entry) * res_id_entries;
5122 /* Write children */
5123 for (l = node->children; l; l = l->next) {
5124 ResTreeNode *child = (ResTreeNode*)l->data;
5126 if (child->win32_res) {
5129 child->offset = p - begin;
5131 /* IMAGE_RESOURCE_DATA_ENTRY */
5132 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5133 size = mono_array_length (child->win32_res->res_data);
5134 data_entry.rde_size = GUINT32_TO_LE (size);
5136 memcpy (p, &data_entry, sizeof (data_entry));
5137 p += sizeof (data_entry);
5139 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5142 resource_tree_encode (child, begin, p, &p);
5146 /* IMAGE_RESOURCE_ENTRY */
5147 for (l = node->children; l; l = l->next) {
5148 ResTreeNode *child = (ResTreeNode*)l->data;
5150 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5151 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5153 memcpy (entries, &dir_entry, sizeof (dir_entry));
5154 entries += sizeof (dir_entry);
5161 resource_tree_free (ResTreeNode * node)
5164 for (list = node->children; list; list = list->next)
5165 resource_tree_free ((ResTreeNode*)list->data);
5166 g_slist_free(node->children);
5171 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5176 MonoReflectionWin32Resource *win32_res;
5179 if (!assemblyb->win32_resources)
5183 * Resources are stored in a three level tree inside the PE file.
5184 * - level one contains a node for each type of resource
5185 * - level two contains a node for each resource
5186 * - level three contains a node for each instance of a resource for a
5187 * specific language.
5190 tree = resource_tree_create (assemblyb->win32_resources);
5192 /* Estimate the size of the encoded tree */
5194 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5195 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5196 size += mono_array_length (win32_res->res_data);
5198 /* Directory structure */
5199 size += mono_array_length (assemblyb->win32_resources) * 256;
5200 p = buf = g_malloc (size);
5202 resource_tree_encode (tree, p, p, &p);
5204 g_assert (p - buf <= size);
5206 assembly->win32_res = g_malloc (p - buf);
5207 assembly->win32_res_size = p - buf;
5208 memcpy (assembly->win32_res, buf, p - buf);
5211 resource_tree_free (tree);
5215 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5217 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5220 p += sizeof (MonoPEResourceDir);
5221 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5222 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5223 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5224 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5225 fixup_resource_directory (res_section, child, rva);
5227 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5228 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5231 p += sizeof (MonoPEResourceDirEntry);
5236 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5239 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5240 g_error ("WriteFile returned %d\n", GetLastError ());
5243 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5246 * mono_image_create_pefile:
5247 * @mb: a module builder object
5249 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5250 * assembly->pefile where it can be easily retrieved later in chunks.
5253 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5255 MonoMSDOSHeader *msdos;
5256 MonoDotNetHeader *header;
5257 MonoSectionTable *section;
5258 MonoCLIHeader *cli_header;
5259 guint32 size, image_size, virtual_base, text_offset;
5260 guint32 header_start, section_start, file_offset, virtual_offset;
5261 MonoDynamicImage *assembly;
5262 MonoReflectionAssemblyBuilder *assemblyb;
5263 MonoDynamicStream pefile_stream = {0};
5264 MonoDynamicStream *pefile = &pefile_stream;
5266 guint32 *rva, value;
5268 static const unsigned char msheader[] = {
5269 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5270 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5273 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5274 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5275 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5276 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5279 assemblyb = mb->assemblyb;
5281 mono_image_basic_init (assemblyb);
5282 assembly = mb->dynamic_image;
5284 assembly->pe_kind = assemblyb->pe_kind;
5285 assembly->machine = assemblyb->machine;
5286 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5287 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5289 mono_image_build_metadata (mb);
5291 if (mb->is_main && assemblyb->resources) {
5292 int len = mono_array_length (assemblyb->resources);
5293 for (i = 0; i < len; ++i)
5294 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5297 if (mb->resources) {
5298 int len = mono_array_length (mb->resources);
5299 for (i = 0; i < len; ++i)
5300 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5303 build_compressed_metadata (assembly);
5306 assembly_add_win32_resources (assembly, assemblyb);
5308 nsections = calc_section_size (assembly);
5310 /* The DOS header and stub */
5311 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5312 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5314 /* the dotnet header */
5315 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5317 /* the section tables */
5318 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5320 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5321 virtual_offset = VIRT_ALIGN;
5324 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5325 if (!assembly->sections [i].size)
5328 file_offset += FILE_ALIGN - 1;
5329 file_offset &= ~(FILE_ALIGN - 1);
5330 virtual_offset += VIRT_ALIGN - 1;
5331 virtual_offset &= ~(VIRT_ALIGN - 1);
5333 assembly->sections [i].offset = file_offset;
5334 assembly->sections [i].rva = virtual_offset;
5336 file_offset += assembly->sections [i].size;
5337 virtual_offset += assembly->sections [i].size;
5338 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5341 file_offset += FILE_ALIGN - 1;
5342 file_offset &= ~(FILE_ALIGN - 1);
5344 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5346 /* back-patch info */
5347 msdos = (MonoMSDOSHeader*)pefile->data;
5348 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5350 header = (MonoDotNetHeader*)(pefile->data + header_start);
5351 header->pesig [0] = 'P';
5352 header->pesig [1] = 'E';
5354 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5355 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5356 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5357 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5358 if (assemblyb->pekind == 1) {
5360 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5363 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5366 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5368 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5369 header->pe.pe_major = 6;
5370 header->pe.pe_minor = 0;
5371 size = assembly->sections [MONO_SECTION_TEXT].size;
5372 size += FILE_ALIGN - 1;
5373 size &= ~(FILE_ALIGN - 1);
5374 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5375 size = assembly->sections [MONO_SECTION_RSRC].size;
5376 size += FILE_ALIGN - 1;
5377 size &= ~(FILE_ALIGN - 1);
5378 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5379 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5380 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5381 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5382 /* pe_rva_entry_point always at the beginning of the text section */
5383 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5385 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5386 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5387 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5388 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5389 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5390 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5391 size = section_start;
5392 size += FILE_ALIGN - 1;
5393 size &= ~(FILE_ALIGN - 1);
5394 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5396 size += VIRT_ALIGN - 1;
5397 size &= ~(VIRT_ALIGN - 1);
5398 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5401 // Translate the PEFileKind value to the value expected by the Windows loader
5407 // PEFileKinds.Dll == 1
5408 // PEFileKinds.ConsoleApplication == 2
5409 // PEFileKinds.WindowApplication == 3
5412 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5413 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5415 if (assemblyb->pekind == 3)
5420 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5422 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5423 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5424 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5425 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5426 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5427 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5429 /* fill data directory entries */
5431 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5432 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5434 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5435 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5437 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5438 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5439 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5440 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5441 /* patch entrypoint name */
5442 if (assemblyb->pekind == 1)
5443 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5445 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5446 /* patch imported function RVA name */
5447 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5448 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5450 /* the import table */
5451 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5452 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5453 /* patch imported dll RVA name and other entries in the dir */
5454 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5455 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5456 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5457 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5458 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5459 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5461 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5462 value = (assembly->text_rva + assembly->imp_names_offset);
5463 *p++ = (value) & 0xff;
5464 *p++ = (value >> 8) & (0xff);
5465 *p++ = (value >> 16) & (0xff);
5466 *p++ = (value >> 24) & (0xff);
5468 /* the CLI header info */
5469 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5470 cli_header->ch_size = GUINT32_FROM_LE (72);
5471 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5472 if (mono_framework_version () > 1)
5473 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5475 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5476 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5477 if (assemblyb->entry_point) {
5478 guint32 table_idx = 0;
5479 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5480 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5481 table_idx = methodb->table_idx;
5483 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5485 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5487 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5489 /* The embedded managed resources */
5490 text_offset = assembly->text_rva + assembly->code.index;
5491 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5492 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5493 text_offset += assembly->resources.index;
5494 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5495 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5496 text_offset += assembly->meta_size;
5497 if (assembly->strong_name_size) {
5498 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5499 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5500 text_offset += assembly->strong_name_size;
5503 /* write the section tables and section content */
5504 section = (MonoSectionTable*)(pefile->data + section_start);
5505 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5506 static const char section_names [][7] = {
5507 ".text", ".rsrc", ".reloc"
5509 if (!assembly->sections [i].size)
5511 strcpy (section->st_name, section_names [i]);
5512 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5513 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5514 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5515 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5516 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5517 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5518 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5522 checked_write_file (file, pefile->data, pefile->index);
5524 mono_dynamic_stream_reset (pefile);
5526 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5527 if (!assembly->sections [i].size)
5530 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5531 g_error ("SetFilePointer returned %d\n", GetLastError ());
5534 case MONO_SECTION_TEXT:
5535 /* patch entry point */
5536 p = (guchar*)(assembly->code.data + 2);
5537 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5538 *p++ = (value) & 0xff;
5539 *p++ = (value >> 8) & 0xff;
5540 *p++ = (value >> 16) & 0xff;
5541 *p++ = (value >> 24) & 0xff;
5543 checked_write_file (file, assembly->code.data, assembly->code.index);
5544 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5545 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5546 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5549 g_free (assembly->image.raw_metadata);
5551 case MONO_SECTION_RELOC: {
5555 guint16 type_and_offset;
5559 g_assert (sizeof (reloc) == 12);
5561 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5562 reloc.block_size = GUINT32_FROM_LE (12);
5565 * the entrypoint is always at the start of the text section
5566 * 3 is IMAGE_REL_BASED_HIGHLOW
5567 * 2 is patch_size_rva - text_rva
5569 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5572 checked_write_file (file, &reloc, sizeof (reloc));
5576 case MONO_SECTION_RSRC:
5577 if (assembly->win32_res) {
5579 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5580 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5581 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5585 g_assert_not_reached ();
5589 /* check that the file is properly padded */
5590 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5591 g_error ("SetFilePointer returned %d\n", GetLastError ());
5592 if (! SetEndOfFile (file))
5593 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5595 mono_dynamic_stream_reset (&assembly->code);
5596 mono_dynamic_stream_reset (&assembly->us);
5597 mono_dynamic_stream_reset (&assembly->blob);
5598 mono_dynamic_stream_reset (&assembly->guid);
5599 mono_dynamic_stream_reset (&assembly->sheap);
5601 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5602 g_hash_table_destroy (assembly->blob_cache);
5603 assembly->blob_cache = NULL;
5606 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5609 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5611 g_assert_not_reached ();
5614 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5616 #ifndef DISABLE_REFLECTION_EMIT
5618 MonoReflectionModule *
5619 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5623 MonoImageOpenStatus status;
5624 MonoDynamicAssembly *assembly;
5625 guint32 module_count;
5626 MonoImage **new_modules;
5627 gboolean *new_modules_loaded;
5629 name = mono_string_to_utf8 (fileName);
5631 image = mono_image_open (name, &status);
5634 if (status == MONO_IMAGE_ERROR_ERRNO)
5635 exc = mono_get_exception_file_not_found (fileName);
5637 exc = mono_get_exception_bad_image_format (name);
5639 mono_raise_exception (exc);
5644 assembly = ab->dynamic_assembly;
5645 image->assembly = (MonoAssembly*)assembly;
5647 module_count = image->assembly->image->module_count;
5648 new_modules = g_new0 (MonoImage *, module_count + 1);
5649 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5651 if (image->assembly->image->modules)
5652 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5653 if (image->assembly->image->modules_loaded)
5654 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5655 new_modules [module_count] = image;
5656 new_modules_loaded [module_count] = TRUE;
5657 mono_image_addref (image);
5659 g_free (image->assembly->image->modules);
5660 image->assembly->image->modules = new_modules;
5661 image->assembly->image->modules_loaded = new_modules_loaded;
5662 image->assembly->image->module_count ++;
5664 mono_assembly_load_references (image, &status);
5666 mono_image_close (image);
5667 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5670 return mono_module_get_object (mono_domain_get (), image);
5673 #endif /* DISABLE_REFLECTION_EMIT */
5676 * We need to return always the same object for MethodInfo, FieldInfo etc..
5677 * but we need to consider the reflected type.
5678 * type uses a different hash, since it uses custom hash/equal functions.
5683 MonoClass *refclass;
5687 reflected_equal (gconstpointer a, gconstpointer b) {
5688 const ReflectedEntry *ea = a;
5689 const ReflectedEntry *eb = b;
5691 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5695 reflected_hash (gconstpointer a) {
5696 const ReflectedEntry *ea = a;
5697 return mono_aligned_addr_hash (ea->item);
5700 #define CHECK_OBJECT(t,p,k) \
5706 mono_domain_lock (domain); \
5707 if (!domain->refobject_hash) \
5708 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5709 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5710 mono_domain_unlock (domain); \
5713 mono_domain_unlock (domain); \
5716 #ifdef HAVE_BOEHM_GC
5717 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5718 #define FREE_REFENTRY(entry) mono_gc_free_fixed ((entry))
5720 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5722 #define FREE_REFENTRY(entry)
5725 #define CACHE_OBJECT(t,p,o,k) \
5728 ReflectedEntry pe; \
5730 pe.refclass = (k); \
5731 mono_domain_lock (domain); \
5732 if (!domain->refobject_hash) \
5733 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5734 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5736 ReflectedEntry *e = ALLOC_REFENTRY; \
5738 e->refclass = (k); \
5739 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5742 mono_domain_unlock (domain); \
5747 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5749 mono_domain_lock (domain);
5750 if (domain->refobject_hash) {
5752 gpointer orig_pe, orig_value;
5755 pe.refclass = klass;
5756 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5757 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5758 FREE_REFENTRY (orig_pe);
5761 mono_domain_unlock (domain);
5765 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5767 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5771 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5773 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5776 #ifndef DISABLE_REFLECTION_EMIT
5779 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5781 MonoDynamicImage *image = moduleb->dynamic_image;
5782 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5785 MonoImage **new_modules;
5788 * FIXME: we already created an image in mono_image_basic_init (), but
5789 * we don't know which module it belongs to, since that is only
5790 * determined at assembly save time.
5792 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5793 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5795 moduleb->module.image = &image->image;
5796 moduleb->dynamic_image = image;
5797 register_module (mono_object_domain (moduleb), moduleb, image);
5799 /* register the module with the assembly */
5800 ass = ab->dynamic_assembly->assembly.image;
5801 module_count = ass->module_count;
5802 new_modules = g_new0 (MonoImage *, module_count + 1);
5805 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5806 new_modules [module_count] = &image->image;
5807 mono_image_addref (&image->image);
5809 g_free (ass->modules);
5810 ass->modules = new_modules;
5811 ass->module_count ++;
5818 * mono_assembly_get_object:
5819 * @domain: an app domain
5820 * @assembly: an assembly
5822 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5824 MonoReflectionAssembly*
5825 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5827 static MonoClass *System_Reflection_Assembly;
5828 MonoReflectionAssembly *res;
5830 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5831 if (!System_Reflection_Assembly)
5832 System_Reflection_Assembly = mono_class_from_name (
5833 mono_defaults.corlib, "System.Reflection", "Assembly");
5834 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5835 res->assembly = assembly;
5837 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5842 MonoReflectionModule*
5843 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5845 static MonoClass *System_Reflection_Module;
5846 MonoReflectionModule *res;
5849 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5850 if (!System_Reflection_Module)
5851 System_Reflection_Module = mono_class_from_name (
5852 mono_defaults.corlib, "System.Reflection", "Module");
5853 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5856 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5858 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5859 basename = g_path_get_basename (image->name);
5860 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5861 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5865 if (image->assembly->image == image) {
5866 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5870 if (image->assembly->image->modules) {
5871 for (i = 0; i < image->assembly->image->module_count; i++) {
5872 if (image->assembly->image->modules [i] == image)
5873 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5875 g_assert (res->token);
5879 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5882 MonoReflectionModule*
5883 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5885 static MonoClass *System_Reflection_Module;
5886 MonoReflectionModule *res;
5887 MonoTableInfo *table;
5888 guint32 cols [MONO_FILE_SIZE];
5890 guint32 i, name_idx;
5893 if (!System_Reflection_Module)
5894 System_Reflection_Module = mono_class_from_name (
5895 mono_defaults.corlib, "System.Reflection", "Module");
5896 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5898 table = &image->tables [MONO_TABLE_FILE];
5899 g_assert (table_index < table->rows);
5900 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5903 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5904 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5906 /* Check whenever the row has a corresponding row in the moduleref table */
5907 table = &image->tables [MONO_TABLE_MODULEREF];
5908 for (i = 0; i < table->rows; ++i) {
5909 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5910 val = mono_metadata_string_heap (image, name_idx);
5911 if (strcmp (val, name) == 0)
5912 res->image = image->modules [i];
5915 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5916 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5917 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5918 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5919 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5925 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5927 if ((t1->type != t2->type) ||
5928 (t1->byref != t2->byref))
5932 case MONO_TYPE_VOID:
5933 case MONO_TYPE_BOOLEAN:
5934 case MONO_TYPE_CHAR:
5945 case MONO_TYPE_STRING:
5948 case MONO_TYPE_OBJECT:
5949 case MONO_TYPE_TYPEDBYREF:
5951 case MONO_TYPE_VALUETYPE:
5952 case MONO_TYPE_CLASS:
5953 case MONO_TYPE_SZARRAY:
5954 return t1->data.klass == t2->data.klass;
5956 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5957 case MONO_TYPE_ARRAY:
5958 if (t1->data.array->rank != t2->data.array->rank)
5960 return t1->data.array->eklass == t2->data.array->eklass;
5961 case MONO_TYPE_GENERICINST: {
5963 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5964 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5965 if (i1->type_argc != i2->type_argc)
5967 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5968 &t2->data.generic_class->container_class->byval_arg))
5970 /* FIXME: we should probably just compare the instance pointers directly. */
5971 for (i = 0; i < i1->type_argc; ++i) {
5972 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5978 case MONO_TYPE_MVAR:
5979 return t1->data.generic_param == t2->data.generic_param;
5981 g_error ("implement type compare for %0x!", t1->type);
5989 mymono_metadata_type_hash (MonoType *t1)
5995 hash |= t1->byref << 6; /* do not collide with t1->type values */
5997 case MONO_TYPE_VALUETYPE:
5998 case MONO_TYPE_CLASS:
5999 case MONO_TYPE_SZARRAY:
6000 /* check if the distribution is good enough */
6001 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6003 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6004 case MONO_TYPE_GENERICINST: {
6006 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6007 hash += g_str_hash (t1->data.generic_class->container_class->name);
6009 for (i = 0; i < inst->type_argc; ++i) {
6010 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6019 static MonoReflectionGenericClass*
6020 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6022 static MonoClass *System_Reflection_MonoGenericClass;
6023 MonoReflectionGenericClass *res;
6024 MonoClass *klass, *gklass;
6026 if (!System_Reflection_MonoGenericClass) {
6027 System_Reflection_MonoGenericClass = mono_class_from_name (
6028 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6029 g_assert (System_Reflection_MonoGenericClass);
6032 klass = mono_class_from_mono_type (geninst);
6033 gklass = klass->generic_class->container_class;
6035 mono_class_init (klass);
6038 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6040 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6043 res->type.type = geninst;
6044 g_assert (gklass->reflection_info);
6045 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6046 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6052 verify_safe_for_managed_space (MonoType *type)
6054 switch (type->type) {
6056 case MONO_TYPE_ARRAY:
6057 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6059 return verify_safe_for_managed_space (type->data.type);
6060 case MONO_TYPE_SZARRAY:
6061 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6062 case MONO_TYPE_GENERICINST: {
6063 MonoGenericInst *inst = type->data.generic_class->inst;
6067 for (i = 0; i < inst->type_argc; ++i)
6068 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6074 case MONO_TYPE_MVAR:
6081 * mono_type_get_object:
6082 * @domain: an app domain
6085 * Return an System.MonoType object representing the type @type.
6088 mono_type_get_object (MonoDomain *domain, MonoType *type)
6090 MonoReflectionType *res;
6091 MonoClass *klass = mono_class_from_mono_type (type);
6093 /*we must avoid using @type as it might have come
6094 * from a mono_metadata_type_dup and the caller
6095 * expects that is can be freed.
6096 * Using the right type from
6098 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6100 /* void is very common */
6101 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6102 return (MonoReflectionType*)domain->typeof_void;
6105 * If the vtable of the given class was already created, we can use
6106 * the MonoType from there and avoid all locking and hash table lookups.
6108 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6109 * that the resulting object is diferent.
6111 if (type == &klass->byval_arg && !klass->image->dynamic) {
6112 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6113 if (vtable && vtable->type)
6114 return vtable->type;
6117 mono_domain_lock (domain);
6118 if (!domain->type_hash)
6119 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6120 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6121 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6122 mono_domain_unlock (domain);
6125 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6126 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6127 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6128 mono_g_hash_table_insert (domain->type_hash, type, res);
6129 mono_domain_unlock (domain);
6133 if (!verify_safe_for_managed_space (type)) {
6134 mono_domain_unlock (domain);
6135 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6138 if (klass->reflection_info && !klass->wastypebuilder) {
6139 /* g_assert_not_reached (); */
6140 /* should this be considered an error condition? */
6142 mono_domain_unlock (domain);
6143 return klass->reflection_info;
6146 // FIXME: Get rid of this, do it in the icalls for Type
6147 mono_class_init (klass);
6149 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6151 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6154 mono_g_hash_table_insert (domain->type_hash, type, res);
6156 if (type->type == MONO_TYPE_VOID)
6157 MONO_OBJECT_SETREF (domain, typeof_void, res);
6159 mono_domain_unlock (domain);
6164 * mono_method_get_object:
6165 * @domain: an app domain
6167 * @refclass: the reflected type (can be NULL)
6169 * Return an System.Reflection.MonoMethod object representing the method @method.
6171 MonoReflectionMethod*
6172 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6175 * We use the same C representation for methods and constructors, but the type
6176 * name in C# is different.
6178 static MonoClass *System_Reflection_MonoMethod = NULL;
6179 static MonoClass *System_Reflection_MonoCMethod = NULL;
6180 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6181 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6183 MonoReflectionMethod *ret;
6186 * Don't let static RGCTX invoke wrappers get into
6187 * MonoReflectionMethods.
6189 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6190 method = mono_marshal_method_from_wrapper (method);
6192 if (method->is_inflated) {
6193 MonoReflectionGenericMethod *gret;
6195 refclass = method->klass;
6196 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6197 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6198 if (!System_Reflection_MonoGenericCMethod)
6199 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6200 klass = System_Reflection_MonoGenericCMethod;
6202 if (!System_Reflection_MonoGenericMethod)
6203 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6204 klass = System_Reflection_MonoGenericMethod;
6206 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6207 gret->method.method = method;
6208 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6209 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6210 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6214 refclass = method->klass;
6216 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6217 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6218 if (!System_Reflection_MonoCMethod)
6219 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6220 klass = System_Reflection_MonoCMethod;
6223 if (!System_Reflection_MonoMethod)
6224 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6225 klass = System_Reflection_MonoMethod;
6227 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6228 ret->method = method;
6229 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6230 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6234 * mono_method_clear_object:
6236 * Clear the cached reflection objects for the dynamic method METHOD.
6239 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6241 g_assert (method->dynamic);
6243 clear_cached_object (domain, method, method->klass);
6244 /* Added by mono_param_get_objects () */
6245 clear_cached_object (domain, &(method->signature), NULL);
6249 * mono_field_get_object:
6250 * @domain: an app domain
6254 * Return an System.Reflection.MonoField object representing the field @field
6257 MonoReflectionField*
6258 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6260 MonoReflectionField *res;
6261 static MonoClass *monofield_klass;
6263 CHECK_OBJECT (MonoReflectionField *, field, klass);
6264 if (!monofield_klass)
6265 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6266 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6269 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6270 if (is_field_on_inst (field))
6271 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6273 res->attrs = field->type->attrs;
6274 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6275 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6279 * mono_property_get_object:
6280 * @domain: an app domain
6282 * @property: a property
6284 * Return an System.Reflection.MonoProperty object representing the property @property
6287 MonoReflectionProperty*
6288 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6290 MonoReflectionProperty *res;
6291 static MonoClass *monoproperty_klass;
6293 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6294 if (!monoproperty_klass)
6295 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6296 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6298 res->property = property;
6299 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6303 * mono_event_get_object:
6304 * @domain: an app domain
6308 * Return an System.Reflection.MonoEvent object representing the event @event
6311 MonoReflectionEvent*
6312 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6314 MonoReflectionEvent *res;
6315 static MonoClass *monoevent_klass;
6317 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6318 if (!monoevent_klass)
6319 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6320 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6323 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6327 * mono_get_reflection_missing_object:
6328 * @domain: Domain where the object lives
6330 * Returns the System.Reflection.Missing.Value singleton object
6331 * (of type System.Reflection.Missing).
6333 * Used as the value for ParameterInfo.DefaultValue when Optional
6337 mono_get_reflection_missing_object (MonoDomain *domain)
6340 static MonoClassField *missing_value_field = NULL;
6342 if (!missing_value_field) {
6343 MonoClass *missing_klass;
6344 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6345 mono_class_init (missing_klass);
6346 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6347 g_assert (missing_value_field);
6349 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6355 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6358 *dbnull = mono_get_dbnull_object (domain);
6363 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6365 if (!*reflection_missing)
6366 *reflection_missing = mono_get_reflection_missing_object (domain);
6367 return *reflection_missing;
6371 * mono_param_get_objects:
6372 * @domain: an app domain
6375 * Return an System.Reflection.ParameterInfo array object representing the parameters
6376 * in the method @method.
6379 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6381 static MonoClass *System_Reflection_ParameterInfo;
6382 static MonoClass *System_Reflection_ParameterInfo_array;
6383 MonoArray *res = NULL;
6384 MonoReflectionMethod *member = NULL;
6385 MonoReflectionParameter *param = NULL;
6386 char **names, **blobs = NULL;
6387 guint32 *types = NULL;
6388 MonoType *type = NULL;
6389 MonoObject *dbnull = NULL;
6390 MonoObject *missing = NULL;
6391 MonoMarshalSpec **mspecs;
6392 MonoMethodSignature *sig;
6393 MonoVTable *pinfo_vtable;
6396 if (!System_Reflection_ParameterInfo_array) {
6399 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6400 mono_memory_barrier ();
6401 System_Reflection_ParameterInfo = klass;
6403 klass = mono_array_class_get (klass, 1);
6404 mono_memory_barrier ();
6405 System_Reflection_ParameterInfo_array = klass;
6408 if (!mono_method_signature (method)->param_count)
6409 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6411 /* Note: the cache is based on the address of the signature into the method
6412 * since we already cache MethodInfos with the method as keys.
6414 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6416 sig = mono_method_signature (method);
6417 member = mono_method_get_object (domain, method, NULL);
6418 names = g_new (char *, sig->param_count);
6419 mono_method_get_param_names (method, (const char **) names);
6421 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6422 mono_method_get_marshal_info (method, mspecs);
6424 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6425 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6426 for (i = 0; i < sig->param_count; ++i) {
6427 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6428 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6429 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6430 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6431 param->PositionImpl = i;
6432 param->AttrsImpl = sig->params [i]->attrs;
6434 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6435 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6436 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6438 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6442 blobs = g_new0 (char *, sig->param_count);
6443 types = g_new0 (guint32, sig->param_count);
6444 get_default_param_value_blobs (method, blobs, types);
6447 /* Build MonoType for the type from the Constant Table */
6449 type = g_new0 (MonoType, 1);
6450 type->type = types [i];
6451 type->data.klass = NULL;
6452 if (types [i] == MONO_TYPE_CLASS)
6453 type->data.klass = mono_defaults.object_class;
6454 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6455 /* For enums, types [i] contains the base type */
6457 type->type = MONO_TYPE_VALUETYPE;
6458 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6460 type->data.klass = mono_class_from_mono_type (type);
6462 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6464 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6465 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6466 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6467 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6469 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6475 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6477 mono_array_setref (res, i, param);
6484 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6486 mono_metadata_free_marshal_spec (mspecs [i]);
6489 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6493 * mono_method_body_get_object:
6494 * @domain: an app domain
6497 * Return an System.Reflection.MethodBody object representing the method @method.
6499 MonoReflectionMethodBody*
6500 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6502 static MonoClass *System_Reflection_MethodBody = NULL;
6503 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6504 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6505 MonoReflectionMethodBody *ret;
6506 MonoMethodNormal *mn;
6507 MonoMethodHeader *header;
6508 guint32 method_rva, local_var_sig_token;
6510 unsigned char format, flags;
6513 if (!System_Reflection_MethodBody)
6514 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6515 if (!System_Reflection_LocalVariableInfo)
6516 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6517 if (!System_Reflection_ExceptionHandlingClause)
6518 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6520 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6522 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6523 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6524 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6525 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6527 mn = (MonoMethodNormal *)method;
6528 header = mono_method_get_header (method);
6530 /* Obtain local vars signature token */
6531 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6532 ptr = mono_image_rva_map (method->klass->image, method_rva);
6533 flags = *(const unsigned char *) ptr;
6534 format = flags & METHOD_HEADER_FORMAT_MASK;
6536 case METHOD_HEADER_TINY_FORMAT:
6537 case METHOD_HEADER_TINY_FORMAT1:
6538 local_var_sig_token = 0;
6540 case METHOD_HEADER_FAT_FORMAT:
6544 local_var_sig_token = read32 (ptr);
6547 g_assert_not_reached ();
6550 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6552 ret->init_locals = header->init_locals;
6553 ret->max_stack = header->max_stack;
6554 ret->local_var_sig_token = local_var_sig_token;
6555 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6556 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6559 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6560 for (i = 0; i < header->num_locals; ++i) {
6561 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6562 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6563 info->is_pinned = header->locals [i]->pinned;
6564 info->local_index = i;
6565 mono_array_setref (ret->locals, i, info);
6569 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6570 for (i = 0; i < header->num_clauses; ++i) {
6571 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6572 MonoExceptionClause *clause = &header->clauses [i];
6574 info->flags = clause->flags;
6575 info->try_offset = clause->try_offset;
6576 info->try_length = clause->try_len;
6577 info->handler_offset = clause->handler_offset;
6578 info->handler_length = clause->handler_len;
6579 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6580 info->filter_offset = clause->data.filter_offset;
6581 else if (clause->data.catch_class)
6582 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6584 mono_array_setref (ret->clauses, i, info);
6587 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6592 * mono_get_dbnull_object:
6593 * @domain: Domain where the object lives
6595 * Returns the System.DBNull.Value singleton object
6597 * Used as the value for ParameterInfo.DefaultValue
6600 mono_get_dbnull_object (MonoDomain *domain)
6603 static MonoClassField *dbnull_value_field = NULL;
6605 if (!dbnull_value_field) {
6606 MonoClass *dbnull_klass;
6607 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6608 mono_class_init (dbnull_klass);
6609 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6610 g_assert (dbnull_value_field);
6612 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6618 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6620 guint32 param_index, i, lastp, crow = 0;
6621 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6624 MonoClass *klass = method->klass;
6625 MonoImage *image = klass->image;
6626 MonoMethodSignature *methodsig = mono_method_signature (method);
6628 MonoTableInfo *constt;
6629 MonoTableInfo *methodt;
6630 MonoTableInfo *paramt;
6632 if (!methodsig->param_count)
6635 mono_class_init (klass);
6637 if (klass->image->dynamic) {
6638 MonoReflectionMethodAux *aux;
6639 if (method->is_inflated)
6640 method = ((MonoMethodInflated*)method)->declaring;
6641 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6642 if (aux && aux->param_defaults) {
6643 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6644 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6649 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6650 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6651 constt = &image->tables [MONO_TABLE_CONSTANT];
6653 idx = mono_method_get_index (method) - 1;
6654 g_assert (idx != -1);
6656 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6657 if (idx + 1 < methodt->rows)
6658 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6660 lastp = paramt->rows + 1;
6662 for (i = param_index; i < lastp; ++i) {
6665 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6666 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6668 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6671 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6676 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6677 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6678 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6685 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6690 MonoType *basetype = type;
6695 klass = mono_class_from_mono_type (type);
6696 if (klass->valuetype) {
6697 object = mono_object_new (domain, klass);
6698 retval = ((gchar *) object + sizeof (MonoObject));
6699 if (klass->enumtype)
6700 basetype = mono_class_enum_basetype (klass);
6705 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6712 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6716 memset (assembly, 0, sizeof (MonoAssemblyName));
6718 assembly->culture = "";
6719 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6721 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6724 while (g_ascii_isspace (*p) || *p == ',') {
6733 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6735 assembly->major = strtoul (p, &s, 10);
6736 if (s == p || *s != '.')
6739 assembly->minor = strtoul (p, &s, 10);
6740 if (s == p || *s != '.')
6743 assembly->build = strtoul (p, &s, 10);
6744 if (s == p || *s != '.')
6747 assembly->revision = strtoul (p, &s, 10);
6751 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6753 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6754 assembly->culture = "";
6757 assembly->culture = p;
6758 while (*p && *p != ',') {
6762 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6764 if (strncmp (p, "null", 4) == 0) {
6769 while (*p && *p != ',') {
6772 len = (p - start + 1);
6773 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6774 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6775 g_strlcpy ((char*)assembly->public_key_token, start, len);
6778 while (*p && *p != ',')
6782 while (g_ascii_isspace (*p) || *p == ',') {
6796 * mono_reflection_parse_type:
6799 * Parse a type name as accepted by the GetType () method and output the info
6800 * extracted in the info structure.
6801 * the name param will be mangled, so, make a copy before passing it to this function.
6802 * The fields in info will be valid until the memory pointed to by name is valid.
6804 * See also mono_type_get_name () below.
6806 * Returns: 0 on parse error.
6809 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6810 MonoTypeNameParse *info)
6812 char *start, *p, *w, *temp, *last_point, *startn;
6813 int in_modifiers = 0;
6814 int isbyref = 0, rank, arity = 0, i;
6816 start = p = w = name;
6818 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6819 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6820 info->name = info->name_space = NULL;
6821 info->nested = NULL;
6822 info->modifiers = NULL;
6823 info->type_arguments = NULL;
6825 /* last_point separates the namespace from the name */
6828 while (*p == ' ') p++, start++, w++, name++;
6833 *p = 0; /* NULL terminate the name */
6835 info->nested = g_list_append (info->nested, startn);
6836 /* we have parsed the nesting namespace + name */
6840 info->name_space = start;
6842 info->name = last_point + 1;
6844 info->name_space = (char *)"";
6863 i = strtol (p, &temp, 10);
6880 info->name_space = start;
6882 info->name = last_point + 1;
6884 info->name_space = (char *)"";
6891 if (isbyref) /* only one level allowed by the spec */
6894 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6898 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6904 info->type_arguments = g_ptr_array_new ();
6905 for (i = 0; i < arity; i++) {
6906 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6907 gboolean fqname = FALSE;
6909 g_ptr_array_add (info->type_arguments, subinfo);
6916 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6927 while (*p && (*p != ']'))
6935 if (g_ascii_isspace (*aname)) {
6942 !assembly_name_to_aname (&subinfo->assembly, aname))
6946 if (i + 1 < arity) {
6966 else if (*p == '*') /* '*' means unknown lower bound */
6967 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6974 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6985 if (g_ascii_isspace (*p)) {
6992 return 0; /* missing assembly name */
6993 if (!assembly_name_to_aname (&info->assembly, p))
6999 if (info->assembly.name)
7002 // *w = 0; /* terminate class name */
7004 if (!info->name || !*info->name)
7008 /* add other consistency checks */
7013 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7015 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7019 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7021 gboolean type_resolve = FALSE;
7023 MonoImage *rootimage = image;
7025 if (info->assembly.name) {
7026 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7027 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7029 * This could happen in the AOT compiler case when the search hook is not
7032 assembly = image->assembly;
7034 /* then we must load the assembly ourselve - see #60439 */
7035 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7039 image = assembly->image;
7040 } else if (!image) {
7041 image = mono_defaults.corlib;
7044 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7045 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7046 image = mono_defaults.corlib;
7047 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7054 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7059 gboolean bounded = FALSE;
7062 image = mono_defaults.corlib;
7065 klass = mono_class_from_name_case (image, info->name_space, info->name);
7067 klass = mono_class_from_name (image, info->name_space, info->name);
7070 for (mod = info->nested; mod; mod = mod->next) {
7071 gpointer iter = NULL;
7075 mono_class_init (parent);
7077 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7079 if (g_strcasecmp (klass->name, mod->data) == 0)
7082 if (strcmp (klass->name, mod->data) == 0)
7091 mono_class_init (klass);
7093 if (info->type_arguments) {
7094 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7095 MonoReflectionType *the_type;
7099 for (i = 0; i < info->type_arguments->len; i++) {
7100 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7102 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7103 if (!type_args [i]) {
7109 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7111 instance = mono_reflection_bind_generic_parameters (
7112 the_type, info->type_arguments->len, type_args);
7118 klass = mono_class_from_mono_type (instance);
7121 for (mod = info->modifiers; mod; mod = mod->next) {
7122 modval = GPOINTER_TO_UINT (mod->data);
7123 if (!modval) { /* byref: must be last modifier */
7124 return &klass->this_arg;
7125 } else if (modval == -1) {
7126 klass = mono_ptr_class_get (&klass->byval_arg);
7127 } else if (modval == -2) {
7129 } else { /* array rank */
7130 klass = mono_bounded_array_class_get (klass, modval, bounded);
7132 mono_class_init (klass);
7135 return &klass->byval_arg;
7139 * mono_reflection_get_type:
7140 * @image: a metadata context
7141 * @info: type description structure
7142 * @ignorecase: flag for case-insensitive string compares
7143 * @type_resolve: whenever type resolve was already tried
7145 * Build a MonoType from the type description in @info.
7150 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7151 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7155 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7157 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7161 g_assert (assembly->dynamic);
7163 /* Enumerate all modules */
7166 if (abuilder->modules) {
7167 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7168 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7169 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7175 if (!type && abuilder->loaded_modules) {
7176 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7177 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7178 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7188 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7191 MonoReflectionAssembly *assembly;
7195 if (image && image->dynamic)
7196 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7198 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7201 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7208 *type_resolve = TRUE;
7211 /* Reconstruct the type name */
7212 fullName = g_string_new ("");
7213 if (info->name_space && (info->name_space [0] != '\0'))
7214 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7216 g_string_printf (fullName, info->name);
7217 for (mod = info->nested; mod; mod = mod->next)
7218 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7220 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7222 if (assembly->assembly->dynamic)
7223 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7225 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7228 g_string_free (fullName, TRUE);
7233 mono_reflection_free_type_info (MonoTypeNameParse *info)
7235 g_list_free (info->modifiers);
7236 g_list_free (info->nested);
7238 if (info->type_arguments) {
7241 for (i = 0; i < info->type_arguments->len; i++) {
7242 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7244 mono_reflection_free_type_info (subinfo);
7245 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7249 g_ptr_array_free (info->type_arguments, TRUE);
7254 * mono_reflection_type_from_name:
7256 * @image: a metadata context (can be NULL).
7258 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7259 * it defaults to get the type from @image or, if @image is NULL or loading
7260 * from it fails, uses corlib.
7264 mono_reflection_type_from_name (char *name, MonoImage *image)
7266 MonoType *type = NULL;
7267 MonoTypeNameParse info;
7270 /* Make a copy since parse_type modifies its argument */
7271 tmp = g_strdup (name);
7273 /*g_print ("requested type %s\n", str);*/
7274 if (mono_reflection_parse_type (tmp, &info)) {
7275 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7279 mono_reflection_free_type_info (&info);
7284 * mono_reflection_get_token:
7286 * Return the metadata token of OBJ which should be an object
7287 * representing a metadata element.
7290 mono_reflection_get_token (MonoObject *obj)
7295 klass = obj->vtable->klass;
7297 if (strcmp (klass->name, "MethodBuilder") == 0) {
7298 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7300 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7301 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7302 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7304 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7305 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7306 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7308 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7309 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7310 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7311 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7312 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7313 } else if (strcmp (klass->name, "MonoType") == 0) {
7314 MonoReflectionType *tb = (MonoReflectionType *)obj;
7315 token = mono_class_from_mono_type (tb->type)->type_token;
7316 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7317 strcmp (klass->name, "MonoMethod") == 0 ||
7318 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7319 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7320 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7321 if (m->method->is_inflated) {
7322 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7323 return inflated->declaring->token;
7325 token = m->method->token;
7327 } else if (strcmp (klass->name, "MonoField") == 0) {
7328 MonoReflectionField *f = (MonoReflectionField*)obj;
7330 if (is_field_on_inst (f->field)) {
7331 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7332 int field_index = f->field - dgclass->fields;
7335 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7336 obj = dgclass->field_objects [field_index];
7337 return mono_reflection_get_token (obj);
7339 token = mono_class_get_field_token (f->field);
7340 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7341 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7343 token = mono_class_get_property_token (p->property);
7344 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7345 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7347 token = mono_class_get_event_token (p->event);
7348 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7349 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7351 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7352 } else if (strcmp (klass->name, "Module") == 0) {
7353 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7356 } else if (strcmp (klass->name, "Assembly") == 0) {
7357 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7359 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7360 MonoException *ex = mono_get_exception_not_implemented (msg);
7362 mono_raise_exception (ex);
7369 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7371 int slen, type = t->type;
7372 MonoClass *tklass = t->data.klass;
7378 case MONO_TYPE_BOOLEAN: {
7379 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7384 case MONO_TYPE_CHAR:
7386 case MONO_TYPE_I2: {
7387 guint16 *val = g_malloc (sizeof (guint16));
7392 #if SIZEOF_VOID_P == 4
7398 case MONO_TYPE_I4: {
7399 guint32 *val = g_malloc (sizeof (guint32));
7404 #if SIZEOF_VOID_P == 8
7405 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7409 case MONO_TYPE_I8: {
7410 guint64 *val = g_malloc (sizeof (guint64));
7415 case MONO_TYPE_R8: {
7416 double *val = g_malloc (sizeof (double));
7421 case MONO_TYPE_VALUETYPE:
7422 if (t->data.klass->enumtype) {
7423 type = mono_class_enum_basetype (t->data.klass)->type;
7426 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7429 case MONO_TYPE_STRING:
7430 if (*p == (char)0xFF) {
7434 slen = mono_metadata_decode_value (p, &p);
7436 return mono_string_new_len (mono_domain_get (), p, slen);
7437 case MONO_TYPE_CLASS: {
7440 if (*p == (char)0xFF) {
7445 slen = mono_metadata_decode_value (p, &p);
7446 n = g_memdup (p, slen + 1);
7448 t = mono_reflection_type_from_name (n, image);
7450 g_warning ("Cannot load type '%s'", n);
7454 return mono_type_get_object (mono_domain_get (), t);
7458 case MONO_TYPE_OBJECT: {
7461 MonoClass *subc = NULL;
7466 } else if (subt == 0x0E) {
7467 type = MONO_TYPE_STRING;
7469 } else if (subt == 0x1D) {
7470 MonoType simple_type = {{0}};
7475 /* See Partition II, Appendix B3 */
7476 etype = MONO_TYPE_OBJECT;
7477 type = MONO_TYPE_SZARRAY;
7478 simple_type.type = etype;
7479 tklass = mono_class_from_mono_type (&simple_type);
7481 } else if (subt == 0x55) {
7484 slen = mono_metadata_decode_value (p, &p);
7485 n = g_memdup (p, slen + 1);
7487 t = mono_reflection_type_from_name (n, image);
7489 g_error ("Cannot load type '%s'", n);
7492 subc = mono_class_from_mono_type (t);
7493 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7494 MonoType simple_type = {{0}};
7495 simple_type.type = subt;
7496 subc = mono_class_from_mono_type (&simple_type);
7498 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7500 val = load_cattr_value (image, &subc->byval_arg, p, end);
7501 obj = mono_object_new (mono_domain_get (), subc);
7502 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7506 case MONO_TYPE_SZARRAY: {
7508 guint32 i, alen, basetype;
7511 if (alen == 0xffffffff) {
7515 arr = mono_array_new (mono_domain_get(), tklass, alen);
7516 basetype = tklass->byval_arg.type;
7517 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7518 basetype = mono_class_enum_basetype (tklass)->type;
7523 case MONO_TYPE_BOOLEAN:
7524 for (i = 0; i < alen; i++) {
7525 MonoBoolean val = *p++;
7526 mono_array_set (arr, MonoBoolean, i, val);
7529 case MONO_TYPE_CHAR:
7532 for (i = 0; i < alen; i++) {
7533 guint16 val = read16 (p);
7534 mono_array_set (arr, guint16, i, val);
7541 for (i = 0; i < alen; i++) {
7542 guint32 val = read32 (p);
7543 mono_array_set (arr, guint32, i, val);
7548 for (i = 0; i < alen; i++) {
7551 mono_array_set (arr, double, i, val);
7557 for (i = 0; i < alen; i++) {
7558 guint64 val = read64 (p);
7559 mono_array_set (arr, guint64, i, val);
7563 case MONO_TYPE_CLASS:
7564 case MONO_TYPE_OBJECT:
7565 case MONO_TYPE_STRING:
7566 for (i = 0; i < alen; i++) {
7567 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7568 mono_array_setref (arr, i, item);
7572 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7578 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7584 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7586 static MonoClass *klass;
7587 static MonoMethod *ctor;
7589 void *params [2], *unboxed;
7592 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7594 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7596 params [0] = mono_type_get_object (mono_domain_get (), t);
7598 retval = mono_object_new (mono_domain_get (), klass);
7599 unboxed = mono_object_unbox (retval);
7600 mono_runtime_invoke (ctor, unboxed, params, NULL);
7606 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7608 static MonoClass *klass;
7609 static MonoMethod *ctor;
7611 void *unboxed, *params [2];
7614 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7616 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7619 params [1] = typedarg;
7620 retval = mono_object_new (mono_domain_get (), klass);
7621 unboxed = mono_object_unbox (retval);
7622 mono_runtime_invoke (ctor, unboxed, params, NULL);
7628 type_is_reference (MonoType *type)
7630 switch (type->type) {
7631 case MONO_TYPE_BOOLEAN:
7632 case MONO_TYPE_CHAR:
7645 case MONO_TYPE_VALUETYPE:
7653 free_param_data (MonoMethodSignature *sig, void **params) {
7655 for (i = 0; i < sig->param_count; ++i) {
7656 if (!type_is_reference (sig->params [i]))
7657 g_free (params [i]);
7662 * Find the field index in the metadata FieldDef table.
7665 find_field_index (MonoClass *klass, MonoClassField *field) {
7668 for (i = 0; i < klass->field.count; ++i) {
7669 if (field == &klass->fields [i])
7670 return klass->field.first + 1 + i;
7676 * Find the property index in the metadata Property table.
7679 find_property_index (MonoClass *klass, MonoProperty *property) {
7682 for (i = 0; i < klass->ext->property.count; ++i) {
7683 if (property == &klass->ext->properties [i])
7684 return klass->ext->property.first + 1 + i;
7690 * Find the event index in the metadata Event table.
7693 find_event_index (MonoClass *klass, MonoEvent *event) {
7696 for (i = 0; i < klass->ext->event.count; ++i) {
7697 if (event == &klass->ext->events [i])
7698 return klass->ext->event.first + 1 + i;
7704 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7706 const char *p = (const char*)data;
7708 guint32 i, j, num_named;
7712 mono_class_init (method->klass);
7715 attr = mono_object_new (mono_domain_get (), method->klass);
7716 mono_runtime_invoke (method, attr, NULL, NULL);
7720 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7723 /*g_print ("got attr %s\n", method->klass->name);*/
7725 /* Allocate using alloca so it gets GC tracking */
7726 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7730 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7731 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7735 attr = mono_object_new (mono_domain_get (), method->klass);
7736 mono_runtime_invoke (method, attr, params, NULL);
7737 free_param_data (method->signature, params);
7738 num_named = read16 (named);
7740 for (j = 0; j < num_named; j++) {
7742 char *name, named_type, data_type;
7743 named_type = *named++;
7744 data_type = *named++; /* type of data */
7745 if (data_type == MONO_TYPE_SZARRAY)
7746 data_type = *named++;
7747 if (data_type == MONO_TYPE_ENUM) {
7750 type_len = mono_metadata_decode_blob_size (named, &named);
7751 type_name = g_malloc (type_len + 1);
7752 memcpy (type_name, named, type_len);
7753 type_name [type_len] = 0;
7755 /* FIXME: lookup the type and check type consistency */
7758 name_len = mono_metadata_decode_blob_size (named, &named);
7759 name = g_malloc (name_len + 1);
7760 memcpy (name, named, name_len);
7761 name [name_len] = 0;
7763 if (named_type == 0x53) {
7764 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7765 void *val = load_cattr_value (image, field->type, named, &named);
7766 mono_field_set_value (attr, field, val);
7767 if (!type_is_reference (field->type))
7769 } else if (named_type == 0x54) {
7772 MonoType *prop_type;
7774 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7775 /* can we have more that 1 arg in a custom attr named property? */
7776 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7777 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7778 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7779 mono_property_set_value (prop, attr, pparams, NULL);
7780 if (!type_is_reference (prop_type))
7781 g_free (pparams [0]);
7790 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7792 MonoArray *typedargs, *namedargs;
7793 MonoClass *attrklass;
7794 static MonoMethod *ctor;
7797 const char *p = (const char*)data;
7799 guint32 i, j, num_named;
7802 mono_class_init (method->klass);
7805 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7807 domain = mono_domain_get ();
7809 /* This is for Attributes with no parameters */
7810 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7811 params [0] = mono_method_get_object (domain, method, NULL);
7812 params [1] = params [2] = NULL;
7813 mono_runtime_invoke (method, attr, params, NULL);
7817 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7820 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7824 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7825 MonoObject *obj, *typedarg;
7828 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7829 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7830 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7831 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7832 mono_array_setref (typedargs, i, typedarg);
7834 if (!type_is_reference (mono_method_signature (method)->params [i]))
7839 num_named = read16 (named);
7840 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7842 attrklass = method->klass;
7843 for (j = 0; j < num_named; j++) {
7845 char *name, named_type, data_type;
7846 named_type = *named++;
7847 data_type = *named++; /* type of data */
7848 if (data_type == MONO_TYPE_SZARRAY)
7849 data_type = *named++;
7850 if (data_type == MONO_TYPE_ENUM) {
7853 type_len = mono_metadata_decode_blob_size (named, &named);
7854 type_name = g_malloc (type_len + 1);
7855 memcpy (type_name, named, type_len);
7856 type_name [type_len] = 0;
7858 /* FIXME: lookup the type and check type consistency */
7861 name_len = mono_metadata_decode_blob_size (named, &named);
7862 name = g_malloc (name_len + 1);
7863 memcpy (name, named, name_len);
7864 name [name_len] = 0;
7866 if (named_type == 0x53) {
7867 MonoObject *obj, *typedarg, *namedarg;
7868 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7869 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7871 minfo = mono_field_get_object (domain, NULL, field);
7872 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7873 typedarg = create_cattr_typed_arg (field->type, obj);
7874 namedarg = create_cattr_named_arg (minfo, typedarg);
7875 mono_array_setref (namedargs, j, namedarg);
7876 if (!type_is_reference (field->type))
7878 } else if (named_type == 0x54) {
7879 MonoObject *obj, *typedarg, *namedarg;
7880 MonoType *prop_type;
7882 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7884 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7885 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7886 minfo = mono_property_get_object (domain, NULL, prop);
7887 val = load_cattr_value (image, prop_type, named, &named);
7888 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7889 typedarg = create_cattr_typed_arg (prop_type, obj);
7890 namedarg = create_cattr_named_arg (minfo, typedarg);
7891 mono_array_setref (namedargs, j, namedarg);
7892 if (!type_is_reference (prop_type))
7897 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7898 params [0] = mono_method_get_object (domain, method, NULL);
7899 params [1] = typedargs;
7900 params [2] = namedargs;
7901 mono_runtime_invoke (ctor, attr, params, NULL);
7906 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7912 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7913 for (i = 0; i < cinfo->num_attrs; ++i) {
7914 if (!cinfo->attrs [i].ctor)
7915 /* The cattr type is not finished yet */
7916 /* We should include the type name but cinfo doesn't contain it */
7917 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7918 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7919 mono_array_setref (result, i, attr);
7925 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7932 for (i = 0; i < cinfo->num_attrs; ++i) {
7933 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7937 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7939 for (i = 0; i < cinfo->num_attrs; ++i) {
7940 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7941 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7942 mono_array_setref (result, n, attr);
7950 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7956 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7957 for (i = 0; i < cinfo->num_attrs; ++i) {
7958 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7959 mono_array_setref (result, i, attr);
7965 * mono_custom_attrs_from_index:
7967 * Returns: NULL if no attributes are found or if a loading error occurs.
7970 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7972 guint32 mtoken, i, len;
7973 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7975 MonoCustomAttrInfo *ainfo;
7976 GList *tmp, *list = NULL;
7979 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7981 i = mono_metadata_custom_attrs_from_index (image, idx);
7985 while (i < ca->rows) {
7986 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7988 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7991 len = g_list_length (list);
7994 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7995 ainfo->num_attrs = len;
7996 ainfo->image = image;
7997 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7998 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7999 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8000 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8001 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8002 mtoken |= MONO_TOKEN_METHOD_DEF;
8004 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8005 mtoken |= MONO_TOKEN_MEMBER_REF;
8008 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8011 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8012 if (!ainfo->attrs [i].ctor) {
8013 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8018 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8019 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8020 ainfo->attrs [i].data = (guchar*)data;
8028 mono_custom_attrs_from_method (MonoMethod *method)
8033 * An instantiated method has the same cattrs as the generic method definition.
8035 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8036 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8038 if (method->is_inflated)
8039 method = ((MonoMethodInflated *) method)->declaring;
8041 if (method->dynamic || method->klass->image->dynamic)
8042 return lookup_custom_attr (method->klass->image, method);
8044 idx = mono_method_get_index (method);
8045 idx <<= MONO_CUSTOM_ATTR_BITS;
8046 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8047 return mono_custom_attrs_from_index (method->klass->image, idx);
8051 mono_custom_attrs_from_class (MonoClass *klass)
8055 if (klass->generic_class)
8056 klass = klass->generic_class->container_class;
8058 if (klass->image->dynamic)
8059 return lookup_custom_attr (klass->image, klass);
8061 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8062 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8063 idx <<= MONO_CUSTOM_ATTR_BITS;
8064 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8066 idx = mono_metadata_token_index (klass->type_token);
8067 idx <<= MONO_CUSTOM_ATTR_BITS;
8068 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8070 return mono_custom_attrs_from_index (klass->image, idx);
8074 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8078 if (assembly->image->dynamic)
8079 return lookup_custom_attr (assembly->image, assembly);
8080 idx = 1; /* there is only one assembly */
8081 idx <<= MONO_CUSTOM_ATTR_BITS;
8082 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8083 return mono_custom_attrs_from_index (assembly->image, idx);
8086 static MonoCustomAttrInfo*
8087 mono_custom_attrs_from_module (MonoImage *image)
8092 return lookup_custom_attr (image, image);
8093 idx = 1; /* there is only one module */
8094 idx <<= MONO_CUSTOM_ATTR_BITS;
8095 idx |= MONO_CUSTOM_ATTR_MODULE;
8096 return mono_custom_attrs_from_index (image, idx);
8100 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8104 if (klass->image->dynamic) {
8105 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8106 return lookup_custom_attr (klass->image, property);
8108 idx = find_property_index (klass, property);
8109 idx <<= MONO_CUSTOM_ATTR_BITS;
8110 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8111 return mono_custom_attrs_from_index (klass->image, idx);
8115 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8119 if (klass->image->dynamic) {
8120 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8121 return lookup_custom_attr (klass->image, event);
8123 idx = find_event_index (klass, event);
8124 idx <<= MONO_CUSTOM_ATTR_BITS;
8125 idx |= MONO_CUSTOM_ATTR_EVENT;
8126 return mono_custom_attrs_from_index (klass->image, idx);
8130 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8133 if (klass->image->dynamic) {
8134 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8135 return lookup_custom_attr (klass->image, field);
8137 idx = find_field_index (klass, field);
8138 idx <<= MONO_CUSTOM_ATTR_BITS;
8139 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8140 return mono_custom_attrs_from_index (klass->image, idx);
8144 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8147 guint32 i, idx, method_index;
8148 guint32 param_list, param_last, param_pos, found;
8150 MonoReflectionMethodAux *aux;
8153 * An instantiated method has the same cattrs as the generic method definition.
8155 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8156 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8158 if (method->is_inflated)
8159 method = ((MonoMethodInflated *) method)->declaring;
8161 if (method->klass->image->dynamic) {
8162 MonoCustomAttrInfo *res, *ainfo;
8165 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8166 if (!aux || !aux->param_cattr)
8169 /* Need to copy since it will be freed later */
8170 ainfo = aux->param_cattr [param];
8171 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8172 res = g_malloc0 (size);
8173 memcpy (res, ainfo, size);
8177 image = method->klass->image;
8178 method_index = mono_method_get_index (method);
8179 ca = &image->tables [MONO_TABLE_METHOD];
8181 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8182 if (method_index == ca->rows) {
8183 ca = &image->tables [MONO_TABLE_PARAM];
8184 param_last = ca->rows + 1;
8186 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8187 ca = &image->tables [MONO_TABLE_PARAM];
8190 for (i = param_list; i < param_last; ++i) {
8191 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8192 if (param_pos == param) {
8200 idx <<= MONO_CUSTOM_ATTR_BITS;
8201 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8202 return mono_custom_attrs_from_index (image, idx);
8206 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8210 for (i = 0; i < ainfo->num_attrs; ++i) {
8211 klass = ainfo->attrs [i].ctor->klass;
8212 if (mono_class_has_parent (klass, attr_klass))
8219 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8226 for (i = 0; i < ainfo->num_attrs; ++i) {
8227 klass = ainfo->attrs [i].ctor->klass;
8228 if (mono_class_has_parent (klass, attr_klass)) {
8233 if (attr_index == -1)
8236 attrs = mono_custom_attrs_construct (ainfo);
8238 return mono_array_get (attrs, MonoObject*, attr_index);
8244 * mono_reflection_get_custom_attrs_info:
8245 * @obj: a reflection object handle
8247 * Return the custom attribute info for attributes defined for the
8248 * reflection handle @obj. The objects.
8250 * FIXME this function leaks like a sieve for SRE objects.
8253 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8256 MonoCustomAttrInfo *cinfo = NULL;
8258 klass = obj->vtable->klass;
8259 if (klass == mono_defaults.monotype_class) {
8260 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8261 klass = mono_class_from_mono_type (rtype->type);
8262 cinfo = mono_custom_attrs_from_class (klass);
8263 } else if (strcmp ("Assembly", klass->name) == 0) {
8264 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8265 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8266 } else if (strcmp ("Module", klass->name) == 0) {
8267 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8268 cinfo = mono_custom_attrs_from_module (module->image);
8269 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8270 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8271 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8272 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8273 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8274 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8275 } else if (strcmp ("MonoField", klass->name) == 0) {
8276 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8277 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8278 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8279 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8280 cinfo = mono_custom_attrs_from_method (rmethod->method);
8281 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8282 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8283 cinfo = mono_custom_attrs_from_method (rmethod->method);
8284 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8285 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8286 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8287 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8288 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8289 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8290 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8291 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8292 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8293 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8294 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8295 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8296 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8297 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8298 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8299 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8300 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8301 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8302 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8303 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8304 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8305 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8306 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8307 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8308 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8309 } else { /* handle other types here... */
8310 g_error ("get custom attrs not yet supported for %s", klass->name);
8317 * mono_reflection_get_custom_attrs_by_type:
8318 * @obj: a reflection object handle
8320 * Return an array with all the custom attributes defined of the
8321 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8322 * of that type are returned. The objects are fully build. Return NULL if a loading error
8326 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8329 MonoCustomAttrInfo *cinfo;
8331 cinfo = mono_reflection_get_custom_attrs_info (obj);
8334 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8336 result = mono_custom_attrs_construct (cinfo);
8338 mono_custom_attrs_free (cinfo);
8340 if (mono_loader_get_last_error ())
8342 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8349 * mono_reflection_get_custom_attrs:
8350 * @obj: a reflection object handle
8352 * Return an array with all the custom attributes defined of the
8353 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8357 mono_reflection_get_custom_attrs (MonoObject *obj)
8359 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8363 * mono_reflection_get_custom_attrs_data:
8364 * @obj: a reflection obj handle
8366 * Returns an array of System.Reflection.CustomAttributeData,
8367 * which include information about attributes reflected on
8368 * types loaded using the Reflection Only methods
8371 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8374 MonoCustomAttrInfo *cinfo;
8376 cinfo = mono_reflection_get_custom_attrs_info (obj);
8378 result = mono_custom_attrs_data_construct (cinfo);
8380 mono_custom_attrs_free (cinfo);
8382 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8387 static MonoReflectionType*
8388 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8390 MonoMethod *method_get_underlying_system_type;
8392 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8393 mono_class_get_method_from_name (mono_object_class (t),
8394 "get_UnderlyingSystemType",
8396 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8400 mono_reflection_type_get_handle (MonoReflectionType* t)
8405 t = mono_reflection_type_get_underlying_system_type (t);
8413 * LOCKING: Assumes the loader lock is held.
8415 static MonoMethodSignature*
8416 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8417 MonoMethodSignature *sig;
8420 count = parameters? mono_array_length (parameters): 0;
8422 sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8423 sig->param_count = count;
8424 sig->sentinelpos = -1; /* FIXME */
8425 for (i = 0; i < count; ++i) {
8426 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8427 sig->params [i] = mono_reflection_type_get_handle (pt);
8433 * LOCKING: Assumes the loader lock is held.
8435 static MonoMethodSignature*
8436 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8437 MonoMethodSignature *sig;
8439 sig = parameters_to_signature (image, ctor->parameters);
8440 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8441 sig->ret = &mono_defaults.void_class->byval_arg;
8446 * LOCKING: Assumes the loader lock is held.
8448 static MonoMethodSignature*
8449 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8450 MonoMethodSignature *sig;
8452 sig = parameters_to_signature (image, method->parameters);
8453 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8454 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8455 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8459 static MonoMethodSignature*
8460 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8461 MonoMethodSignature *sig;
8463 sig = parameters_to_signature (NULL, method->parameters);
8464 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8465 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8466 sig->generic_param_count = 0;
8471 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8473 MonoClass *klass = mono_object_class (prop);
8474 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8475 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8476 *name = mono_string_to_utf8 (pb->name);
8477 *type = pb->type->type;
8479 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8480 *name = g_strdup (p->property->name);
8481 if (p->property->get)
8482 *type = mono_method_signature (p->property->get)->ret;
8484 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8489 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8491 MonoClass *klass = mono_object_class (field);
8492 if (strcmp (klass->name, "FieldBuilder") == 0) {
8493 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8494 *name = mono_string_to_utf8 (fb->name);
8495 *type = fb->type->type;
8497 MonoReflectionField *f = (MonoReflectionField *)field;
8498 *name = g_strdup (mono_field_get_name (f->field));
8499 *type = f->field->type;
8504 * Encode a value in a custom attribute stream of bytes.
8505 * The value to encode is either supplied as an object in argument val
8506 * (valuetypes are boxed), or as a pointer to the data in the
8508 * @type represents the type of the value
8509 * @buffer is the start of the buffer
8510 * @p the current position in the buffer
8511 * @buflen contains the size of the buffer and is used to return the new buffer size
8512 * if this needs to be realloced.
8513 * @retbuffer and @retp return the start and the position of the buffer
8516 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8518 MonoTypeEnum simple_type;
8520 if ((p-buffer) + 10 >= *buflen) {
8523 newbuf = g_realloc (buffer, *buflen);
8524 p = newbuf + (p-buffer);
8528 argval = ((char*)arg + sizeof (MonoObject));
8529 simple_type = type->type;
8531 switch (simple_type) {
8532 case MONO_TYPE_BOOLEAN:
8537 case MONO_TYPE_CHAR:
8540 swap_with_size (p, argval, 2, 1);
8546 swap_with_size (p, argval, 4, 1);
8550 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8560 swap_with_size (p, argval, 8, 1);
8566 swap_with_size (p, argval, 8, 1);
8569 case MONO_TYPE_VALUETYPE:
8570 if (type->data.klass->enumtype) {
8571 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8574 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8577 case MONO_TYPE_STRING: {
8584 str = mono_string_to_utf8 ((MonoString*)arg);
8585 slen = strlen (str);
8586 if ((p-buffer) + 10 + slen >= *buflen) {
8590 newbuf = g_realloc (buffer, *buflen);
8591 p = newbuf + (p-buffer);
8594 mono_metadata_encode_value (slen, p, &p);
8595 memcpy (p, str, slen);
8600 case MONO_TYPE_CLASS: {
8608 k = mono_object_class (arg);
8609 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8610 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8611 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8614 if (rt && (rtc = mono_object_class (rt)) &&
8615 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8616 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8617 arg = (MonoObject *) rt;
8620 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8623 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8624 slen = strlen (str);
8625 if ((p-buffer) + 10 + slen >= *buflen) {
8629 newbuf = g_realloc (buffer, *buflen);
8630 p = newbuf + (p-buffer);
8633 mono_metadata_encode_value (slen, p, &p);
8634 memcpy (p, str, slen);
8639 case MONO_TYPE_SZARRAY: {
8641 MonoClass *eclass, *arg_eclass;
8644 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8647 len = mono_array_length ((MonoArray*)arg);
8649 *p++ = (len >> 8) & 0xff;
8650 *p++ = (len >> 16) & 0xff;
8651 *p++ = (len >> 24) & 0xff;
8653 *retbuffer = buffer;
8654 eclass = type->data.klass;
8655 arg_eclass = mono_object_class (arg)->element_class;
8658 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8659 eclass = mono_defaults.object_class;
8661 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8662 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8663 int elsize = mono_class_array_element_size (arg_eclass);
8664 for (i = 0; i < len; ++i) {
8665 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8668 } else if (eclass->valuetype && arg_eclass->valuetype) {
8669 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8670 int elsize = mono_class_array_element_size (eclass);
8671 for (i = 0; i < len; ++i) {
8672 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8676 for (i = 0; i < len; ++i) {
8677 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8682 case MONO_TYPE_OBJECT: {
8688 * The parameter type is 'object' but the type of the actual
8689 * argument is not. So we have to add type information to the blob
8690 * too. This is completely undocumented in the spec.
8694 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8699 klass = mono_object_class (arg);
8701 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8704 } else if (klass->enumtype) {
8706 } else if (klass == mono_defaults.string_class) {
8707 simple_type = MONO_TYPE_STRING;
8710 } else if (klass->rank == 1) {
8712 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8713 /* See Partition II, Appendix B3 */
8716 *p++ = klass->element_class->byval_arg.type;
8717 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8719 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8720 *p++ = simple_type = klass->byval_arg.type;
8723 g_error ("unhandled type in custom attr");
8725 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8726 slen = strlen (str);
8727 if ((p-buffer) + 10 + slen >= *buflen) {
8731 newbuf = g_realloc (buffer, *buflen);
8732 p = newbuf + (p-buffer);
8735 mono_metadata_encode_value (slen, p, &p);
8736 memcpy (p, str, slen);
8739 simple_type = mono_class_enum_basetype (klass)->type;
8743 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8746 *retbuffer = buffer;
8750 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8752 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8753 char *str = type_get_qualified_name (type, NULL);
8754 int slen = strlen (str);
8758 * This seems to be optional...
8761 mono_metadata_encode_value (slen, p, &p);
8762 memcpy (p, str, slen);
8765 } else if (type->type == MONO_TYPE_OBJECT) {
8767 } else if (type->type == MONO_TYPE_CLASS) {
8768 /* it should be a type: encode_cattr_value () has the check */
8771 mono_metadata_encode_value (type->type, p, &p);
8772 if (type->type == MONO_TYPE_SZARRAY)
8773 /* See the examples in Partition VI, Annex B */
8774 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8781 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8784 /* Preallocate a large enough buffer */
8785 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8786 char *str = type_get_qualified_name (type, NULL);
8789 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8790 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8796 len += strlen (name);
8798 if ((p-buffer) + 20 + len >= *buflen) {
8802 newbuf = g_realloc (buffer, *buflen);
8803 p = newbuf + (p-buffer);
8807 encode_field_or_prop_type (type, p, &p);
8809 len = strlen (name);
8810 mono_metadata_encode_value (len, p, &p);
8811 memcpy (p, name, len);
8813 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8815 *retbuffer = buffer;
8818 #ifndef DISABLE_REFLECTION_EMIT
8821 * mono_reflection_get_custom_attrs_blob:
8822 * @ctor: custom attribute constructor
8823 * @ctorArgs: arguments o the constructor
8829 * Creates the blob of data that needs to be saved in the metadata and that represents
8830 * the custom attributed described by @ctor, @ctorArgs etc.
8831 * Returns: a Byte array representing the blob of data.
8834 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8837 MonoMethodSignature *sig;
8842 MONO_ARCH_SAVE_REGS;
8844 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8845 /* sig is freed later so allocate it in the heap */
8846 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8848 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8851 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8853 p = buffer = g_malloc (buflen);
8854 /* write the prolog */
8857 for (i = 0; i < sig->param_count; ++i) {
8858 arg = mono_array_get (ctorArgs, MonoObject*, i);
8859 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8863 i += mono_array_length (properties);
8865 i += mono_array_length (fields);
8867 *p++ = (i >> 8) & 0xff;
8870 for (i = 0; i < mono_array_length (properties); ++i) {
8874 prop = mono_array_get (properties, gpointer, i);
8875 get_prop_name_and_type (prop, &pname, &ptype);
8876 *p++ = 0x54; /* PROPERTY signature */
8877 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8884 for (i = 0; i < mono_array_length (fields); ++i) {
8888 field = mono_array_get (fields, gpointer, i);
8889 get_field_name_and_type (field, &fname, &ftype);
8890 *p++ = 0x53; /* FIELD signature */
8891 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8896 g_assert (p - buffer <= buflen);
8897 buflen = p - buffer;
8898 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8899 p = mono_array_addr (result, char, 0);
8900 memcpy (p, buffer, buflen);
8902 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8908 * mono_reflection_setup_internal_class:
8909 * @tb: a TypeBuilder object
8911 * Creates a MonoClass that represents the TypeBuilder.
8912 * This is a trick that lets us simplify a lot of reflection code
8913 * (and will allow us to support Build and Run assemblies easier).
8916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8918 MonoClass *klass, *parent;
8920 MONO_ARCH_SAVE_REGS;
8922 mono_loader_lock ();
8925 /* check so we can compile corlib correctly */
8926 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8927 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8928 parent = tb->parent->type->data.klass;
8930 parent = my_mono_class_from_mono_type (tb->parent->type);
8936 /* the type has already being created: it means we just have to change the parent */
8937 if (tb->type.type) {
8938 klass = mono_class_from_mono_type (tb->type.type);
8939 klass->parent = NULL;
8940 /* fool mono_class_setup_parent */
8941 klass->supertypes = NULL;
8942 mono_class_setup_parent (klass, parent);
8943 mono_class_setup_mono_type (klass);
8944 mono_loader_unlock ();
8948 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8950 klass->image = &tb->module->dynamic_image->image;
8952 klass->inited = 1; /* we lie to the runtime */
8953 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8954 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8955 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8956 klass->flags = tb->attrs;
8958 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8960 klass->element_class = klass;
8962 MOVING_GC_REGISTER (&klass->reflection_info);
8963 klass->reflection_info = tb;
8965 /* Put into cache so mono_class_get () will find it */
8966 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8968 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8969 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8971 if (parent != NULL) {
8972 mono_class_setup_parent (klass, parent);
8973 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8974 const char *old_n = klass->name;
8975 /* trick to get relative numbering right when compiling corlib */
8976 klass->name = "BuildingObject";
8977 mono_class_setup_parent (klass, mono_defaults.object_class);
8978 klass->name = old_n;
8981 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8982 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8983 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8984 klass->instance_size = sizeof (MonoObject);
8985 klass->size_inited = 1;
8986 mono_class_setup_vtable_general (klass, NULL, 0);
8989 mono_class_setup_mono_type (klass);
8991 mono_class_setup_supertypes (klass);
8994 * FIXME: handle interfaces.
8997 tb->type.type = &klass->byval_arg;
8999 if (tb->nesting_type) {
9000 g_assert (tb->nesting_type->type);
9001 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9004 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9006 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9008 mono_loader_unlock ();
9012 * mono_reflection_setup_generic_class:
9013 * @tb: a TypeBuilder object
9015 * Setup the generic class before adding the first generic parameter.
9018 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9023 * mono_reflection_create_generic_class:
9024 * @tb: a TypeBuilder object
9026 * Creates the generic class after all generic parameters have been added.
9029 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9034 MONO_ARCH_SAVE_REGS;
9036 klass = my_mono_class_from_mono_type (tb->type.type);
9038 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9040 if (klass->generic_container || (count == 0))
9043 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9045 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9047 klass->generic_container->owner.klass = klass;
9048 klass->generic_container->type_argc = count;
9049 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9051 klass->is_generic = 1;
9053 for (i = 0; i < count; i++) {
9054 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9055 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9056 /*Make sure we are a diferent type instance */
9057 klass->generic_container->type_params [i].owner = klass->generic_container;
9058 klass->generic_container->type_params [i].pklass = NULL;
9060 g_assert (klass->generic_container->type_params [i].owner);
9063 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9067 * mono_reflection_create_internal_class:
9068 * @tb: a TypeBuilder object
9070 * Actually create the MonoClass that is associated with the TypeBuilder.
9073 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9077 MONO_ARCH_SAVE_REGS;
9079 klass = my_mono_class_from_mono_type (tb->type.type);
9081 mono_loader_lock ();
9082 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9083 MonoReflectionFieldBuilder *fb;
9085 MonoType *enum_basetype;
9087 g_assert (tb->fields != NULL);
9088 g_assert (mono_array_length (tb->fields) >= 1);
9090 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9092 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9093 mono_loader_unlock ();
9097 enum_basetype = fb->type->type;
9098 klass->element_class = my_mono_class_from_mono_type (enum_basetype);
9099 if (!klass->element_class)
9100 klass->element_class = mono_class_from_mono_type (enum_basetype);
9103 * get the element_class from the current corlib.
9105 ec = default_class_from_mono_type (enum_basetype);
9106 klass->instance_size = ec->instance_size;
9107 klass->size_inited = 1;
9109 * this is almost safe to do with enums and it's needed to be able
9110 * to create objects of the enum type (for use in SetConstant).
9112 /* FIXME: Does this mean enums can't have method overrides ? */
9113 mono_class_setup_vtable_general (klass, NULL, 0);
9115 mono_loader_unlock ();
9118 #endif /* DISABLE_REFLECTION_EMIT */
9120 static MonoMarshalSpec*
9121 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9122 MonoReflectionMarshal *minfo)
9124 MonoMarshalSpec *res;
9126 res = image_g_new0 (image, MonoMarshalSpec, 1);
9127 res->native = minfo->type;
9129 switch (minfo->type) {
9130 case MONO_NATIVE_LPARRAY:
9131 res->data.array_data.elem_type = minfo->eltype;
9132 if (minfo->has_size) {
9133 res->data.array_data.param_num = minfo->param_num;
9134 res->data.array_data.num_elem = minfo->count;
9135 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9138 res->data.array_data.param_num = -1;
9139 res->data.array_data.num_elem = -1;
9140 res->data.array_data.elem_mult = -1;
9144 case MONO_NATIVE_BYVALTSTR:
9145 case MONO_NATIVE_BYVALARRAY:
9146 res->data.array_data.num_elem = minfo->count;
9149 case MONO_NATIVE_CUSTOM:
9150 if (minfo->marshaltyperef)
9151 res->data.custom_data.custom_name =
9152 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9154 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9164 MonoReflectionMarshal*
9165 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9166 MonoMarshalSpec *spec)
9168 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9169 MonoReflectionMarshal *minfo;
9172 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9173 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9174 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9175 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9178 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9179 minfo->type = spec->native;
9181 switch (minfo->type) {
9182 case MONO_NATIVE_LPARRAY:
9183 minfo->eltype = spec->data.array_data.elem_type;
9184 minfo->count = spec->data.array_data.num_elem;
9185 minfo->param_num = spec->data.array_data.param_num;
9188 case MONO_NATIVE_BYVALTSTR:
9189 case MONO_NATIVE_BYVALARRAY:
9190 minfo->count = spec->data.array_data.num_elem;
9193 case MONO_NATIVE_CUSTOM:
9194 if (spec->data.custom_data.custom_name) {
9195 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9197 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9199 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9201 if (spec->data.custom_data.cookie)
9202 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9213 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9214 ReflectionMethodBuilder *rmb,
9215 MonoMethodSignature *sig)
9218 MonoMethodNormal *pm;
9219 MonoMarshalSpec **specs;
9220 MonoReflectionMethodAux *method_aux;
9226 * Methods created using a MethodBuilder should have their memory allocated
9227 * inside the image mempool, while dynamic methods should have their memory
9230 dynamic = rmb->refs != NULL;
9231 image = dynamic ? NULL : klass->image;
9234 g_assert (!klass->generic_class);
9236 mono_loader_lock ();
9238 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9239 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9240 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9242 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9244 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9246 pm = (MonoMethodNormal*)m;
9248 m->dynamic = dynamic;
9250 m->flags = rmb->attrs;
9251 m->iflags = rmb->iattrs;
9252 m->name = mono_string_to_utf8_image (image, rmb->name);
9255 m->skip_visibility = rmb->skip_visibility;
9257 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9259 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9260 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9263 m->signature->pinvoke = 1;
9264 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9265 m->signature->pinvoke = 1;
9267 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9269 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9270 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9272 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9274 if (klass->image->dynamic)
9275 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9277 mono_loader_unlock ();
9280 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9281 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9282 MonoMethodHeader *header;
9284 gint32 max_stack, i;
9285 gint32 num_locals = 0;
9286 gint32 num_clauses = 0;
9290 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9291 code_size = rmb->ilgen->code_len;
9292 max_stack = rmb->ilgen->max_stack;
9293 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9294 if (rmb->ilgen->ex_handlers)
9295 num_clauses = method_count_clauses (rmb->ilgen);
9298 code = mono_array_addr (rmb->code, guint8, 0);
9299 code_size = mono_array_length (rmb->code);
9300 /* we probably need to run a verifier on the code... */
9310 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
9311 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9312 header->code_size = code_size;
9313 header->code = image_g_malloc (image, code_size);
9314 memcpy ((char*)header->code, code, code_size);
9315 header->max_stack = max_stack;
9316 header->init_locals = rmb->init_locals;
9317 header->num_locals = num_locals;
9319 for (i = 0; i < num_locals; ++i) {
9320 MonoReflectionLocalBuilder *lb =
9321 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9323 header->locals [i] = image_g_new0 (image, MonoType, 1);
9324 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9327 header->num_clauses = num_clauses;
9329 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9330 rmb->ilgen, num_clauses);
9333 pm->header = header;
9336 if (rmb->generic_params) {
9337 int count = mono_array_length (rmb->generic_params);
9338 MonoGenericContainer *container;
9340 container = rmb->generic_container;
9342 m->is_generic = TRUE;
9343 mono_method_set_generic_container (m, container);
9345 container->type_argc = count;
9346 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9347 container->owner.method = m;
9349 for (i = 0; i < count; i++) {
9350 MonoReflectionGenericParam *gp =
9351 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9353 container->type_params [i] = *gp->type.type->data.generic_param;
9356 if (klass->generic_container) {
9357 container->parent = klass->generic_container;
9358 container->context.class_inst = klass->generic_container->context.class_inst;
9360 container->context.method_inst = mono_get_shared_generic_inst (container);
9364 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9368 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9370 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9371 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9372 for (i = 0; i < rmb->nrefs; ++i)
9373 data [i + 1] = rmb->refs [i];
9378 /* Parameter info */
9381 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9382 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9383 for (i = 0; i <= m->signature->param_count; ++i) {
9384 MonoReflectionParamBuilder *pb;
9385 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9386 if ((i > 0) && (pb->attrs)) {
9387 /* Make a copy since it might point to a shared type structure */
9388 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9389 m->signature->params [i - 1]->attrs = pb->attrs;
9392 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9393 MonoDynamicImage *assembly;
9394 guint32 idx, def_type, len;
9398 if (!method_aux->param_defaults) {
9399 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9400 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9402 assembly = (MonoDynamicImage*)klass->image;
9403 idx = encode_constant (assembly, pb->def_value, &def_type);
9404 /* Copy the data from the blob since it might get realloc-ed */
9405 p = assembly->blob.data + idx;
9406 len = mono_metadata_decode_blob_size (p, &p2);
9408 method_aux->param_defaults [i] = image_g_malloc (image, len);
9409 method_aux->param_default_types [i] = def_type;
9410 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9414 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9416 if (!method_aux->param_cattr)
9417 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9418 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9424 /* Parameter marshalling */
9427 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9428 MonoReflectionParamBuilder *pb;
9429 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9430 if (pb->marshal_info) {
9432 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9433 specs [pb->position] =
9434 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9438 if (specs != NULL) {
9440 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9441 method_aux->param_marshall = specs;
9444 if (klass->image->dynamic && method_aux)
9445 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9447 mono_loader_unlock ();
9453 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9455 ReflectionMethodBuilder rmb;
9456 MonoMethodSignature *sig;
9458 mono_loader_lock ();
9459 sig = ctor_builder_to_signature (klass->image, mb);
9460 mono_loader_unlock ();
9462 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9464 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9465 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9467 /* If we are in a generic class, we might be called multiple times from inflate_method */
9468 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9469 /* ilgen is no longer needed */
9477 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9479 ReflectionMethodBuilder rmb;
9480 MonoMethodSignature *sig;
9482 mono_loader_lock ();
9483 sig = method_builder_to_signature (klass->image, mb);
9484 mono_loader_unlock ();
9486 reflection_methodbuilder_from_method_builder (&rmb, mb);
9488 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9489 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9491 /* If we are in a generic class, we might be called multiple times from inflate_method */
9492 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9493 /* ilgen is no longer needed */
9499 static MonoClassField*
9500 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9502 MonoClassField *field;
9505 field = g_new0 (MonoClassField, 1);
9507 field->name = mono_string_to_utf8 (fb->name);
9508 if (fb->attrs || fb->modreq || fb->modopt) {
9509 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9510 field->type->attrs = fb->attrs;
9512 g_assert (klass->image->dynamic);
9513 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9514 g_free (field->type);
9515 field->type = custom;
9517 field->type = fb->type->type;
9519 if (fb->offset != -1)
9520 field->offset = fb->offset;
9521 field->parent = klass;
9522 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9524 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9530 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9533 MonoReflectionTypeBuilder *tb = NULL;
9534 gboolean is_dynamic = FALSE;
9538 mono_loader_lock ();
9540 domain = mono_object_domain (type);
9542 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9543 tb = (MonoReflectionTypeBuilder *) type;
9546 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9547 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9549 tb = rgi->generic_type;
9553 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9554 if (tb && tb->generic_container)
9555 mono_reflection_create_generic_class (tb);
9557 klass = mono_class_from_mono_type (type->type);
9558 if (!klass->generic_container) {
9559 mono_loader_unlock ();
9563 if (klass->wastypebuilder) {
9564 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9569 mono_loader_unlock ();
9571 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9573 return &geninst->byval_arg;
9577 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9579 MonoGenericClass *gclass;
9580 MonoGenericInst *inst;
9582 g_assert (klass->generic_container);
9584 inst = mono_metadata_get_generic_inst (type_argc, types);
9585 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9587 return mono_generic_class_get_class (gclass);
9590 MonoReflectionMethod*
9591 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9594 MonoMethod *method, *inflated;
9595 MonoMethodInflated *imethod;
9596 MonoReflectionMethodBuilder *mb = NULL;
9597 MonoGenericContext tmp_context;
9598 MonoGenericInst *ginst;
9599 MonoType **type_argv;
9602 MONO_ARCH_SAVE_REGS;
9604 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9605 #ifndef DISABLE_REFLECTION_EMIT
9606 MonoReflectionTypeBuilder *tb;
9609 mb = (MonoReflectionMethodBuilder *) rmethod;
9610 tb = (MonoReflectionTypeBuilder *) mb->type;
9611 klass = mono_class_from_mono_type (tb->type.type);
9613 method = methodbuilder_to_mono_method (klass, mb);
9615 g_assert_not_reached ();
9619 method = rmethod->method;
9622 klass = method->klass;
9624 if (method->is_inflated)
9625 method = ((MonoMethodInflated *) method)->declaring;
9627 count = mono_method_signature (method)->generic_param_count;
9628 if (count != mono_array_length (types))
9631 type_argv = g_new0 (MonoType *, count);
9632 for (i = 0; i < count; i++) {
9633 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9634 type_argv [i] = garg->type;
9636 ginst = mono_metadata_get_generic_inst (count, type_argv);
9639 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9640 tmp_context.method_inst = ginst;
9642 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9643 imethod = (MonoMethodInflated *) inflated;
9645 if (method->klass->image->dynamic) {
9646 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9648 * This table maps metadata structures representing inflated methods/fields
9649 * to the reflection objects representing their generic definitions.
9651 mono_loader_lock ();
9652 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9653 mono_loader_unlock ();
9656 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9659 #ifndef DISABLE_REFLECTION_EMIT
9662 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9664 MonoMethodInflated *imethod;
9665 MonoGenericContext *context;
9669 * With generic code sharing the klass might not be inflated.
9670 * This can happen because classes inflated with their own
9671 * type arguments are "normalized" to the uninflated class.
9673 if (!klass->generic_class)
9676 context = mono_class_get_context (klass);
9678 if (klass->method.count) {
9679 /* Find the already created inflated method */
9680 for (i = 0; i < klass->method.count; ++i) {
9681 g_assert (klass->methods [i]->is_inflated);
9682 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9685 g_assert (i < klass->method.count);
9686 imethod = (MonoMethodInflated*)klass->methods [i];
9688 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9691 if (method->is_generic && method->klass->image->dynamic) {
9692 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9694 mono_loader_lock ();
9695 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9696 mono_loader_unlock ();
9698 return (MonoMethod *) imethod;
9702 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9707 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9709 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9710 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9711 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9713 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9714 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9715 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9716 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9717 method = ((MonoReflectionMethod *) obj)->method;
9719 method = NULL; /* prevent compiler warning */
9720 g_assert_not_reached ();
9723 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9726 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9728 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9729 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9732 MonoGenericClass *gclass;
9733 MonoDynamicGenericClass *dgclass;
9734 MonoClass *klass, *gklass;
9737 MONO_ARCH_SAVE_REGS;
9739 klass = mono_class_from_mono_type (type->type.type);
9740 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9741 gclass = type->type.type->data.generic_class;
9743 g_assert (gclass->is_dynamic);
9744 dgclass = (MonoDynamicGenericClass *) gclass;
9746 if (dgclass->initialized)
9749 gklass = gclass->container_class;
9750 mono_class_init (gklass);
9752 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9753 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9754 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9755 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9756 dgclass->count_events = events ? mono_array_length (events) : 0;
9758 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9759 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9760 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9761 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9762 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9763 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9764 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9766 for (i = 0; i < dgclass->count_methods; i++) {
9767 MonoObject *obj = mono_array_get (methods, gpointer, i);
9769 dgclass->methods [i] = inflate_method (type, obj);
9772 for (i = 0; i < dgclass->count_ctors; i++) {
9773 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9775 dgclass->ctors [i] = inflate_method (type, obj);
9778 for (i = 0; i < dgclass->count_fields; i++) {
9779 MonoObject *obj = mono_array_get (fields, gpointer, i);
9780 MonoClassField *field, *inflated_field = NULL;
9782 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9783 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9784 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9785 field = ((MonoReflectionField *) obj)->field;
9787 field = NULL; /* prevent compiler warning */
9788 g_assert_not_reached ();
9791 dgclass->fields [i] = *field;
9792 dgclass->fields [i].parent = klass;
9793 dgclass->fields [i].type = mono_class_inflate_generic_type (
9794 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9795 dgclass->field_generic_types [i] = field->type;
9796 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9797 dgclass->field_objects [i] = obj;
9799 if (inflated_field) {
9800 g_free (inflated_field);
9802 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9806 for (i = 0; i < dgclass->count_properties; i++) {
9807 MonoObject *obj = mono_array_get (properties, gpointer, i);
9808 MonoProperty *property = &dgclass->properties [i];
9810 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9811 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9813 property->parent = klass;
9814 property->attrs = pb->attrs;
9815 property->name = mono_string_to_utf8 (pb->name);
9817 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9819 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9820 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9821 *property = *((MonoReflectionProperty *) obj)->property;
9822 property->name = g_strdup (property->name);
9825 property->get = inflate_mono_method (klass, property->get, NULL);
9827 property->set = inflate_mono_method (klass, property->set, NULL);
9829 g_assert_not_reached ();
9832 for (i = 0; i < dgclass->count_events; i++) {
9833 MonoObject *obj = mono_array_get (events, gpointer, i);
9834 MonoEvent *event = &dgclass->events [i];
9836 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9837 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9839 event->parent = klass;
9840 event->attrs = eb->attrs;
9841 event->name = mono_string_to_utf8 (eb->name);
9843 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9844 if (eb->remove_method)
9845 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9846 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9847 *event = *((MonoReflectionEvent *) obj)->event;
9848 event->name = g_strdup (event->name);
9851 event->add = inflate_mono_method (klass, event->add, NULL);
9853 event->remove = inflate_mono_method (klass, event->remove, NULL);
9855 g_assert_not_reached ();
9858 dgclass->initialized = TRUE;
9862 ensure_generic_class_runtime_vtable (MonoClass *klass)
9864 MonoClass *gklass = klass->generic_class->container_class;
9867 if (klass->wastypebuilder)
9870 ensure_runtime_vtable (gklass);
9872 klass->method.count = gklass->method.count;
9873 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9875 for (i = 0; i < klass->method.count; i++) {
9876 klass->methods [i] = mono_class_inflate_generic_method_full (
9877 gklass->methods [i], klass, mono_class_get_context (klass));
9880 klass->interface_count = gklass->interface_count;
9881 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9882 for (i = 0; i < klass->interface_count; ++i) {
9883 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9884 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9885 mono_metadata_free_type (iface_type);
9887 ensure_runtime_vtable (klass->interfaces [i]);
9889 klass->interfaces_inited = 1;
9891 /*We can only finish with this klass once it's parent has as well*/
9892 if (gklass->wastypebuilder)
9893 klass->wastypebuilder = TRUE;
9898 ensure_runtime_vtable (MonoClass *klass)
9900 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9903 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9906 ensure_runtime_vtable (klass->parent);
9909 num = tb->ctors? mono_array_length (tb->ctors): 0;
9910 num += tb->num_methods;
9911 klass->method.count = num;
9912 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9913 num = tb->ctors? mono_array_length (tb->ctors): 0;
9914 for (i = 0; i < num; ++i)
9915 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9916 num = tb->num_methods;
9918 for (i = 0; i < num; ++i)
9919 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9921 if (tb->interfaces) {
9922 klass->interface_count = mono_array_length (tb->interfaces);
9923 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9924 for (i = 0; i < klass->interface_count; ++i) {
9925 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9926 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9927 ensure_runtime_vtable (klass->interfaces [i]);
9929 klass->interfaces_inited = 1;
9931 } else if (klass->generic_class){
9932 ensure_generic_class_runtime_vtable (klass);
9935 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9936 for (i = 0; i < klass->method.count; ++i)
9937 klass->methods [i]->slot = i;
9939 mono_class_setup_interface_offsets (klass);
9940 mono_class_setup_interface_id (klass);
9944 * The generic vtable is needed even if image->run is not set since some
9945 * runtime code like ves_icall_Type_GetMethodsByName depends on
9946 * method->slot being defined.
9950 * tb->methods could not be freed since it is used for determining
9951 * overrides during dynamic vtable construction.
9956 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9958 MonoReflectionTypeBuilder *tb;
9964 g_assert (klass->image->dynamic);
9966 if (!klass->reflection_info)
9969 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9971 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9975 for (i = 0; i < tb->num_methods; ++i) {
9976 MonoReflectionMethodBuilder *mb =
9977 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9978 if (mb->override_method)
9984 *overrides = g_new0 (MonoMethod*, onum * 2);
9987 for (i = 0; i < tb->num_methods; ++i) {
9988 MonoReflectionMethodBuilder *mb =
9989 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9990 if (mb->override_method) {
9991 (*overrides) [onum * 2] =
9992 mb->override_method->method;
9993 (*overrides) [onum * 2 + 1] =
9996 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9997 g_assert (mb->override_method->method);
9998 g_assert (mb->mhandle);
10005 *num_overrides = onum;
10009 typebuilder_setup_fields (MonoClass *klass)
10011 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10012 MonoReflectionFieldBuilder *fb;
10013 MonoClassField *field;
10014 MonoImage *image = klass->image;
10015 const char *p, *p2;
10017 guint32 len, idx, real_size = 0;
10019 klass->field.count = tb->num_fields;
10020 klass->field.first = 0;
10022 if (tb->class_size) {
10023 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10024 klass->packing_size = tb->packing_size;
10025 real_size = klass->instance_size + tb->class_size;
10028 if (!klass->field.count) {
10029 klass->instance_size = MAX (klass->instance_size, real_size);
10033 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10034 mono_class_alloc_ext (klass);
10035 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10037 for (i = 0; i < klass->field.count; ++i) {
10038 fb = mono_array_get (tb->fields, gpointer, i);
10039 field = &klass->fields [i];
10040 field->name = mono_string_to_utf8_image (image, fb->name);
10042 field->type = mono_metadata_type_dup (klass->image, fb->type->type);
10043 field->type->attrs = fb->attrs;
10045 field->type = fb->type->type;
10047 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10048 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10049 if (fb->offset != -1)
10050 field->offset = fb->offset;
10051 field->parent = klass;
10052 fb->handle = field;
10053 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10055 if (fb->def_value) {
10056 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10057 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10058 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10059 /* Copy the data from the blob since it might get realloc-ed */
10060 p = assembly->blob.data + idx;
10061 len = mono_metadata_decode_blob_size (p, &p2);
10063 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10064 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10068 klass->instance_size = MAX (klass->instance_size, real_size);
10069 mono_class_layout_fields (klass);
10073 typebuilder_setup_properties (MonoClass *klass)
10075 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10076 MonoReflectionPropertyBuilder *pb;
10077 MonoImage *image = klass->image;
10078 MonoProperty *properties;
10082 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10084 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10085 klass->ext->property.first = 0;
10087 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10088 klass->ext->properties = properties;
10089 for (i = 0; i < klass->ext->property.count; ++i) {
10090 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10091 properties [i].parent = klass;
10092 properties [i].attrs = pb->attrs;
10093 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10094 if (pb->get_method)
10095 properties [i].get = pb->get_method->mhandle;
10096 if (pb->set_method)
10097 properties [i].set = pb->set_method->mhandle;
10099 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10103 MonoReflectionEvent *
10104 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10106 MonoEvent *event = g_new0 (MonoEvent, 1);
10110 klass = my_mono_class_from_mono_type (tb->type.type);
10112 event->parent = klass;
10113 event->attrs = eb->attrs;
10114 event->name = mono_string_to_utf8 (eb->name);
10115 if (eb->add_method)
10116 event->add = eb->add_method->mhandle;
10117 if (eb->remove_method)
10118 event->remove = eb->remove_method->mhandle;
10119 if (eb->raise_method)
10120 event->raise = eb->raise_method->mhandle;
10122 if (eb->other_methods) {
10123 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10124 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10125 MonoReflectionMethodBuilder *mb =
10126 mono_array_get (eb->other_methods,
10127 MonoReflectionMethodBuilder*, j);
10128 event->other [j] = mb->mhandle;
10132 return mono_event_get_object (mono_object_domain (tb), klass, event);
10136 typebuilder_setup_events (MonoClass *klass)
10138 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10139 MonoReflectionEventBuilder *eb;
10140 MonoImage *image = klass->image;
10145 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10147 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10148 klass->ext->event.first = 0;
10150 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10151 klass->ext->events = events;
10152 for (i = 0; i < klass->ext->event.count; ++i) {
10153 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10154 events [i].parent = klass;
10155 events [i].attrs = eb->attrs;
10156 events [i].name = mono_string_to_utf8_image (image, eb->name);
10157 if (eb->add_method)
10158 events [i].add = eb->add_method->mhandle;
10159 if (eb->remove_method)
10160 events [i].remove = eb->remove_method->mhandle;
10161 if (eb->raise_method)
10162 events [i].raise = eb->raise_method->mhandle;
10164 if (eb->other_methods) {
10165 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10166 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10167 MonoReflectionMethodBuilder *mb =
10168 mono_array_get (eb->other_methods,
10169 MonoReflectionMethodBuilder*, j);
10170 events [i].other [j] = mb->mhandle;
10173 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10178 remove_instantiations_of (gpointer key,
10180 gpointer user_data)
10182 MonoType *type = (MonoType*)key;
10183 MonoClass *klass = (MonoClass*)user_data;
10185 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10191 MonoReflectionType*
10192 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10195 MonoDomain* domain;
10196 MonoReflectionType* res;
10199 MONO_ARCH_SAVE_REGS;
10201 domain = mono_object_domain (tb);
10202 klass = my_mono_class_from_mono_type (tb->type.type);
10204 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10207 * we need to lock the domain because the lock will be taken inside
10208 * So, we need to keep the locking order correct.
10210 mono_domain_lock (domain);
10211 mono_loader_lock ();
10212 if (klass->wastypebuilder) {
10213 mono_loader_unlock ();
10214 mono_domain_unlock (domain);
10215 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10218 * Fields to set in klass:
10219 * the various flags: delegate/unicode/contextbound etc.
10221 klass->flags = tb->attrs;
10222 klass->has_cctor = 1;
10223 klass->has_finalize = 1;
10226 if (!((MonoDynamicImage*)klass->image)->run) {
10227 if (klass->generic_container) {
10228 /* FIXME: The code below can't handle generic classes */
10229 klass->wastypebuilder = TRUE;
10230 mono_loader_unlock ();
10231 mono_domain_unlock (domain);
10232 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10237 /* enums are done right away */
10238 if (!klass->enumtype)
10239 ensure_runtime_vtable (klass);
10241 if (tb->subtypes) {
10242 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10243 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10244 mono_class_alloc_ext (klass);
10245 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10249 klass->nested_classes_inited = TRUE;
10251 /* fields and object layout */
10252 if (klass->parent) {
10253 if (!klass->parent->size_inited)
10254 mono_class_init (klass->parent);
10255 klass->instance_size = klass->parent->instance_size;
10256 klass->sizes.class_size = 0;
10257 klass->min_align = klass->parent->min_align;
10258 /* if the type has no fields we won't call the field_setup
10259 * routine which sets up klass->has_references.
10261 klass->has_references |= klass->parent->has_references;
10263 klass->instance_size = sizeof (MonoObject);
10264 klass->min_align = 1;
10267 /* FIXME: handle packing_size and instance_size */
10268 typebuilder_setup_fields (klass);
10270 typebuilder_setup_properties (klass);
10272 typebuilder_setup_events (klass);
10274 klass->wastypebuilder = TRUE;
10277 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10278 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10279 * we want to return normal System.MonoType objects, so clear these out from the cache.
10281 if (domain->type_hash && klass->generic_container)
10282 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10284 mono_loader_unlock ();
10285 mono_domain_unlock (domain);
10287 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10288 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10289 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10292 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10293 g_assert (res != (MonoReflectionType*)tb);
10299 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10301 MonoGenericParam *param;
10304 MONO_ARCH_SAVE_REGS;
10306 param = g_new0 (MonoGenericParam, 1);
10308 if (gparam->mbuilder) {
10309 if (!gparam->mbuilder->generic_container) {
10310 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10311 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10312 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10313 gparam->mbuilder->generic_container->is_method = TRUE;
10315 param->owner = gparam->mbuilder->generic_container;
10316 } else if (gparam->tbuilder) {
10317 if (!gparam->tbuilder->generic_container) {
10318 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10319 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10320 gparam->tbuilder->generic_container->owner.klass = klass;
10322 param->owner = gparam->tbuilder->generic_container;
10325 param->name = mono_string_to_utf8 (gparam->name);
10326 param->num = gparam->index;
10328 image = &gparam->tbuilder->module->dynamic_image->image;
10329 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10331 gparam->type.type = ¶m->pklass->byval_arg;
10333 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10334 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10338 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10340 MonoDynamicImage *assembly = sig->module->dynamic_image;
10341 guint32 na = mono_array_length (sig->arguments);
10346 sigbuffer_init (&buf, 32);
10348 sigbuffer_add_value (&buf, 0x07);
10349 sigbuffer_add_value (&buf, na);
10350 for (i = 0; i < na; ++i) {
10351 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10352 encode_reflection_type (assembly, type, &buf);
10355 buflen = buf.p - buf.buf;
10356 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10357 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10358 sigbuffer_free (&buf);
10364 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10366 MonoDynamicImage *assembly = sig->module->dynamic_image;
10367 guint32 na = mono_array_length (sig->arguments);
10372 sigbuffer_init (&buf, 32);
10374 sigbuffer_add_value (&buf, 0x06);
10375 for (i = 0; i < na; ++i) {
10376 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10377 encode_reflection_type (assembly, type, &buf);
10380 buflen = buf.p - buf.buf;
10381 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10382 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10383 sigbuffer_free (&buf);
10389 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10391 ReflectionMethodBuilder rmb;
10392 MonoMethodSignature *sig;
10397 sig = dynamic_method_to_signature (mb);
10399 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10402 * Resolve references.
10405 * Every second entry in the refs array is reserved for storing handle_class,
10406 * which is needed by the ldtoken implementation in the JIT.
10408 rmb.nrefs = mb->nrefs;
10409 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10410 for (i = 0; i < mb->nrefs; i += 2) {
10411 MonoClass *handle_class;
10413 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10415 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10416 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10418 * The referenced DynamicMethod should already be created by the managed
10419 * code, except in the case of circular references. In that case, we store
10420 * method in the refs array, and fix it up later when the referenced
10421 * DynamicMethod is created.
10423 if (method->mhandle) {
10424 ref = method->mhandle;
10426 /* FIXME: GC object stored in unmanaged memory */
10429 /* FIXME: GC object stored in unmanaged memory */
10430 method->referenced_by = g_slist_append (method->referenced_by, mb);
10432 handle_class = mono_defaults.methodhandle_class;
10434 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10437 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10442 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10443 rmb.refs [i + 1] = handle_class;
10446 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10448 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10450 /* Fix up refs entries pointing at us */
10451 for (l = mb->referenced_by; l; l = l->next) {
10452 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10453 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10456 g_assert (method->mhandle);
10458 data = (gpointer*)wrapper->method_data;
10459 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10460 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10461 data [i + 1] = mb->mhandle;
10464 g_slist_free (mb->referenced_by);
10468 /* ilgen is no longer needed */
10472 #endif /* DISABLE_REFLECTION_EMIT */
10475 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10480 mono_runtime_free_method (
10481 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10486 * mono_reflection_is_valid_dynamic_token:
10488 * Returns TRUE if token is valid.
10492 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10494 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10497 #ifndef DISABLE_REFLECTION_EMIT
10500 * mono_reflection_lookup_dynamic_token:
10502 * Finish the Builder object pointed to by TOKEN and return the corresponding
10503 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10504 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10507 * LOCKING: Take the loader lock
10510 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10512 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10516 mono_loader_lock ();
10517 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10518 mono_loader_unlock ();
10521 g_assert_not_reached ();
10527 handle_class = &klass;
10528 return resolve_object (image, obj, handle_class, context);
10532 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10534 gpointer result = NULL;
10536 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10537 result = mono_string_intern ((MonoString*)obj);
10538 *handle_class = NULL;
10540 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10541 MonoReflectionType *tb = (MonoReflectionType*)obj;
10543 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10544 result = mono_class_from_mono_type (inflated);
10545 mono_metadata_free_type (inflated);
10547 result = mono_class_from_mono_type (tb->type);
10549 *handle_class = mono_defaults.typehandle_class;
10551 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10552 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10553 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10554 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10555 result = ((MonoReflectionMethod*)obj)->method;
10557 result = mono_class_inflate_generic_method (result, context);
10558 *handle_class = mono_defaults.methodhandle_class;
10560 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10561 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10562 result = mb->mhandle;
10564 /* Type is not yet created */
10565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10567 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10570 * Hopefully this has been filled in by calling CreateType() on the
10574 * TODO: This won't work if the application finishes another
10575 * TypeBuilder instance instead of this one.
10577 result = mb->mhandle;
10580 result = mono_class_inflate_generic_method (result, context);
10581 *handle_class = mono_defaults.methodhandle_class;
10582 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10583 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10585 result = cb->mhandle;
10587 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10589 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10590 result = cb->mhandle;
10593 result = mono_class_inflate_generic_method (result, context);
10594 *handle_class = mono_defaults.methodhandle_class;
10595 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10596 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10598 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10599 MonoClass *class = mono_class_from_mono_type (inflated);
10600 MonoClassField *inflated_field;
10601 gpointer iter = NULL;
10602 mono_metadata_free_type (inflated);
10603 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10604 if (!strcmp (field->name, inflated_field->name))
10607 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10608 result = inflated_field;
10612 *handle_class = mono_defaults.fieldhandle_class;
10614 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10615 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10616 result = fb->handle;
10619 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10621 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10622 result = fb->handle;
10625 if (fb->handle && fb->handle->parent->generic_container) {
10626 MonoClass *klass = fb->handle->parent;
10627 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10628 MonoClass *inflated = mono_class_from_mono_type (type);
10630 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10632 mono_metadata_free_type (type);
10634 *handle_class = mono_defaults.fieldhandle_class;
10635 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10636 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10639 klass = tb->type.type->data.klass;
10640 if (klass->wastypebuilder) {
10641 /* Already created */
10645 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10646 result = tb->type.type->data.klass;
10649 *handle_class = mono_defaults.typehandle_class;
10650 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10651 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10652 MonoMethodSignature *sig;
10655 if (helper->arguments)
10656 nargs = mono_array_length (helper->arguments);
10660 sig = mono_metadata_signature_alloc (image, nargs);
10661 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10662 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10664 if (helper->call_conv == 0) /* unmanaged */
10665 sig->call_convention = helper->unmanaged_call_conv - 1;
10667 if (helper->call_conv & 0x02)
10668 sig->call_convention = MONO_CALL_VARARG;
10670 sig->call_convention = MONO_CALL_DEFAULT;
10672 sig->param_count = nargs;
10673 /* TODO: Copy type ? */
10674 sig->ret = helper->return_type->type;
10675 for (i = 0; i < nargs; ++i) {
10676 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10677 sig->params [i] = rt->type;
10681 *handle_class = NULL;
10682 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10683 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10684 /* Already created by the managed code */
10685 g_assert (method->mhandle);
10686 result = method->mhandle;
10687 *handle_class = mono_defaults.methodhandle_class;
10688 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10689 MonoReflectionType *tb = (MonoReflectionType*)obj;
10690 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10691 result = mono_class_from_mono_type (type);
10692 *handle_class = mono_defaults.typehandle_class;
10694 mono_metadata_free_type (type);
10695 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10696 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10697 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10698 result = mono_class_from_mono_type (type);
10699 *handle_class = mono_defaults.typehandle_class;
10701 mono_metadata_free_type (type);
10702 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10703 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10704 MonoClass *inflated;
10707 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10708 inflated = mono_class_from_mono_type (type);
10710 g_assert (f->fb->handle);
10711 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10713 mono_metadata_free_type (type);
10714 *handle_class = mono_defaults.fieldhandle_class;
10715 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10716 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10717 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10718 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10719 g_assert (c->cb->mhandle);
10720 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10721 *handle_class = mono_defaults.methodhandle_class;
10722 mono_metadata_free_type (type);
10723 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10724 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10725 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10726 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10727 g_assert (m->mb->mhandle);
10728 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10729 *handle_class = mono_defaults.methodhandle_class;
10730 mono_metadata_free_type (type);
10732 g_print (obj->vtable->klass->name);
10733 g_assert_not_reached ();
10738 #else /* DISABLE_REFLECTION_EMIT */
10741 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10743 g_assert_not_reached ();
10748 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10750 g_assert_not_reached ();
10754 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10756 g_assert_not_reached ();
10760 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10762 g_assert_not_reached ();
10766 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10768 g_assert_not_reached ();
10772 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10774 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10778 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10780 g_assert_not_reached ();
10783 MonoReflectionModule *
10784 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10786 g_assert_not_reached ();
10791 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10793 g_assert_not_reached ();
10798 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10800 g_assert_not_reached ();
10805 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10806 gboolean create_methodspec, gboolean register_token)
10808 g_assert_not_reached ();
10813 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10818 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10819 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10822 g_assert_not_reached ();
10826 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10829 *num_overrides = 0;
10832 MonoReflectionEvent *
10833 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10835 g_assert_not_reached ();
10839 MonoReflectionType*
10840 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10842 g_assert_not_reached ();
10847 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10849 g_assert_not_reached ();
10853 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10855 g_assert_not_reached ();
10860 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10862 g_assert_not_reached ();
10867 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10872 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10877 #endif /* DISABLE_REFLECTION_EMIT */
10879 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10880 const static guint32 declsec_flags_map[] = {
10881 0x00000000, /* empty */
10882 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10883 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10884 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10885 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10886 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10887 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10888 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10889 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10890 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10891 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10892 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10893 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10894 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10895 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10896 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10897 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10898 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10899 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10903 * Returns flags that includes all available security action associated to the handle.
10904 * @token: metadata token (either for a class or a method)
10905 * @image: image where resides the metadata.
10908 mono_declsec_get_flags (MonoImage *image, guint32 token)
10910 int index = mono_metadata_declsec_from_index (image, token);
10911 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10912 guint32 result = 0;
10916 /* HasSecurity can be present for other, not specially encoded, attributes,
10917 e.g. SuppressUnmanagedCodeSecurityAttribute */
10921 for (i = index; i < t->rows; i++) {
10922 guint32 cols [MONO_DECL_SECURITY_SIZE];
10924 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10925 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10928 action = cols [MONO_DECL_SECURITY_ACTION];
10929 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10930 result |= declsec_flags_map [action];
10932 g_assert_not_reached ();
10939 * Get the security actions (in the form of flags) associated with the specified method.
10941 * @method: The method for which we want the declarative security flags.
10942 * Return the declarative security flags for the method (only).
10944 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10945 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10948 mono_declsec_flags_from_method (MonoMethod *method)
10950 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10951 /* FIXME: No cache (for the moment) */
10952 guint32 idx = mono_method_get_index (method);
10953 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10954 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10955 return mono_declsec_get_flags (method->klass->image, idx);
10961 * Get the security actions (in the form of flags) associated with the specified class.
10963 * @klass: The class for which we want the declarative security flags.
10964 * Return the declarative security flags for the class.
10966 * Note: We cache the flags inside the MonoClass structure as this will get
10967 * called very often (at least for each method).
10970 mono_declsec_flags_from_class (MonoClass *klass)
10972 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10973 if (!klass->ext || !klass->ext->declsec_flags) {
10976 idx = mono_metadata_token_index (klass->type_token);
10977 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10978 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10979 mono_loader_lock ();
10980 mono_class_alloc_ext (klass);
10981 mono_loader_unlock ();
10982 /* we cache the flags on classes */
10983 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10985 return klass->ext->declsec_flags;
10991 * Get the security actions (in the form of flags) associated with the specified assembly.
10993 * @assembly: The assembly for which we want the declarative security flags.
10994 * Return the declarative security flags for the assembly.
10997 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10999 guint32 idx = 1; /* there is only one assembly */
11000 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11001 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11002 return mono_declsec_get_flags (assembly->image, idx);
11007 * Fill actions for the specific index (which may either be an encoded class token or
11008 * an encoded method token) from the metadata image.
11009 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11012 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11013 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11015 MonoBoolean result = FALSE;
11017 guint32 cols [MONO_DECL_SECURITY_SIZE];
11018 int index = mono_metadata_declsec_from_index (image, token);
11021 t = &image->tables [MONO_TABLE_DECLSECURITY];
11022 for (i = index; i < t->rows; i++) {
11023 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11025 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11028 /* if present only replace (class) permissions with method permissions */
11029 /* if empty accept either class or method permissions */
11030 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11031 if (!actions->demand.blob) {
11032 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11033 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11034 actions->demand.blob = (char*) (blob + 2);
11035 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11038 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11039 if (!actions->noncasdemand.blob) {
11040 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11041 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11042 actions->noncasdemand.blob = (char*) (blob + 2);
11043 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11046 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11047 if (!actions->demandchoice.blob) {
11048 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11049 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11050 actions->demandchoice.blob = (char*) (blob + 2);
11051 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11061 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11062 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11064 guint32 idx = mono_metadata_token_index (klass->type_token);
11065 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11066 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11067 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11071 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11072 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11074 guint32 idx = mono_method_get_index (method);
11075 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11076 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11077 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11081 * Collect all actions (that requires to generate code in mini) assigned for
11082 * the specified method.
11083 * Note: Don't use the content of actions if the function return FALSE.
11086 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11088 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11089 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11090 MonoBoolean result = FALSE;
11093 /* quick exit if no declarative security is present in the metadata */
11094 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11097 /* we want the original as the wrapper is "free" of the security informations */
11098 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11099 method = mono_marshal_method_from_wrapper (method);
11104 /* First we look for method-level attributes */
11105 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11106 mono_class_init (method->klass);
11107 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11109 result = mono_declsec_get_method_demands_params (method, demands,
11110 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11113 /* Here we use (or create) the class declarative cache to look for demands */
11114 flags = mono_declsec_flags_from_class (method->klass);
11115 if (flags & mask) {
11117 mono_class_init (method->klass);
11118 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11120 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11121 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11124 /* The boolean return value is used as a shortcut in case nothing needs to
11125 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11131 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11133 * Note: Don't use the content of actions if the function return FALSE.
11136 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11138 MonoBoolean result = FALSE;
11141 /* quick exit if no declarative security is present in the metadata */
11142 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11145 /* we want the original as the wrapper is "free" of the security informations */
11146 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11147 method = mono_marshal_method_from_wrapper (method);
11152 /* results are independant - zeroize both */
11153 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11154 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11156 /* First we look for method-level attributes */
11157 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11158 mono_class_init (method->klass);
11160 result = mono_declsec_get_method_demands_params (method, cmethod,
11161 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11164 /* Here we use (or create) the class declarative cache to look for demands */
11165 flags = mono_declsec_flags_from_class (method->klass);
11166 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11167 mono_class_init (method->klass);
11169 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11170 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11177 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11179 * @klass The inherited class - this is the class that provides the security check (attributes)
11181 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11183 * Note: Don't use the content of actions if the function return FALSE.
11186 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11188 MonoBoolean result = FALSE;
11191 /* quick exit if no declarative security is present in the metadata */
11192 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11195 /* Here we use (or create) the class declarative cache to look for demands */
11196 flags = mono_declsec_flags_from_class (klass);
11197 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11198 mono_class_init (klass);
11199 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11201 result |= mono_declsec_get_class_demands_params (klass, demands,
11202 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11209 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11211 * Note: Don't use the content of actions if the function return FALSE.
11214 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11216 /* quick exit if no declarative security is present in the metadata */
11217 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11220 /* we want the original as the wrapper is "free" of the security informations */
11221 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11222 method = mono_marshal_method_from_wrapper (method);
11227 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11228 mono_class_init (method->klass);
11229 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11231 return mono_declsec_get_method_demands_params (method, demands,
11232 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11239 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11241 guint32 cols [MONO_DECL_SECURITY_SIZE];
11245 int index = mono_metadata_declsec_from_index (image, token);
11249 t = &image->tables [MONO_TABLE_DECLSECURITY];
11250 for (i = index; i < t->rows; i++) {
11251 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11253 /* shortcut - index are ordered */
11254 if (token != cols [MONO_DECL_SECURITY_PARENT])
11257 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11258 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11259 entry->blob = (char*) (metadata + 2);
11260 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11269 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11271 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11272 guint32 idx = mono_method_get_index (method);
11273 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11274 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11275 return get_declsec_action (method->klass->image, idx, action, entry);
11281 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11284 guint32 flags = mono_declsec_flags_from_class (klass);
11285 if (declsec_flags_map [action] & flags) {
11286 guint32 idx = mono_metadata_token_index (klass->type_token);
11287 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11288 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11289 return get_declsec_action (klass->image, idx, action, entry);
11295 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11297 guint32 idx = 1; /* there is only one assembly */
11298 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11299 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11301 return get_declsec_action (assembly->image, idx, action, entry);
11305 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11307 MonoObject *res, *exc;
11309 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11310 static MonoMethod *method = NULL;
11312 if (!System_Reflection_Emit_TypeBuilder) {
11313 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11314 g_assert (System_Reflection_Emit_TypeBuilder);
11316 if (method == NULL) {
11317 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11322 * The result of mono_type_get_object () might be a System.MonoType but we
11323 * need a TypeBuilder so use klass->reflection_info.
11325 g_assert (klass->reflection_info);
11326 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11328 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11330 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11334 return *(MonoBoolean*)mono_object_unbox (res);