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)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do { \
50 if (!reflection_info_desc) { \
52 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
54 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
57 #define MOVING_GC_REGISTER(addr)
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA 0x00002000
76 MonoReflectionILGen *ilgen;
77 MonoReflectionType *rtype;
78 MonoArray *parameters;
79 MonoArray *generic_params;
80 MonoGenericContainer *generic_container;
86 guint32 *table_idx; /* note: it's a pointer */
90 MonoBoolean init_locals;
91 MonoBoolean skip_visibility;
92 MonoArray *return_modreq;
93 MonoArray *return_modopt;
94 MonoArray *param_modreq;
95 MonoArray *param_modopt;
96 MonoArray *permissions;
101 int charset, extra_flags, native_cc;
102 MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
107 MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
120 MONO_INTERFACEIMPL_SIZE,
121 MONO_MEMBERREF_SIZE, /* 0x0A */
123 MONO_CUSTOM_ATTR_SIZE,
124 MONO_FIELD_MARSHAL_SIZE,
125 MONO_DECL_SECURITY_SIZE,
126 MONO_CLASS_LAYOUT_SIZE,
127 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128 MONO_STAND_ALONE_SIGNATURE_SIZE,
132 MONO_PROPERTY_MAP_SIZE,
135 MONO_METHOD_SEMA_SIZE,
136 MONO_METHODIMPL_SIZE,
137 MONO_MODULEREF_SIZE, /* 0x1A */
143 MONO_ASSEMBLY_SIZE, /* 0x20 */
144 MONO_ASSEMBLY_PROCESSOR_SIZE,
145 MONO_ASSEMBLYOS_SIZE,
146 MONO_ASSEMBLYREF_SIZE,
147 MONO_ASSEMBLYREFPROC_SIZE,
148 MONO_ASSEMBLYREFOS_SIZE,
152 MONO_NESTED_CLASS_SIZE,
154 MONO_GENERICPARAM_SIZE, /* 0x2A */
155 MONO_METHODSPEC_SIZE,
156 MONO_GENPARCONSTRAINT_SIZE
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
206 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
207 static void init_type_builder_generics (MonoObject *type);
209 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
210 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
211 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
212 __type = mono_reflection_type_resolve_user_types (__type); \
213 mono_array_set (arr, MonoReflectionType*, index, __type); \
216 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
219 mono_reflection_init (void)
224 sigbuffer_init (SigBuffer *buf, int size)
226 buf->buf = g_malloc (size);
228 buf->end = buf->buf + size;
232 sigbuffer_make_room (SigBuffer *buf, int size)
234 if (buf->end - buf->p < size) {
235 int new_size = buf->end - buf->buf + size + 32;
236 char *p = g_realloc (buf->buf, new_size);
237 size = buf->p - buf->buf;
240 buf->end = buf->buf + new_size;
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
247 sigbuffer_make_room (buf, 6);
248 mono_metadata_encode_value (val, buf->p, &buf->p);
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
254 sigbuffer_make_room (buf, 1);
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
262 sigbuffer_make_room (buf, size);
263 memcpy (buf->p, p, size);
268 sigbuffer_free (SigBuffer *buf)
273 #ifndef DISABLE_REFLECTION_EMIT
277 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281 image_g_malloc (MonoImage *image, guint size)
284 return mono_image_alloc (image, size);
286 return g_malloc (size);
288 #endif /* !DISABLE_REFLECTION_EMIT */
293 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
297 image_g_malloc0 (MonoImage *image, guint size)
300 return mono_image_alloc0 (image, size);
302 return g_malloc0 (size);
305 #ifndef DISABLE_REFLECTION_EMIT
307 image_strdup (MonoImage *image, const char *s)
310 return mono_image_strdup (image, s);
316 #define image_g_new(image,struct_type, n_structs) \
317 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
319 #define image_g_new0(image,struct_type, n_structs) \
320 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
324 alloc_table (MonoDynamicTable *table, guint nrows)
327 g_assert (table->columns);
328 if (nrows + 1 >= table->alloc_rows) {
329 while (nrows + 1 >= table->alloc_rows) {
330 if (table->alloc_rows == 0)
331 table->alloc_rows = 16;
333 table->alloc_rows *= 2;
336 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
341 make_room_in_stream (MonoDynamicStream *stream, int size)
343 if (size <= stream->alloc_size)
346 while (stream->alloc_size <= size) {
347 if (stream->alloc_size < 4096)
348 stream->alloc_size = 4096;
350 stream->alloc_size *= 2;
353 stream->data = g_realloc (stream->data, stream->alloc_size);
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
361 gpointer oldkey, oldval;
363 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364 return GPOINTER_TO_UINT (oldval);
366 len = strlen (str) + 1;
369 make_room_in_stream (sh, idx + len);
372 * We strdup the string even if we already copy them in sh->data
373 * so that the string pointers in the hash remain valid even if
374 * we need to realloc sh->data. We may want to avoid that later.
376 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377 memcpy (sh->data + idx, str, len);
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
385 char *name = mono_string_to_utf8 (str);
387 idx = string_heap_insert (sh, name);
392 #ifndef DISABLE_REFLECTION_EMIT
394 string_heap_init (MonoDynamicStream *sh)
397 sh->alloc_size = 4096;
398 sh->data = g_malloc (4096);
399 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400 string_heap_insert (sh, "");
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
409 make_room_in_stream (stream, stream->index + len);
410 memcpy (stream->data + stream->index, data, len);
412 stream->index += len;
414 * align index? Not without adding an additional param that controls it since
415 * we may store a blob value in pieces.
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
425 make_room_in_stream (stream, stream->index + len);
426 memset (stream->data + stream->index, 0, len);
428 stream->index += len;
433 stream_data_align (MonoDynamicStream *stream)
436 guint32 count = stream->index % 4;
438 /* we assume the stream data will be aligned */
440 mono_image_add_stream_data (stream, buf, 4 - count);
443 #ifndef DISABLE_REFLECTION_EMIT
445 mono_blob_entry_hash (const char* str)
449 len = mono_metadata_decode_blob_size (str, &str);
453 for (str += 1; str < end; str++)
454 h = (h << 5) - h + *str;
462 mono_blob_entry_equal (const char *str1, const char *str2) {
466 len = mono_metadata_decode_blob_size (str1, &end1);
467 len2 = mono_metadata_decode_blob_size (str2, &end2);
470 return memcmp (end1, end2, len) == 0;
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
478 gpointer oldkey, oldval;
480 copy = g_malloc (s1+s2);
481 memcpy (copy, b1, s1);
482 memcpy (copy + s1, b2, s2);
483 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
485 idx = GPOINTER_TO_UINT (oldval);
487 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488 mono_image_add_stream_data (&assembly->blob, b2, s2);
489 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
499 guint32 size = buf->p - buf->buf;
501 g_assert (size <= (buf->end - buf->buf));
502 mono_metadata_encode_value (size, b, &b);
503 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
507 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508 * dest may be misaligned.
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
515 for (elem = 0; elem < nelem; ++elem) {
541 g_assert_not_reached ();
547 memcpy (dest, val, len * nelem);
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
556 guint32 idx = 0, len;
558 len = str->length * 2;
559 mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
562 char *swapped = g_malloc (2 * mono_string_length (str));
563 const char *p = (const char*)mono_string_chars (str);
565 swap_with_size (swapped, p, 2, mono_string_length (str));
566 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
570 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
575 #ifndef DISABLE_REFLECTION_EMIT
577 default_class_from_mono_type (MonoType *type)
579 switch (type->type) {
580 case MONO_TYPE_OBJECT:
581 return mono_defaults.object_class;
583 return mono_defaults.void_class;
584 case MONO_TYPE_BOOLEAN:
585 return mono_defaults.boolean_class;
587 return mono_defaults.char_class;
589 return mono_defaults.sbyte_class;
591 return mono_defaults.byte_class;
593 return mono_defaults.int16_class;
595 return mono_defaults.uint16_class;
597 return mono_defaults.int32_class;
599 return mono_defaults.uint32_class;
601 return mono_defaults.int_class;
603 return mono_defaults.uint_class;
605 return mono_defaults.int64_class;
607 return mono_defaults.uint64_class;
609 return mono_defaults.single_class;
611 return mono_defaults.double_class;
612 case MONO_TYPE_STRING:
613 return mono_defaults.string_class;
615 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616 g_assert_not_reached ();
624 * mono_class_get_ref_info:
626 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
629 mono_class_get_ref_info (MonoClass *klass)
631 if (klass->ref_info_handle == 0)
634 return mono_gchandle_get_target (klass->ref_info_handle);
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
640 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641 g_assert (klass->ref_info_handle != 0);
645 mono_class_free_ref_info (MonoClass *klass)
647 if (klass->ref_info_handle) {
648 mono_gchandle_free (klass->ref_info_handle);
649 klass->ref_info_handle = 0;
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
657 MonoGenericInst *class_inst;
662 class_inst = gclass->context.class_inst;
664 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665 klass = gclass->container_class;
666 sigbuffer_add_value (buf, klass->byval_arg.type);
667 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
669 sigbuffer_add_value (buf, class_inst->type_argc);
670 for (i = 0; i < class_inst->type_argc; ++i)
671 encode_type (assembly, class_inst->type_argv [i], buf);
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
679 g_assert_not_reached ();
684 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
688 case MONO_TYPE_BOOLEAN:
702 case MONO_TYPE_STRING:
703 case MONO_TYPE_OBJECT:
704 case MONO_TYPE_TYPEDBYREF:
705 sigbuffer_add_value (buf, type->type);
708 sigbuffer_add_value (buf, type->type);
709 encode_type (assembly, type->data.type, buf);
711 case MONO_TYPE_SZARRAY:
712 sigbuffer_add_value (buf, type->type);
713 encode_type (assembly, &type->data.klass->byval_arg, buf);
715 case MONO_TYPE_VALUETYPE:
716 case MONO_TYPE_CLASS: {
717 MonoClass *k = mono_class_from_mono_type (type);
719 if (k->generic_container) {
720 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721 encode_generic_class (assembly, gclass, buf);
724 * Make sure we use the correct type.
726 sigbuffer_add_value (buf, k->byval_arg.type);
728 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729 * otherwise two typerefs could point to the same type, leading to
730 * verification errors.
732 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
736 case MONO_TYPE_ARRAY:
737 sigbuffer_add_value (buf, type->type);
738 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739 sigbuffer_add_value (buf, type->data.array->rank);
740 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741 sigbuffer_add_value (buf, 0);
743 case MONO_TYPE_GENERICINST:
744 encode_generic_class (assembly, type->data.generic_class, buf);
748 sigbuffer_add_value (buf, type->type);
749 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
752 g_error ("need to encode type %x", type->type);
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
760 sigbuffer_add_value (buf, MONO_TYPE_VOID);
764 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
773 for (i = 0; i < mono_array_length (modreq); ++i) {
774 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
780 for (i = 0; i < mono_array_length (modopt); ++i) {
781 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
788 #ifndef DISABLE_REFLECTION_EMIT
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
794 guint32 nparams = sig->param_count;
800 sigbuffer_init (&buf, 32);
802 * FIXME: vararg, explicit_this, differenc call_conv values...
804 idx = sig->call_convention;
806 idx |= 0x20; /* hasthis */
807 if (sig->generic_param_count)
808 idx |= 0x10; /* generic */
809 sigbuffer_add_byte (&buf, idx);
810 if (sig->generic_param_count)
811 sigbuffer_add_value (&buf, sig->generic_param_count);
812 sigbuffer_add_value (&buf, nparams);
813 encode_type (assembly, sig->ret, &buf);
814 for (i = 0; i < nparams; ++i) {
815 if (i == sig->sentinelpos)
816 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817 encode_type (assembly, sig->params [i], &buf);
819 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820 sigbuffer_free (&buf);
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
829 * FIXME: reuse code from method_encode_signature().
833 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
834 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
838 sigbuffer_init (&buf, 32);
839 /* LAMESPEC: all the call conv spec is foobared */
840 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841 if (mb->call_conv & 2)
842 idx |= 0x5; /* vararg */
843 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844 idx |= 0x20; /* hasthis */
846 idx |= 0x10; /* generic */
847 sigbuffer_add_byte (&buf, idx);
849 sigbuffer_add_value (&buf, ngparams);
850 sigbuffer_add_value (&buf, nparams + notypes);
851 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852 encode_reflection_type (assembly, mb->rtype, &buf);
853 for (i = 0; i < nparams; ++i) {
854 MonoArray *modreq = NULL;
855 MonoArray *modopt = NULL;
856 MonoReflectionType *pt;
858 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864 encode_reflection_type (assembly, pt, &buf);
867 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868 for (i = 0; i < notypes; ++i) {
869 MonoReflectionType *pt;
871 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872 encode_reflection_type (assembly, pt, &buf);
875 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876 sigbuffer_free (&buf);
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
883 MonoDynamicTable *table;
885 guint32 idx, sig_idx;
886 guint nl = mono_array_length (ilgen->locals);
890 sigbuffer_init (&buf, 32);
891 sigbuffer_add_value (&buf, 0x07);
892 sigbuffer_add_value (&buf, nl);
893 for (i = 0; i < nl; ++i) {
894 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
897 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
899 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
901 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902 sigbuffer_free (&buf);
904 if (assembly->standalonesig_cache == NULL)
905 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
910 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911 idx = table->next_idx ++;
913 alloc_table (table, table->rows);
914 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
916 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
918 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
924 method_count_clauses (MonoReflectionILGen *ilgen)
926 guint32 num_clauses = 0;
929 MonoILExceptionInfo *ex_info;
930 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932 if (ex_info->handlers)
933 num_clauses += mono_array_length (ex_info->handlers);
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
945 MonoExceptionClause *clauses;
946 MonoExceptionClause *clause;
947 MonoILExceptionInfo *ex_info;
948 MonoILExceptionBlock *ex_block;
949 guint32 finally_start;
950 int i, j, clause_index;;
952 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
955 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957 finally_start = ex_info->start + ex_info->len;
958 if (!ex_info->handlers)
960 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962 clause = &(clauses [clause_index]);
964 clause->flags = ex_block->type;
965 clause->try_offset = ex_info->start;
967 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968 clause->try_len = finally_start - ex_info->start;
970 clause->try_len = ex_info->len;
971 clause->handler_offset = ex_block->start;
972 clause->handler_len = ex_block->len;
973 if (ex_block->extype) {
974 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
976 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977 clause->data.filter_offset = ex_block->filter_offset;
979 clause->data.filter_offset = 0;
981 finally_start = ex_block->start + ex_block->len;
989 #endif /* !DISABLE_REFLECTION_EMIT */
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
998 gint32 num_locals = 0;
999 gint32 num_exception = 0;
1002 char fat_header [12];
1004 guint16 short_value;
1005 guint32 local_sig = 0;
1006 guint32 header_size = 12;
1009 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1014 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1016 code = mb->ilgen->code;
1017 code_size = mb->ilgen->code_len;
1018 max_stack = mb->ilgen->max_stack;
1019 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020 if (mb->ilgen->ex_handlers)
1021 num_exception = method_count_clauses (mb->ilgen);
1025 char *name = mono_string_to_utf8 (mb->name);
1026 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1030 mono_raise_exception (exception);
1033 code_size = mono_array_length (code);
1034 max_stack = 8; /* we probably need to run a verifier on the code... */
1037 stream_data_align (&assembly->code);
1039 /* check for exceptions, maxstack, locals */
1040 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1042 if (code_size < 64 && !(code_size & 1)) {
1043 flags = (code_size << 2) | 0x2;
1044 } else if (code_size < 32 && (code_size & 1)) {
1045 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1049 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050 /* add to the fixup todo list */
1051 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054 return assembly->text_rva + idx;
1058 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1060 * FIXME: need to set also the header size in fat_flags.
1061 * (and more sects and init locals flags)
1065 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066 if (mb->init_locals)
1067 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068 fat_header [0] = fat_flags;
1069 fat_header [1] = (header_size / 4 ) << 4;
1070 short_value = GUINT16_TO_LE (max_stack);
1071 memcpy (fat_header + 2, &short_value, 2);
1072 int_value = GUINT32_TO_LE (code_size);
1073 memcpy (fat_header + 4, &int_value, 4);
1074 int_value = GUINT32_TO_LE (local_sig);
1075 memcpy (fat_header + 8, &int_value, 4);
1076 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077 /* add to the fixup todo list */
1078 if (mb->ilgen && mb->ilgen->num_token_fixups)
1079 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1081 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082 if (num_exception) {
1083 unsigned char sheader [4];
1084 MonoILExceptionInfo * ex_info;
1085 MonoILExceptionBlock * ex_block;
1088 stream_data_align (&assembly->code);
1089 /* always use fat format for now */
1090 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091 num_exception *= 6 * sizeof (guint32);
1092 num_exception += 4; /* include the size of the header */
1093 sheader [1] = num_exception & 0xff;
1094 sheader [2] = (num_exception >> 8) & 0xff;
1095 sheader [3] = (num_exception >> 16) & 0xff;
1096 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097 /* fat header, so we are already aligned */
1099 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101 if (ex_info->handlers) {
1102 int finally_start = ex_info->start + ex_info->len;
1103 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1105 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1107 val = GUINT32_TO_LE (ex_block->type);
1108 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110 val = GUINT32_TO_LE (ex_info->start);
1111 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112 /* need fault, too, probably */
1113 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114 val = GUINT32_TO_LE (finally_start - ex_info->start);
1116 val = GUINT32_TO_LE (ex_info->len);
1117 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118 /* handler offset */
1119 val = GUINT32_TO_LE (ex_block->start);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122 val = GUINT32_TO_LE (ex_block->len);
1123 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124 finally_start = ex_block->start + ex_block->len;
1125 if (ex_block->extype) {
1126 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1128 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129 val = ex_block->filter_offset;
1133 val = GUINT32_TO_LE (val);
1134 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135 /*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",
1136 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);*/
1139 g_error ("No clauses for ex info block %d", i);
1143 return assembly->text_rva + idx;
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1150 MonoDynamicTable *table;
1153 table = &assembly->tables [table_idx];
1155 g_assert (col < table->columns);
1157 values = table->values + table->columns;
1158 for (i = 1; i <= table->rows; ++i) {
1159 if (values [col] == token)
1161 values += table->columns;
1167 * LOCKING: Acquires the loader lock.
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1172 MonoCustomAttrInfo* res;
1174 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1179 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1183 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1185 /* FIXME: Need to do more checks */
1186 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1187 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1189 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1196 static MonoCustomAttrInfo*
1197 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1199 int i, index, count, not_visible;
1200 MonoCustomAttrInfo *ainfo;
1201 MonoReflectionCustomAttr *cattr;
1205 /* FIXME: check in assembly the Run flag is set */
1207 count = mono_array_length (cattrs);
1209 /* Skip nonpublic attributes since MS.NET seems to do the same */
1210 /* FIXME: This needs to be done more globally */
1212 for (i = 0; i < count; ++i) {
1213 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1214 if (!custom_attr_visible (image, cattr))
1217 count -= not_visible;
1219 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1221 ainfo->image = image;
1222 ainfo->num_attrs = count;
1223 ainfo->cached = alloc_img != NULL;
1225 for (i = 0; i < count; ++i) {
1226 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1227 if (custom_attr_visible (image, cattr)) {
1228 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1229 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1230 ainfo->attrs [index].ctor = cattr->ctor->method;
1231 ainfo->attrs [index].data = saved;
1232 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1240 #ifndef DISABLE_REFLECTION_EMIT
1242 * LOCKING: Acquires the loader lock.
1245 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1247 MonoCustomAttrInfo *ainfo, *tmp;
1249 if (!cattrs || !mono_array_length (cattrs))
1252 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1254 mono_loader_lock ();
1255 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1257 mono_custom_attrs_free (tmp);
1258 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1259 mono_loader_unlock ();
1265 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1272 * idx is the table index of the object
1273 * type is one of MONO_CUSTOM_ATTR_*
1276 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1278 MonoDynamicTable *table;
1279 MonoReflectionCustomAttr *cattr;
1281 guint32 count, i, token;
1283 char *p = blob_size;
1285 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1288 count = mono_array_length (cattrs);
1289 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1290 table->rows += count;
1291 alloc_table (table, table->rows);
1292 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1293 idx <<= MONO_CUSTOM_ATTR_BITS;
1295 for (i = 0; i < count; ++i) {
1296 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1297 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1298 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1299 type = mono_metadata_token_index (token);
1300 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1301 switch (mono_metadata_token_table (token)) {
1302 case MONO_TABLE_METHOD:
1303 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1305 case MONO_TABLE_MEMBERREF:
1306 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1309 g_warning ("got wrong token in custom attr");
1312 values [MONO_CUSTOM_ATTR_TYPE] = type;
1314 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1315 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1316 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1317 values += MONO_CUSTOM_ATTR_SIZE;
1323 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1325 MonoDynamicTable *table;
1327 guint32 count, i, idx;
1328 MonoReflectionPermissionSet *perm;
1333 count = mono_array_length (permissions);
1334 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1335 table->rows += count;
1336 alloc_table (table, table->rows);
1338 for (i = 0; i < mono_array_length (permissions); ++i) {
1339 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1341 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1343 idx = mono_metadata_token_index (parent_token);
1344 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1345 switch (mono_metadata_token_table (parent_token)) {
1346 case MONO_TABLE_TYPEDEF:
1347 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1349 case MONO_TABLE_METHOD:
1350 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1352 case MONO_TABLE_ASSEMBLY:
1353 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1356 g_assert_not_reached ();
1359 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1360 values [MONO_DECL_SECURITY_PARENT] = idx;
1361 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1368 * Fill in the MethodDef and ParamDef tables for a method.
1369 * This is used for both normal methods and constructors.
1372 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1374 MonoDynamicTable *table;
1378 /* room in this table is already allocated */
1379 table = &assembly->tables [MONO_TABLE_METHOD];
1380 *mb->table_idx = table->next_idx ++;
1381 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1382 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1383 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1384 values [MONO_METHOD_FLAGS] = mb->attrs;
1385 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1386 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1387 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1389 table = &assembly->tables [MONO_TABLE_PARAM];
1390 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1392 mono_image_add_decl_security (assembly,
1393 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1396 MonoDynamicTable *mtable;
1399 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1400 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1403 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1404 if (mono_array_get (mb->pinfo, gpointer, i))
1407 table->rows += count;
1408 alloc_table (table, table->rows);
1409 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1410 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411 MonoReflectionParamBuilder *pb;
1412 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1413 values [MONO_PARAM_FLAGS] = pb->attrs;
1414 values [MONO_PARAM_SEQUENCE] = i;
1415 if (pb->name != NULL) {
1416 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1418 values [MONO_PARAM_NAME] = 0;
1420 values += MONO_PARAM_SIZE;
1421 if (pb->marshal_info) {
1423 alloc_table (mtable, mtable->rows);
1424 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1425 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1426 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1428 pb->table_idx = table->next_idx++;
1429 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1430 guint32 field_type = 0;
1431 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1433 alloc_table (mtable, mtable->rows);
1434 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1435 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1436 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1437 mvalues [MONO_CONSTANT_TYPE] = field_type;
1438 mvalues [MONO_CONSTANT_PADDING] = 0;
1445 #ifndef DISABLE_REFLECTION_EMIT
1447 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1449 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1451 rmb->ilgen = mb->ilgen;
1452 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1453 rmb->parameters = mb->parameters;
1454 rmb->generic_params = mb->generic_params;
1455 rmb->generic_container = mb->generic_container;
1456 rmb->opt_types = NULL;
1457 rmb->pinfo = mb->pinfo;
1458 rmb->attrs = mb->attrs;
1459 rmb->iattrs = mb->iattrs;
1460 rmb->call_conv = mb->call_conv;
1461 rmb->code = mb->code;
1462 rmb->type = mb->type;
1463 rmb->name = mb->name;
1464 rmb->table_idx = &mb->table_idx;
1465 rmb->init_locals = mb->init_locals;
1466 rmb->skip_visibility = FALSE;
1467 rmb->return_modreq = mb->return_modreq;
1468 rmb->return_modopt = mb->return_modopt;
1469 rmb->param_modreq = mb->param_modreq;
1470 rmb->param_modopt = mb->param_modopt;
1471 rmb->permissions = mb->permissions;
1472 rmb->mhandle = mb->mhandle;
1477 rmb->charset = mb->charset;
1478 rmb->extra_flags = mb->extra_flags;
1479 rmb->native_cc = mb->native_cc;
1480 rmb->dllentry = mb->dllentry;
1486 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1488 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1490 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1492 rmb->ilgen = mb->ilgen;
1493 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1494 rmb->parameters = mb->parameters;
1495 rmb->generic_params = NULL;
1496 rmb->generic_container = NULL;
1497 rmb->opt_types = NULL;
1498 rmb->pinfo = mb->pinfo;
1499 rmb->attrs = mb->attrs;
1500 rmb->iattrs = mb->iattrs;
1501 rmb->call_conv = mb->call_conv;
1503 rmb->type = mb->type;
1504 rmb->name = mono_string_new (mono_domain_get (), name);
1505 rmb->table_idx = &mb->table_idx;
1506 rmb->init_locals = mb->init_locals;
1507 rmb->skip_visibility = FALSE;
1508 rmb->return_modreq = NULL;
1509 rmb->return_modopt = NULL;
1510 rmb->param_modreq = mb->param_modreq;
1511 rmb->param_modopt = mb->param_modopt;
1512 rmb->permissions = mb->permissions;
1513 rmb->mhandle = mb->mhandle;
1519 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1521 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1523 rmb->ilgen = mb->ilgen;
1524 rmb->rtype = mb->rtype;
1525 rmb->parameters = mb->parameters;
1526 rmb->generic_params = NULL;
1527 rmb->generic_container = NULL;
1528 rmb->opt_types = NULL;
1530 rmb->attrs = mb->attrs;
1532 rmb->call_conv = mb->call_conv;
1534 rmb->type = (MonoObject *) mb->owner;
1535 rmb->name = mb->name;
1536 rmb->table_idx = NULL;
1537 rmb->init_locals = mb->init_locals;
1538 rmb->skip_visibility = mb->skip_visibility;
1539 rmb->return_modreq = NULL;
1540 rmb->return_modopt = NULL;
1541 rmb->param_modreq = NULL;
1542 rmb->param_modopt = NULL;
1543 rmb->permissions = NULL;
1544 rmb->mhandle = mb->mhandle;
1551 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1553 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1554 MonoDynamicTable *table;
1558 if (!mb->override_method)
1561 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1563 alloc_table (table, table->rows);
1564 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1565 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1566 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1568 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1569 switch (mono_metadata_token_table (tok)) {
1570 case MONO_TABLE_MEMBERREF:
1571 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1573 case MONO_TABLE_METHOD:
1574 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1577 g_assert_not_reached ();
1579 values [MONO_METHODIMPL_DECLARATION] = tok;
1582 #ifndef DISABLE_REFLECTION_EMIT
1584 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1586 MonoDynamicTable *table;
1588 ReflectionMethodBuilder rmb;
1591 reflection_methodbuilder_from_method_builder (&rmb, mb);
1593 mono_image_basic_method (&rmb, assembly);
1594 mb->table_idx = *rmb.table_idx;
1596 if (mb->dll) { /* It's a P/Invoke method */
1598 /* map CharSet values to on-disk values */
1599 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1600 int extra_flags = mb->extra_flags;
1601 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1603 alloc_table (table, table->rows);
1604 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1606 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1607 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1609 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1611 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1612 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1613 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1614 table = &assembly->tables [MONO_TABLE_MODULEREF];
1616 alloc_table (table, table->rows);
1617 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1618 values [MONO_IMPLMAP_SCOPE] = table->rows;
1622 if (mb->generic_params) {
1623 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1624 table->rows += mono_array_length (mb->generic_params);
1625 alloc_table (table, table->rows);
1626 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1627 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1629 mono_image_get_generic_param_info (
1630 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1637 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1639 ReflectionMethodBuilder rmb;
1641 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1643 mono_image_basic_method (&rmb, assembly);
1644 mb->table_idx = *rmb.table_idx;
1649 type_get_fully_qualified_name (MonoType *type)
1651 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1655 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1659 klass = mono_class_from_mono_type (type);
1661 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1662 ta = klass->image->assembly;
1663 if (ta->dynamic || (ta == ass)) {
1664 if (klass->generic_class || klass->generic_container)
1665 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1666 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1668 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1671 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 /*field_image is the image to which the eventual custom mods have been encoded against*/
1677 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1680 guint32 idx, i, token;
1682 if (!assembly->save)
1685 sigbuffer_init (&buf, 32);
1687 sigbuffer_add_value (&buf, 0x06);
1688 /* encode custom attributes before the type */
1689 if (type->num_mods) {
1690 for (i = 0; i < type->num_mods; ++i) {
1692 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1694 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1696 token = type->modifiers [i].token;
1699 if (type->modifiers [i].required)
1700 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1702 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1704 sigbuffer_add_value (&buf, token);
1707 encode_type (assembly, type, &buf);
1708 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1709 sigbuffer_free (&buf);
1715 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1719 guint32 typespec = 0;
1723 init_type_builder_generics (fb->type);
1725 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1726 class = mono_class_from_mono_type (type);
1728 sigbuffer_init (&buf, 32);
1730 sigbuffer_add_value (&buf, 0x06);
1731 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1732 /* encode custom attributes before the type */
1734 if (class->generic_container)
1735 typespec = create_typespec (assembly, type);
1738 MonoGenericClass *gclass;
1739 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1740 encode_generic_class (assembly, gclass, &buf);
1742 encode_type (assembly, type, &buf);
1744 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1745 sigbuffer_free (&buf);
1750 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1751 char blob_size [64];
1752 char *b = blob_size;
1755 guint32 idx = 0, len = 0, dummy = 0;
1757 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1758 guint32 fpa_double [2];
1763 p = buf = g_malloc (64);
1765 *ret_type = MONO_TYPE_CLASS;
1767 box_val = (char*)&dummy;
1769 box_val = ((char*)val) + sizeof (MonoObject);
1770 *ret_type = val->vtable->klass->byval_arg.type;
1773 switch (*ret_type) {
1774 case MONO_TYPE_BOOLEAN:
1779 case MONO_TYPE_CHAR:
1796 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1797 fpa_p = (guint32*)box_val;
1798 fpa_double [0] = fpa_p [1];
1799 fpa_double [1] = fpa_p [0];
1800 box_val = (char*)fpa_double;
1804 case MONO_TYPE_VALUETYPE: {
1805 MonoClass *klass = val->vtable->klass;
1807 if (klass->enumtype) {
1808 *ret_type = mono_class_enum_basetype (klass)->type;
1810 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1813 g_error ("we can't encode valuetypes, we should have never reached this line");
1816 case MONO_TYPE_CLASS:
1818 case MONO_TYPE_STRING: {
1819 MonoString *str = (MonoString*)val;
1820 /* there is no signature */
1821 len = str->length * 2;
1822 mono_metadata_encode_value (len, b, &b);
1823 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1825 char *swapped = g_malloc (2 * mono_string_length (str));
1826 const char *p = (const char*)mono_string_chars (str);
1828 swap_with_size (swapped, p, 2, mono_string_length (str));
1829 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1833 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1839 case MONO_TYPE_GENERICINST:
1840 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1843 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1846 /* there is no signature */
1847 mono_metadata_encode_value (len, b, &b);
1848 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1849 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1850 swap_with_size (blob_size, box_val, len, 1);
1851 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1853 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1861 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1866 sigbuffer_init (&buf, 32);
1868 sigbuffer_add_value (&buf, minfo->type);
1870 switch (minfo->type) {
1871 case MONO_NATIVE_BYVALTSTR:
1872 case MONO_NATIVE_BYVALARRAY:
1873 sigbuffer_add_value (&buf, minfo->count);
1875 case MONO_NATIVE_LPARRAY:
1876 if (minfo->eltype || minfo->has_size) {
1877 sigbuffer_add_value (&buf, minfo->eltype);
1878 if (minfo->has_size) {
1879 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1880 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1882 /* LAMESPEC: ElemMult is undocumented */
1883 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1887 case MONO_NATIVE_SAFEARRAY:
1889 sigbuffer_add_value (&buf, minfo->eltype);
1891 case MONO_NATIVE_CUSTOM:
1893 str = mono_string_to_utf8 (minfo->guid);
1895 sigbuffer_add_value (&buf, len);
1896 sigbuffer_add_mem (&buf, str, len);
1899 sigbuffer_add_value (&buf, 0);
1901 /* native type name */
1902 sigbuffer_add_value (&buf, 0);
1903 /* custom marshaler type name */
1904 if (minfo->marshaltype || minfo->marshaltyperef) {
1905 if (minfo->marshaltyperef)
1906 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1908 str = mono_string_to_utf8 (minfo->marshaltype);
1910 sigbuffer_add_value (&buf, len);
1911 sigbuffer_add_mem (&buf, str, len);
1914 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1915 sigbuffer_add_value (&buf, 0);
1917 if (minfo->mcookie) {
1918 str = mono_string_to_utf8 (minfo->mcookie);
1920 sigbuffer_add_value (&buf, len);
1921 sigbuffer_add_mem (&buf, str, len);
1924 sigbuffer_add_value (&buf, 0);
1930 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1931 sigbuffer_free (&buf);
1936 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1938 MonoDynamicTable *table;
1941 /* maybe this fixup should be done in the C# code */
1942 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1943 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1944 table = &assembly->tables [MONO_TABLE_FIELD];
1945 fb->table_idx = table->next_idx ++;
1946 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1947 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1948 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1949 values [MONO_FIELD_FLAGS] = fb->attrs;
1950 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1952 if (fb->offset != -1) {
1953 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1955 alloc_table (table, table->rows);
1956 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1957 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1958 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1960 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1961 guint32 field_type = 0;
1962 table = &assembly->tables [MONO_TABLE_CONSTANT];
1964 alloc_table (table, table->rows);
1965 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1966 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1967 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1968 values [MONO_CONSTANT_TYPE] = field_type;
1969 values [MONO_CONSTANT_PADDING] = 0;
1971 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1973 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1975 alloc_table (table, table->rows);
1976 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1977 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1979 * We store it in the code section because it's simpler for now.
1982 if (mono_array_length (fb->rva_data) >= 10)
1983 stream_data_align (&assembly->code);
1984 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1986 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1987 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1989 if (fb->marshal_info) {
1990 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1992 alloc_table (table, table->rows);
1993 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1994 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1995 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2000 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2003 guint32 nparams = 0;
2004 MonoReflectionMethodBuilder *mb = fb->get_method;
2005 MonoReflectionMethodBuilder *smb = fb->set_method;
2008 if (mb && mb->parameters)
2009 nparams = mono_array_length (mb->parameters);
2010 if (!mb && smb && smb->parameters)
2011 nparams = mono_array_length (smb->parameters) - 1;
2012 sigbuffer_init (&buf, 32);
2013 if (fb->call_conv & 0x20)
2014 sigbuffer_add_byte (&buf, 0x28);
2016 sigbuffer_add_byte (&buf, 0x08);
2017 sigbuffer_add_value (&buf, nparams);
2019 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2020 for (i = 0; i < nparams; ++i) {
2021 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2022 encode_reflection_type (assembly, pt, &buf);
2024 } else if (smb && smb->parameters) {
2025 /* the property type is the last param */
2026 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2027 for (i = 0; i < nparams; ++i) {
2028 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2029 encode_reflection_type (assembly, pt, &buf);
2032 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2035 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2036 sigbuffer_free (&buf);
2041 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2043 MonoDynamicTable *table;
2045 guint num_methods = 0;
2049 * we need to set things in the following tables:
2050 * PROPERTYMAP (info already filled in _get_type_info ())
2051 * PROPERTY (rows already preallocated in _get_type_info ())
2052 * METHOD (method info already done with the generic method code)
2056 table = &assembly->tables [MONO_TABLE_PROPERTY];
2057 pb->table_idx = table->next_idx ++;
2058 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2059 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2060 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2061 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2063 /* FIXME: we still don't handle 'other' methods */
2064 if (pb->get_method) num_methods ++;
2065 if (pb->set_method) num_methods ++;
2067 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2068 table->rows += num_methods;
2069 alloc_table (table, table->rows);
2071 if (pb->get_method) {
2072 semaidx = table->next_idx ++;
2073 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2074 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2075 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2076 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2078 if (pb->set_method) {
2079 semaidx = table->next_idx ++;
2080 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2081 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2082 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2083 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2085 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2086 guint32 field_type = 0;
2087 table = &assembly->tables [MONO_TABLE_CONSTANT];
2089 alloc_table (table, table->rows);
2090 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2091 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2092 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2093 values [MONO_CONSTANT_TYPE] = field_type;
2094 values [MONO_CONSTANT_PADDING] = 0;
2099 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2101 MonoDynamicTable *table;
2103 guint num_methods = 0;
2107 * we need to set things in the following tables:
2108 * EVENTMAP (info already filled in _get_type_info ())
2109 * EVENT (rows already preallocated in _get_type_info ())
2110 * METHOD (method info already done with the generic method code)
2113 table = &assembly->tables [MONO_TABLE_EVENT];
2114 eb->table_idx = table->next_idx ++;
2115 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2116 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2117 values [MONO_EVENT_FLAGS] = eb->attrs;
2118 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2121 * FIXME: we still don't handle 'other' methods
2123 if (eb->add_method) num_methods ++;
2124 if (eb->remove_method) num_methods ++;
2125 if (eb->raise_method) num_methods ++;
2127 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2128 table->rows += num_methods;
2129 alloc_table (table, table->rows);
2131 if (eb->add_method) {
2132 semaidx = table->next_idx ++;
2133 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2135 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2136 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2138 if (eb->remove_method) {
2139 semaidx = table->next_idx ++;
2140 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2141 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2142 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2143 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2145 if (eb->raise_method) {
2146 semaidx = table->next_idx ++;
2147 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2148 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2149 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2150 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2155 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2157 MonoDynamicTable *table;
2158 guint32 num_constraints, i;
2162 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2163 num_constraints = gparam->iface_constraints ?
2164 mono_array_length (gparam->iface_constraints) : 0;
2165 table->rows += num_constraints;
2166 if (gparam->base_type)
2168 alloc_table (table, table->rows);
2170 if (gparam->base_type) {
2171 table_idx = table->next_idx ++;
2172 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176 assembly, mono_reflection_type_get_handle (gparam->base_type));
2179 for (i = 0; i < num_constraints; i++) {
2180 MonoReflectionType *constraint = mono_array_get (
2181 gparam->iface_constraints, gpointer, i);
2183 table_idx = table->next_idx ++;
2184 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2186 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2187 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2188 assembly, mono_reflection_type_get_handle (constraint));
2193 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2195 GenericParamTableEntry *entry;
2198 * The GenericParam table must be sorted according to the `owner' field.
2199 * We need to do this sorting prior to writing the GenericParamConstraint
2200 * table, since we have to use the final GenericParam table indices there
2201 * and they must also be sorted.
2204 entry = g_new0 (GenericParamTableEntry, 1);
2205 entry->owner = owner;
2206 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2207 MOVING_GC_REGISTER (&entry->gparam);
2208 entry->gparam = gparam;
2210 g_ptr_array_add (assembly->gen_params, entry);
2214 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2216 MonoDynamicTable *table;
2217 MonoGenericParam *param;
2221 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2222 table_idx = table->next_idx ++;
2223 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2225 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2227 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2228 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2229 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2230 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2232 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2234 encode_constraints (entry->gparam, table_idx, assembly);
2238 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2240 MonoDynamicTable *table;
2243 guint32 cols [MONO_ASSEMBLY_SIZE];
2247 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2250 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2251 table = &assembly->tables [MONO_TABLE_MODULEREF];
2252 token = table->next_idx ++;
2254 alloc_table (table, table->rows);
2255 values = table->values + token * MONO_MODULEREF_SIZE;
2256 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2258 token <<= MONO_RESOLTION_SCOPE_BITS;
2259 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2260 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2265 if (image->assembly->dynamic)
2267 memset (cols, 0, sizeof (cols));
2269 /* image->assembly->image is the manifest module */
2270 image = image->assembly->image;
2271 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2274 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2275 token = table->next_idx ++;
2277 alloc_table (table, table->rows);
2278 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2279 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2280 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2281 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2282 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2283 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2284 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2285 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2286 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2288 if (strcmp ("", image->assembly->aname.culture)) {
2289 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2290 image->assembly->aname.culture);
2293 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2294 guchar pubtoken [9];
2296 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2297 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2299 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2301 token <<= MONO_RESOLTION_SCOPE_BITS;
2302 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2303 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2308 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2310 MonoDynamicTable *table;
2315 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2318 sigbuffer_init (&buf, 32);
2319 switch (type->type) {
2320 case MONO_TYPE_FNPTR:
2322 case MONO_TYPE_SZARRAY:
2323 case MONO_TYPE_ARRAY:
2325 case MONO_TYPE_MVAR:
2326 case MONO_TYPE_GENERICINST:
2327 encode_type (assembly, type, &buf);
2329 case MONO_TYPE_CLASS:
2330 case MONO_TYPE_VALUETYPE: {
2331 MonoClass *k = mono_class_from_mono_type (type);
2332 if (!k || !k->generic_container) {
2333 sigbuffer_free (&buf);
2336 encode_type (assembly, type, &buf);
2340 sigbuffer_free (&buf);
2344 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2345 if (assembly->save) {
2346 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2347 alloc_table (table, table->rows + 1);
2348 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2349 values [MONO_TYPESPEC_SIGNATURE] = token;
2351 sigbuffer_free (&buf);
2353 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2354 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2360 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2362 MonoDynamicTable *table;
2364 guint32 token, scope, enclosing;
2367 /* if the type requires a typespec, we must try that first*/
2368 if (try_typespec && (token = create_typespec (assembly, type)))
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2373 klass = mono_class_from_mono_type (type);
2375 klass = mono_class_from_mono_type (type);
2378 * If it's in the same module and not a generic type parameter:
2380 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2381 (type->type != MONO_TYPE_MVAR)) {
2382 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2383 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2384 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2388 if (klass->nested_in) {
2389 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2390 /* get the typeref idx of the enclosing type */
2391 enclosing >>= MONO_TYPEDEFORREF_BITS;
2392 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2394 scope = resolution_scope_from_image (assembly, klass->image);
2396 table = &assembly->tables [MONO_TABLE_TYPEREF];
2397 if (assembly->save) {
2398 alloc_table (table, table->rows + 1);
2399 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2400 values [MONO_TYPEREF_SCOPE] = scope;
2401 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2402 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2404 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2405 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2407 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2412 * Despite the name, we handle also TypeSpec (with the above helper).
2415 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2417 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2420 #ifndef DISABLE_REFLECTION_EMIT
2422 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2424 MonoDynamicTable *table;
2426 guint32 token, pclass;
2428 switch (parent & MONO_TYPEDEFORREF_MASK) {
2429 case MONO_TYPEDEFORREF_TYPEREF:
2430 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2432 case MONO_TYPEDEFORREF_TYPESPEC:
2433 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2435 case MONO_TYPEDEFORREF_TYPEDEF:
2436 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2439 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2442 /* extract the index */
2443 parent >>= MONO_TYPEDEFORREF_BITS;
2445 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2447 if (assembly->save) {
2448 alloc_table (table, table->rows + 1);
2449 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2450 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2451 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2452 values [MONO_MEMBERREF_SIGNATURE] = sig;
2455 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2462 * Insert a memberef row into the metadata: the token that point to the memberref
2463 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2464 * mono_image_get_fieldref_token()).
2465 * The sig param is an index to an already built signature.
2468 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2470 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2471 return mono_image_add_memberef_row (assembly, parent, name, sig);
2476 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2479 MonoMethodSignature *sig;
2481 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2483 if (create_typespec) {
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2489 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2490 if (token && !create_typespec)
2493 g_assert (!method->is_inflated);
2496 * A methodref signature can't contain an unmanaged calling convention.
2498 sig = mono_metadata_signature_dup (mono_method_signature (method));
2499 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2500 sig->call_convention = MONO_CALL_DEFAULT;
2501 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2502 method->name, method_encode_signature (assembly, sig));
2504 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2507 if (create_typespec) {
2508 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2509 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2510 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2512 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517 values [MONO_METHODSPEC_METHOD] = token;
2518 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2521 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2523 /*methodspec and memberef tokens are diferent, */
2524 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2531 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2533 guint32 token, parent, sig;
2534 ReflectionMethodBuilder rmb;
2536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2538 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2542 name = mono_string_to_utf8 (method->name);
2543 reflection_methodbuilder_from_method_builder (&rmb, method);
2546 * A methodref signature can't contain an unmanaged calling convention.
2547 * Since some flags are encoded as part of call_conv, we need to check against it.
2549 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2550 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2552 sig = method_builder_encode_signature (assembly, &rmb);
2554 if (tb->generic_params)
2555 parent = create_generic_typespec (assembly, tb);
2557 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2559 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2562 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2567 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2568 const gchar *name, guint32 sig)
2570 MonoDynamicTable *table;
2574 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2576 if (assembly->save) {
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2579 values [MONO_MEMBERREF_CLASS] = original;
2580 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2581 values [MONO_MEMBERREF_SIGNATURE] = sig;
2584 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2591 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2595 guint32 nparams = mono_array_length (mb->generic_params);
2598 if (!assembly->save)
2601 sigbuffer_init (&buf, 32);
2603 sigbuffer_add_value (&buf, 0xa);
2604 sigbuffer_add_value (&buf, nparams);
2606 for (i = 0; i < nparams; i++) {
2607 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2608 sigbuffer_add_value (&buf, i);
2611 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2612 sigbuffer_free (&buf);
2617 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2619 MonoDynamicTable *table;
2621 guint32 token, mtoken = 0;
2623 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2627 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2629 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2630 switch (mono_metadata_token_table (mtoken)) {
2631 case MONO_TABLE_MEMBERREF:
2632 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2634 case MONO_TABLE_METHOD:
2635 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2638 g_assert_not_reached ();
2641 if (assembly->save) {
2642 alloc_table (table, table->rows + 1);
2643 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2644 values [MONO_METHODSPEC_METHOD] = mtoken;
2645 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2648 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2651 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2656 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2660 if (mb->generic_params && create_methodspec)
2661 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2663 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2667 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2668 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2673 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2675 guint32 token, parent, sig;
2676 ReflectionMethodBuilder rmb;
2678 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2680 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2684 g_assert (tb->generic_params);
2686 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2688 parent = create_generic_typespec (assembly, tb);
2689 name = mono_string_to_utf8 (rmb.name);
2690 sig = method_builder_encode_signature (assembly, &rmb);
2692 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2695 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2701 is_field_on_inst (MonoClassField *field)
2703 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2707 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2710 get_field_on_inst_generic_type (MonoClassField *field)
2712 MonoClass *class, *gtd;
2713 MonoDynamicGenericClass *dgclass;
2716 g_assert (is_field_on_inst (field));
2718 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2720 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2721 field_index = field - dgclass->fields;
2722 return dgclass->field_generic_types [field_index];
2725 class = field->parent;
2726 gtd = class->generic_class->container_class;
2728 if (field >= class->fields && field - class->fields < class->field.count) {
2729 field_index = field - class->fields;
2730 return gtd->fields [field_index].type;
2733 g_assert_not_reached ();
2737 #ifndef DISABLE_REFLECTION_EMIT
2739 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2745 g_assert (field->parent);
2747 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2751 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2752 int index = field - field->parent->fields;
2753 type = field->parent->generic_class->container_class->fields [index].type;
2755 if (is_field_on_inst (field))
2756 type = get_field_on_inst_generic_type (field);
2760 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2761 mono_field_get_name (field),
2762 fieldref_encode_signature (assembly, field->parent->image, type));
2763 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2768 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2772 MonoGenericClass *gclass;
2773 MonoDynamicGenericClass *dgclass;
2777 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2780 if (is_sre_field_builder (mono_object_class (f->fb))) {
2781 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2782 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2783 klass = mono_class_from_mono_type (type);
2784 gclass = type->data.generic_class;
2785 g_assert (gclass->is_dynamic);
2786 dgclass = (MonoDynamicGenericClass *) gclass;
2788 name = mono_string_to_utf8 (fb->name);
2789 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2790 field_encode_signature (assembly, fb));
2792 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2794 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2796 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2797 klass = mono_class_from_mono_type (type);
2799 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2800 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2802 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2803 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2806 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2811 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2815 MonoGenericClass *gclass;
2818 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2820 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2824 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2825 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2826 MonoDynamicGenericClass *dgclass;
2827 ReflectionMethodBuilder rmb;
2830 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2831 klass = mono_class_from_mono_type (type);
2833 gclass = type->data.generic_class;
2834 g_assert (gclass->is_dynamic);
2835 dgclass = (MonoDynamicGenericClass *) gclass;
2837 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2839 name = mono_string_to_utf8 (rmb.name);
2841 sig = method_builder_encode_signature (assembly, &rmb);
2843 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2845 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2846 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2848 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2849 klass = mono_class_from_mono_type (type);
2851 sig = method_encode_signature (assembly, mono_method_signature (mm));
2852 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2854 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2855 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2859 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2864 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2867 MonoGenericContext tmp_context;
2868 MonoType **type_argv;
2869 MonoGenericInst *ginst;
2870 MonoMethod *method, *inflated;
2873 init_type_builder_generics ((MonoObject*)m->inst);
2875 method = inflate_method (m->inst, (MonoObject*)m->mb);
2877 klass = method->klass;
2879 if (m->method_args == NULL)
2882 if (method->is_inflated)
2883 method = ((MonoMethodInflated *) method)->declaring;
2885 count = mono_array_length (m->method_args);
2887 type_argv = g_new0 (MonoType *, count);
2888 for (i = 0; i < count; i++) {
2889 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2890 type_argv [i] = mono_reflection_type_get_handle (garg);
2892 ginst = mono_metadata_get_generic_inst (count, type_argv);
2895 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2896 tmp_context.method_inst = ginst;
2898 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2903 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2905 guint32 sig, token = 0;
2909 if (m->method_args) {
2910 MonoMethod *inflated;
2912 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2913 if (create_methodspec)
2914 token = mono_image_get_methodspec_token (assembly, inflated);
2916 token = mono_image_get_inflated_method_token (assembly, inflated);
2920 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2924 if (is_sre_method_builder (mono_object_class (m->mb))) {
2925 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2926 MonoGenericClass *gclass;
2927 ReflectionMethodBuilder rmb;
2930 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2931 klass = mono_class_from_mono_type (type);
2932 gclass = type->data.generic_class;
2933 g_assert (gclass->is_dynamic);
2935 reflection_methodbuilder_from_method_builder (&rmb, mb);
2937 name = mono_string_to_utf8 (rmb.name);
2939 sig = method_builder_encode_signature (assembly, &rmb);
2941 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2943 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2944 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2946 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2947 klass = mono_class_from_mono_type (type);
2949 sig = method_encode_signature (assembly, mono_method_signature (mm));
2950 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2952 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2953 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2956 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2961 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2965 guint32 nparams = context->method_inst->type_argc;
2968 if (!assembly->save)
2971 sigbuffer_init (&buf, 32);
2973 * FIXME: vararg, explicit_this, differenc call_conv values...
2975 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2976 sigbuffer_add_value (&buf, nparams);
2978 for (i = 0; i < nparams; i++)
2979 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2981 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2982 sigbuffer_free (&buf);
2987 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2989 MonoDynamicTable *table;
2991 guint32 token, mtoken = 0, sig;
2992 MonoMethodInflated *imethod;
2993 MonoMethod *declaring;
2995 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2997 g_assert (method->is_inflated);
2998 imethod = (MonoMethodInflated *) method;
2999 declaring = imethod->declaring;
3001 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3002 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3004 if (!mono_method_signature (declaring)->generic_param_count)
3007 switch (mono_metadata_token_table (mtoken)) {
3008 case MONO_TABLE_MEMBERREF:
3009 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3011 case MONO_TABLE_METHOD:
3012 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3015 g_assert_not_reached ();
3018 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3020 if (assembly->save) {
3021 alloc_table (table, table->rows + 1);
3022 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3023 values [MONO_METHODSPEC_METHOD] = mtoken;
3024 values [MONO_METHODSPEC_SIGNATURE] = sig;
3027 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3034 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3036 MonoMethodInflated *imethod;
3039 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3043 g_assert (method->is_inflated);
3044 imethod = (MonoMethodInflated *) method;
3046 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3047 token = method_encode_methodspec (assembly, method);
3049 guint32 sig = method_encode_signature (
3050 assembly, mono_method_signature (imethod->declaring));
3051 token = mono_image_get_memberref_token (
3052 assembly, &method->klass->byval_arg, method->name, sig);
3055 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3060 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3062 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3065 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3066 token = mono_image_get_memberref_token (
3067 assembly, &m->klass->byval_arg, m->name, sig);
3073 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3075 MonoDynamicTable *table;
3084 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3085 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3086 * Because of this, we must not insert it into the `typeref' hash table.
3088 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3089 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3093 sigbuffer_init (&buf, 32);
3095 g_assert (tb->generic_params);
3096 klass = mono_class_from_mono_type (type);
3098 if (tb->generic_container)
3099 mono_reflection_create_generic_class (tb);
3101 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3102 g_assert (klass->generic_container);
3103 sigbuffer_add_value (&buf, klass->byval_arg.type);
3104 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3106 count = mono_array_length (tb->generic_params);
3107 sigbuffer_add_value (&buf, count);
3108 for (i = 0; i < count; i++) {
3109 MonoReflectionGenericParam *gparam;
3111 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3113 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3116 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3118 if (assembly->save) {
3119 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3120 alloc_table (table, table->rows + 1);
3121 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3122 values [MONO_TYPESPEC_SIGNATURE] = token;
3124 sigbuffer_free (&buf);
3126 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3127 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3133 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3136 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3138 int i, count, len, pos;
3143 count += mono_array_length (modreq);
3145 count += mono_array_length (modopt);
3148 return mono_metadata_type_dup (NULL, type);
3150 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3152 memcpy (t, type, MONO_SIZEOF_TYPE);
3154 t->num_mods = count;
3157 for (i = 0; i < mono_array_length (modreq); ++i) {
3158 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3159 t->modifiers [pos].required = 1;
3160 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3165 for (i = 0; i < mono_array_length (modopt); ++i) {
3166 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3167 t->modifiers [pos].required = 0;
3168 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3177 init_type_builder_generics (MonoObject *type)
3179 MonoReflectionTypeBuilder *tb;
3181 if (!is_sre_type_builder(mono_object_class (type)))
3183 tb = (MonoReflectionTypeBuilder *)type;
3185 if (tb && tb->generic_container)
3186 mono_reflection_create_generic_class (tb);
3190 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3192 MonoDynamicTable *table;
3194 MonoType *custom = NULL, *type;
3196 guint32 token, pclass, parent, sig;
3199 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3203 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3204 name = mono_string_to_utf8 (fb->name);
3206 /*FIXME this is one more layer of ugliness due how types are created.*/
3207 init_type_builder_generics (fb->type);
3209 /* fb->type does not include the custom modifiers */
3210 /* FIXME: We should do this in one place when a fieldbuilder is created */
3211 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3212 if (fb->modreq || fb->modopt)
3213 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3215 sig = fieldref_encode_signature (assembly, NULL, type);
3218 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3219 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3221 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3222 parent >>= MONO_TYPEDEFORREF_BITS;
3224 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3226 if (assembly->save) {
3227 alloc_table (table, table->rows + 1);
3228 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3229 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3230 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3231 values [MONO_MEMBERREF_SIGNATURE] = sig;
3234 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3236 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3242 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3249 if (!assembly->save)
3252 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3253 g_assert (helper->type == 2);
3255 if (helper->arguments)
3256 nargs = mono_array_length (helper->arguments);
3260 size = 10 + (nargs * 10);
3262 sigbuffer_init (&buf, 32);
3264 /* Encode calling convention */
3265 /* Change Any to Standard */
3266 if ((helper->call_conv & 0x03) == 0x03)
3267 helper->call_conv = 0x01;
3268 /* explicit_this implies has_this */
3269 if (helper->call_conv & 0x40)
3270 helper->call_conv &= 0x20;
3272 if (helper->call_conv == 0) { /* Unmanaged */
3273 idx = helper->unmanaged_call_conv - 1;
3276 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3277 if (helper->call_conv & 0x02) /* varargs */
3281 sigbuffer_add_byte (&buf, idx);
3282 sigbuffer_add_value (&buf, nargs);
3283 encode_reflection_type (assembly, helper->return_type, &buf);
3284 for (i = 0; i < nargs; ++i) {
3285 MonoArray *modreqs = NULL;
3286 MonoArray *modopts = NULL;
3287 MonoReflectionType *pt;
3289 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3290 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3291 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3292 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3294 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3295 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3296 encode_reflection_type (assembly, pt, &buf);
3298 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3299 sigbuffer_free (&buf);
3305 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3308 MonoDynamicTable *table;
3311 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3312 idx = table->next_idx ++;
3314 alloc_table (table, table->rows);
3315 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3317 values [MONO_STAND_ALONE_SIGNATURE] =
3318 mono_reflection_encode_sighelper (assembly, helper);
3324 reflection_cc_to_file (int call_conv) {
3325 switch (call_conv & 0x3) {
3327 case 1: return MONO_CALL_DEFAULT;
3328 case 2: return MONO_CALL_VARARG;
3330 g_assert_not_reached ();
3334 #endif /* !DISABLE_REFLECTION_EMIT */
3338 MonoMethodSignature *sig;
3343 #ifndef DISABLE_REFLECTION_EMIT
3345 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3350 MonoMethodSignature *sig;
3354 name = mono_string_to_utf8 (m->name);
3355 nparams = mono_array_length (m->parameters);
3356 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3358 sig->sentinelpos = -1;
3359 sig->call_convention = reflection_cc_to_file (m->call_conv);
3360 sig->param_count = nparams;
3361 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3362 mtype = mono_reflection_type_get_handle (m->parent);
3363 for (i = 0; i < nparams; ++i)
3364 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3366 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3368 if (strcmp (name, am->name) == 0 &&
3369 mono_metadata_type_equal (am->parent, mtype) &&
3370 mono_metadata_signature_equal (am->sig, sig)) {
3373 m->table_idx = am->token & 0xffffff;
3377 am = g_new0 (ArrayMethod, 1);
3381 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3382 method_encode_signature (assembly, sig));
3383 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3384 m->table_idx = am->token & 0xffffff;
3389 * Insert into the metadata tables all the info about the TypeBuilder tb.
3390 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3393 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3395 MonoDynamicTable *table;
3397 int i, is_object = 0, is_system = 0;
3400 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3401 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3402 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3403 n = mono_string_to_utf8 (tb->name);
3404 if (strcmp (n, "Object") == 0)
3406 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3408 n = mono_string_to_utf8 (tb->nspace);
3409 if (strcmp (n, "System") == 0)
3411 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3413 if (tb->parent && !(is_system && is_object) &&
3414 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3415 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3417 values [MONO_TYPEDEF_EXTENDS] = 0;
3419 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3420 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3423 * if we have explicitlayout or sequentiallayouts, output data in the
3424 * ClassLayout table.
3426 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3427 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3428 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3430 alloc_table (table, table->rows);
3431 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3432 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3433 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3434 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3437 /* handle interfaces */
3438 if (tb->interfaces) {
3439 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3441 table->rows += mono_array_length (tb->interfaces);
3442 alloc_table (table, table->rows);
3443 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3444 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3445 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3446 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3447 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3448 values += MONO_INTERFACEIMPL_SIZE;
3454 table = &assembly->tables [MONO_TABLE_FIELD];
3455 table->rows += tb->num_fields;
3456 alloc_table (table, table->rows);
3457 for (i = 0; i < tb->num_fields; ++i)
3458 mono_image_get_field_info (
3459 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3462 /* handle constructors */
3464 table = &assembly->tables [MONO_TABLE_METHOD];
3465 table->rows += mono_array_length (tb->ctors);
3466 alloc_table (table, table->rows);
3467 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3468 mono_image_get_ctor_info (domain,
3469 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3472 /* handle methods */
3474 table = &assembly->tables [MONO_TABLE_METHOD];
3475 table->rows += tb->num_methods;
3476 alloc_table (table, table->rows);
3477 for (i = 0; i < tb->num_methods; ++i)
3478 mono_image_get_method_info (
3479 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3482 /* Do the same with properties etc.. */
3483 if (tb->events && mono_array_length (tb->events)) {
3484 table = &assembly->tables [MONO_TABLE_EVENT];
3485 table->rows += mono_array_length (tb->events);
3486 alloc_table (table, table->rows);
3487 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3489 alloc_table (table, table->rows);
3490 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3491 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3492 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3493 for (i = 0; i < mono_array_length (tb->events); ++i)
3494 mono_image_get_event_info (
3495 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3497 if (tb->properties && mono_array_length (tb->properties)) {
3498 table = &assembly->tables [MONO_TABLE_PROPERTY];
3499 table->rows += mono_array_length (tb->properties);
3500 alloc_table (table, table->rows);
3501 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3503 alloc_table (table, table->rows);
3504 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3505 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3506 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3507 for (i = 0; i < mono_array_length (tb->properties); ++i)
3508 mono_image_get_property_info (
3509 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3512 /* handle generic parameters */
3513 if (tb->generic_params) {
3514 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3515 table->rows += mono_array_length (tb->generic_params);
3516 alloc_table (table, table->rows);
3517 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3518 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3520 mono_image_get_generic_param_info (
3521 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3525 mono_image_add_decl_security (assembly,
3526 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3529 MonoDynamicTable *ntable;
3531 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3532 ntable->rows += mono_array_length (tb->subtypes);
3533 alloc_table (ntable, ntable->rows);
3534 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3536 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3537 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3539 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3540 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3541 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3542 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3543 mono_string_to_utf8 (tb->name), tb->table_idx,
3544 ntable->next_idx, ntable->rows);*/
3545 values += MONO_NESTED_CLASS_SIZE;
3553 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3557 mono_ptr_array_append (*types, type);
3559 if (!type->subtypes)
3562 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3563 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3564 collect_types (types, subtype);
3569 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3571 if ((*type1)->table_idx < (*type2)->table_idx)
3574 if ((*type1)->table_idx > (*type2)->table_idx)
3581 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3586 for (i = 0; i < mono_array_length (pinfo); ++i) {
3587 MonoReflectionParamBuilder *pb;
3588 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3591 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3596 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3599 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3601 for (i = 0; i < tb->num_fields; ++i) {
3602 MonoReflectionFieldBuilder* fb;
3603 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3604 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3608 for (i = 0; i < mono_array_length (tb->events); ++i) {
3609 MonoReflectionEventBuilder* eb;
3610 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3611 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3614 if (tb->properties) {
3615 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3616 MonoReflectionPropertyBuilder* pb;
3617 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3618 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3622 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3623 MonoReflectionCtorBuilder* cb;
3624 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3625 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3626 params_add_cattrs (assembly, cb->pinfo);
3631 for (i = 0; i < tb->num_methods; ++i) {
3632 MonoReflectionMethodBuilder* mb;
3633 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3634 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3635 params_add_cattrs (assembly, mb->pinfo);
3640 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3641 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3646 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3650 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3652 if (moduleb->global_methods) {
3653 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3654 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3655 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3656 params_add_cattrs (assembly, mb->pinfo);
3660 if (moduleb->global_fields) {
3661 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3662 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3663 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3667 if (moduleb->types) {
3668 for (i = 0; i < moduleb->num_types; ++i)
3669 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3674 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3676 MonoDynamicTable *table;
3680 char *b = blob_size;
3683 table = &assembly->tables [MONO_TABLE_FILE];
3685 alloc_table (table, table->rows);
3686 values = table->values + table->next_idx * MONO_FILE_SIZE;
3687 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3688 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3689 if (module->image->dynamic) {
3690 /* This depends on the fact that the main module is emitted last */
3691 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3692 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3695 path = g_strdup (module->image->name);
3697 mono_sha1_get_digest_from_file (path, hash);
3700 mono_metadata_encode_value (20, b, &b);
3701 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3702 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3707 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3709 MonoDynamicTable *table;
3712 table = &assembly->tables [MONO_TABLE_MODULE];
3713 mb->table_idx = table->next_idx ++;
3714 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3715 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3718 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3719 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3720 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3721 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3725 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3726 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3728 MonoDynamicTable *table;
3732 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3733 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3736 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3738 alloc_table (table, table->rows);
3739 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3741 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3742 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3743 if (klass->nested_in)
3744 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3746 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3747 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3748 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3750 res = table->next_idx;
3754 /* Emit nested types */
3755 if (klass->ext && klass->ext->nested_classes) {
3758 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3759 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3766 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3767 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3772 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3774 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3776 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3777 parent_index, assembly);
3781 * We need to do this ourselves since klass->nested_classes is not set up.
3784 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3785 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3790 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3791 guint32 module_index, MonoDynamicImage *assembly)
3793 MonoImage *image = module->image;
3797 t = &image->tables [MONO_TABLE_TYPEDEF];
3799 for (i = 0; i < t->rows; ++i) {
3800 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3802 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3803 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3808 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3810 MonoDynamicTable *table;
3812 guint32 scope, scope_idx, impl, current_idx;
3813 gboolean forwarder = TRUE;
3814 gpointer iter = NULL;
3817 if (klass->nested_in) {
3818 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3821 scope = resolution_scope_from_image (assembly, klass->image);
3822 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3823 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3824 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3827 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3830 alloc_table (table, table->rows);
3831 current_idx = table->next_idx;
3832 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3834 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3835 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3836 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3837 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3838 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3842 while ((nested = mono_class_get_nested_types (klass, &iter)))
3843 add_exported_type (assemblyb, assembly, nested, current_idx);
3847 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3852 if (!assemblyb->type_forwarders)
3855 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3856 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3861 type = mono_reflection_type_get_handle (t);
3864 klass = mono_class_from_mono_type (type);
3866 add_exported_type (assemblyb, assembly, klass, 0);
3870 #define align_pointer(base,p)\
3872 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3874 (p) += 4 - (__diff & 3);\
3878 compare_constants (const void *a, const void *b)
3880 const guint32 *a_values = a;
3881 const guint32 *b_values = b;
3882 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3886 compare_semantics (const void *a, const void *b)
3888 const guint32 *a_values = a;
3889 const guint32 *b_values = b;
3890 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3893 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3897 compare_custom_attrs (const void *a, const void *b)
3899 const guint32 *a_values = a;
3900 const guint32 *b_values = b;
3902 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3906 compare_field_marshal (const void *a, const void *b)
3908 const guint32 *a_values = a;
3909 const guint32 *b_values = b;
3911 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3915 compare_nested (const void *a, const void *b)
3917 const guint32 *a_values = a;
3918 const guint32 *b_values = b;
3920 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3924 compare_genericparam (const void *a, const void *b)
3926 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3927 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3929 if ((*b_entry)->owner == (*a_entry)->owner)
3931 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3932 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3934 return (*a_entry)->owner - (*b_entry)->owner;
3938 compare_declsecurity_attrs (const void *a, const void *b)
3940 const guint32 *a_values = a;
3941 const guint32 *b_values = b;
3943 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3947 compare_interface_impl (const void *a, const void *b)
3949 const guint32 *a_values = a;
3950 const guint32 *b_values = b;
3952 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3956 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3960 pad_heap (MonoDynamicStream *sh)
3962 if (sh->index & 3) {
3963 int sz = 4 - (sh->index & 3);
3964 memset (sh->data + sh->index, 0, sz);
3971 MonoDynamicStream *stream;
3975 * build_compressed_metadata() fills in the blob of data that represents the
3976 * raw metadata as it will be saved in the PE file. The five streams are output
3977 * and the metadata tables are comnpressed from the guint32 array representation,
3978 * to the compressed on-disk format.
3981 build_compressed_metadata (MonoDynamicImage *assembly)
3983 MonoDynamicTable *table;
3985 guint64 valid_mask = 0;
3986 guint64 sorted_mask;
3987 guint32 heapt_size = 0;
3988 guint32 meta_size = 256; /* allow for header and other stuff */
3989 guint32 table_offset;
3990 guint32 ntables = 0;
3996 struct StreamDesc stream_desc [5];
3998 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3999 for (i = 0; i < assembly->gen_params->len; i++){
4000 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4001 write_generic_param_entry (assembly, entry);
4004 stream_desc [0].name = "#~";
4005 stream_desc [0].stream = &assembly->tstream;
4006 stream_desc [1].name = "#Strings";
4007 stream_desc [1].stream = &assembly->sheap;
4008 stream_desc [2].name = "#US";
4009 stream_desc [2].stream = &assembly->us;
4010 stream_desc [3].name = "#Blob";
4011 stream_desc [3].stream = &assembly->blob;
4012 stream_desc [4].name = "#GUID";
4013 stream_desc [4].stream = &assembly->guid;
4015 /* tables that are sorted */
4016 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4017 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4018 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4019 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4020 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4021 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4022 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4024 /* Compute table sizes */
4025 /* the MonoImage has already been created in mono_image_basic_init() */
4026 meta = &assembly->image;
4028 /* sizes should be multiple of 4 */
4029 pad_heap (&assembly->blob);
4030 pad_heap (&assembly->guid);
4031 pad_heap (&assembly->sheap);
4032 pad_heap (&assembly->us);
4034 /* Setup the info used by compute_sizes () */
4035 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4036 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4037 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4039 meta_size += assembly->blob.index;
4040 meta_size += assembly->guid.index;
4041 meta_size += assembly->sheap.index;
4042 meta_size += assembly->us.index;
4044 for (i=0; i < MONO_TABLE_NUM; ++i)
4045 meta->tables [i].rows = assembly->tables [i].rows;
4047 for (i = 0; i < MONO_TABLE_NUM; i++){
4048 if (meta->tables [i].rows == 0)
4050 valid_mask |= (guint64)1 << i;
4052 meta->tables [i].row_size = mono_metadata_compute_size (
4053 meta, i, &meta->tables [i].size_bitfield);
4054 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4056 heapt_size += 24; /* #~ header size */
4057 heapt_size += ntables * 4;
4058 /* make multiple of 4 */
4061 meta_size += heapt_size;
4062 meta->raw_metadata = g_malloc0 (meta_size);
4063 p = (unsigned char*)meta->raw_metadata;
4064 /* the metadata signature */
4065 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4066 /* version numbers and 4 bytes reserved */
4067 int16val = (guint16*)p;
4068 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4069 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4071 /* version string */
4072 int32val = (guint32*)p;
4073 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4075 memcpy (p, meta->version, strlen (meta->version));
4076 p += GUINT32_FROM_LE (*int32val);
4077 align_pointer (meta->raw_metadata, p);
4078 int16val = (guint16*)p;
4079 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4080 *int16val = GUINT16_TO_LE (5); /* number of streams */
4084 * write the stream info.
4086 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4087 table_offset += 3; table_offset &= ~3;
4089 assembly->tstream.index = heapt_size;
4090 for (i = 0; i < 5; ++i) {
4091 int32val = (guint32*)p;
4092 stream_desc [i].stream->offset = table_offset;
4093 *int32val++ = GUINT32_TO_LE (table_offset);
4094 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4095 table_offset += GUINT32_FROM_LE (*int32val);
4096 table_offset += 3; table_offset &= ~3;
4098 strcpy ((char*)p, stream_desc [i].name);
4099 p += strlen (stream_desc [i].name) + 1;
4100 align_pointer (meta->raw_metadata, p);
4103 * now copy the data, the table stream header and contents goes first.
4105 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4106 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4107 int32val = (guint32*)p;
4108 *int32val = GUINT32_TO_LE (0); /* reserved */
4111 *p++ = 2; /* version */
4114 if (meta->idx_string_wide)
4116 if (meta->idx_guid_wide)
4118 if (meta->idx_blob_wide)
4121 *p++ = 1; /* reserved */
4122 int64val = (guint64*)p;
4123 *int64val++ = GUINT64_TO_LE (valid_mask);
4124 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4126 int32val = (guint32*)p;
4127 for (i = 0; i < MONO_TABLE_NUM; i++){
4128 if (meta->tables [i].rows == 0)
4130 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4132 p = (unsigned char*)int32val;
4134 /* sort the tables that still need sorting */
4135 table = &assembly->tables [MONO_TABLE_CONSTANT];
4137 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4138 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4140 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4141 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4143 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4144 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4146 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4147 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4149 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4150 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4151 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4153 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4154 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4156 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4158 /* compress the tables */
4159 for (i = 0; i < MONO_TABLE_NUM; i++){
4162 guint32 bitfield = meta->tables [i].size_bitfield;
4163 if (!meta->tables [i].rows)
4165 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4166 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4167 meta->tables [i].base = (char*)p;
4168 for (row = 1; row <= meta->tables [i].rows; ++row) {
4169 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4170 for (col = 0; col < assembly->tables [i].columns; ++col) {
4171 switch (mono_metadata_table_size (bitfield, col)) {
4173 *p++ = values [col];
4176 *p++ = values [col] & 0xff;
4177 *p++ = (values [col] >> 8) & 0xff;
4180 *p++ = values [col] & 0xff;
4181 *p++ = (values [col] >> 8) & 0xff;
4182 *p++ = (values [col] >> 16) & 0xff;
4183 *p++ = (values [col] >> 24) & 0xff;
4186 g_assert_not_reached ();
4190 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4193 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4194 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4195 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4196 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4197 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4199 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4203 * Some tables in metadata need to be sorted according to some criteria, but
4204 * when methods and fields are first created with reflection, they may be assigned a token
4205 * that doesn't correspond to the final token they will get assigned after the sorting.
4206 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4207 * with the reflection objects that represent them. Once all the tables are set up, the
4208 * reflection objects will contains the correct table index. fixup_method() will fixup the
4209 * tokens for the method with ILGenerator @ilgen.
4212 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4214 guint32 code_idx = GPOINTER_TO_UINT (value);
4215 MonoReflectionILTokenInfo *iltoken;
4216 MonoReflectionFieldBuilder *field;
4217 MonoReflectionCtorBuilder *ctor;
4218 MonoReflectionMethodBuilder *method;
4219 MonoReflectionTypeBuilder *tb;
4220 MonoReflectionArrayMethod *am;
4222 unsigned char *target;
4224 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4225 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4226 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4227 switch (target [3]) {
4228 case MONO_TABLE_FIELD:
4229 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4230 field = (MonoReflectionFieldBuilder *)iltoken->member;
4231 idx = field->table_idx;
4232 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4233 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4234 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4236 g_assert_not_reached ();
4239 case MONO_TABLE_METHOD:
4240 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4241 method = (MonoReflectionMethodBuilder *)iltoken->member;
4242 idx = method->table_idx;
4243 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4244 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4245 idx = ctor->table_idx;
4246 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4247 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4248 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4249 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4251 g_assert_not_reached ();
4254 case MONO_TABLE_TYPEDEF:
4255 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4256 g_assert_not_reached ();
4257 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4258 idx = tb->table_idx;
4260 case MONO_TABLE_MEMBERREF:
4261 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4262 am = (MonoReflectionArrayMethod*)iltoken->member;
4263 idx = am->table_idx;
4264 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4265 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4266 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4267 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4268 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4269 g_assert (m->klass->generic_class || m->klass->generic_container);
4271 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4273 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4274 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4275 g_assert (is_field_on_inst (f));
4277 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4278 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4280 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4282 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4284 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4287 g_assert_not_reached ();
4290 case MONO_TABLE_METHODSPEC:
4291 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4292 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4293 g_assert (mono_method_signature (m)->generic_param_count);
4295 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4297 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4300 g_assert_not_reached ();
4304 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4306 target [0] = idx & 0xff;
4307 target [1] = (idx >> 8) & 0xff;
4308 target [2] = (idx >> 16) & 0xff;
4315 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4316 * value is not known when the table is emitted.
4319 fixup_cattrs (MonoDynamicImage *assembly)
4321 MonoDynamicTable *table;
4323 guint32 type, i, idx, token;
4326 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4328 for (i = 0; i < table->rows; ++i) {
4329 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4331 type = values [MONO_CUSTOM_ATTR_TYPE];
4332 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4333 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4334 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4335 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4338 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4339 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4340 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4341 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4348 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4350 MonoDynamicTable *table;
4353 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4355 alloc_table (table, table->rows);
4356 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4357 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4358 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4359 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4360 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4365 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4367 MonoDynamicTable *table;
4371 char *b = blob_size;
4373 guint32 idx, offset;
4375 if (rsrc->filename) {
4376 name = mono_string_to_utf8 (rsrc->filename);
4377 sname = g_path_get_basename (name);
4379 table = &assembly->tables [MONO_TABLE_FILE];
4381 alloc_table (table, table->rows);
4382 values = table->values + table->next_idx * MONO_FILE_SIZE;
4383 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4384 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4387 mono_sha1_get_digest_from_file (name, hash);
4388 mono_metadata_encode_value (20, b, &b);
4389 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4390 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4392 idx = table->next_idx++;
4394 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4400 data = mono_array_addr (rsrc->data, char, 0);
4401 len = mono_array_length (rsrc->data);
4407 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4408 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4409 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4410 mono_image_add_stream_data (&assembly->resources, data, len);
4414 * The entry should be emitted into the MANIFESTRESOURCE table of
4415 * the main module, but that needs to reference the FILE table
4416 * which isn't emitted yet.
4423 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4427 set_version_from_string (MonoString *version, guint32 *values)
4429 gchar *ver, *p, *str;
4432 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4433 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4434 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4435 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4438 ver = str = mono_string_to_utf8 (version);
4439 for (i = 0; i < 4; ++i) {
4440 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4446 /* handle Revision and Build */
4456 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4460 char *b = blob_size;
4465 len = mono_array_length (pkey);
4466 mono_metadata_encode_value (len, b, &b);
4467 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4468 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4470 assembly->public_key = g_malloc (len);
4471 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4472 assembly->public_key_len = len;
4474 /* Special case: check for ECMA key (16 bytes) */
4475 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4476 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4477 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4478 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4479 /* minimum key size (in 2.0) is 384 bits */
4480 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4482 /* FIXME - verifier */
4483 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4484 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4486 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4492 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4494 MonoDynamicTable *table;
4495 MonoDynamicImage *assembly;
4496 MonoReflectionAssemblyBuilder *assemblyb;
4500 guint32 module_index;
4502 assemblyb = moduleb->assemblyb;
4503 assembly = moduleb->dynamic_image;
4504 domain = mono_object_domain (assemblyb);
4506 /* Emit ASSEMBLY table */
4507 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4508 alloc_table (table, 1);
4509 values = table->values + MONO_ASSEMBLY_SIZE;
4510 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4511 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4512 if (assemblyb->culture) {
4513 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4515 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4517 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4518 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4519 set_version_from_string (assemblyb->version, values);
4521 /* Emit FILE + EXPORTED_TYPE table */
4523 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4525 MonoReflectionModuleBuilder *file_module =
4526 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4527 if (file_module != moduleb) {
4528 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4530 if (file_module->types) {
4531 for (j = 0; j < file_module->num_types; ++j) {
4532 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4533 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4538 if (assemblyb->loaded_modules) {
4539 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4540 MonoReflectionModule *file_module =
4541 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4542 mono_image_fill_file_table (domain, file_module, assembly);
4544 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4547 if (assemblyb->type_forwarders)
4548 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4550 /* Emit MANIFESTRESOURCE table */
4552 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4554 MonoReflectionModuleBuilder *file_module =
4555 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4556 /* The table for the main module is emitted later */
4557 if (file_module != moduleb) {
4559 if (file_module->resources) {
4560 int len = mono_array_length (file_module->resources);
4561 for (j = 0; j < len; ++j) {
4562 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4563 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4570 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4573 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4574 * for the modulebuilder @moduleb.
4575 * At the end of the process, method and field tokens are fixed up and the
4576 * on-disk compressed metadata representation is created.
4579 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4581 MonoDynamicTable *table;
4582 MonoDynamicImage *assembly;
4583 MonoReflectionAssemblyBuilder *assemblyb;
4589 assemblyb = moduleb->assemblyb;
4590 assembly = moduleb->dynamic_image;
4591 domain = mono_object_domain (assemblyb);
4593 if (assembly->text_rva)
4596 assembly->text_rva = START_TEXT_RVA;
4598 if (moduleb->is_main) {
4599 mono_image_emit_manifest (moduleb);
4602 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4603 table->rows = 1; /* .<Module> */
4605 alloc_table (table, table->rows);
4607 * Set the first entry.
4609 values = table->values + table->columns;
4610 values [MONO_TYPEDEF_FLAGS] = 0;
4611 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4612 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4613 values [MONO_TYPEDEF_EXTENDS] = 0;
4614 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4615 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4618 * handle global methods
4619 * FIXME: test what to do when global methods are defined in multiple modules.
4621 if (moduleb->global_methods) {
4622 table = &assembly->tables [MONO_TABLE_METHOD];
4623 table->rows += mono_array_length (moduleb->global_methods);
4624 alloc_table (table, table->rows);
4625 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4626 mono_image_get_method_info (
4627 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4629 if (moduleb->global_fields) {
4630 table = &assembly->tables [MONO_TABLE_FIELD];
4631 table->rows += mono_array_length (moduleb->global_fields);
4632 alloc_table (table, table->rows);
4633 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4634 mono_image_get_field_info (
4635 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4638 table = &assembly->tables [MONO_TABLE_MODULE];
4639 alloc_table (table, 1);
4640 mono_image_fill_module_table (domain, moduleb, assembly);
4642 /* Collect all types into a list sorted by their table_idx */
4643 mono_ptr_array_init (types, moduleb->num_types);
4646 for (i = 0; i < moduleb->num_types; ++i) {
4647 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4648 collect_types (&types, type);
4651 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4652 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4653 table->rows += mono_ptr_array_size (types);
4654 alloc_table (table, table->rows);
4657 * Emit type names + namespaces at one place inside the string heap,
4658 * so load_class_names () needs to touch fewer pages.
4660 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4661 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4662 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4664 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4665 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4666 string_heap_insert_mstring (&assembly->sheap, tb->name);
4669 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4671 mono_image_get_type_info (domain, type, assembly);
4675 * table->rows is already set above and in mono_image_fill_module_table.
4677 /* add all the custom attributes at the end, once all the indexes are stable */
4678 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4680 /* CAS assembly permissions */
4681 if (assemblyb->permissions_minimum)
4682 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4683 if (assemblyb->permissions_optional)
4684 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4685 if (assemblyb->permissions_refused)
4686 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4688 module_add_cattrs (assembly, moduleb);
4691 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4693 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4694 * the final tokens and don't need another fixup pass. */
4696 if (moduleb->global_methods) {
4697 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4698 MonoReflectionMethodBuilder *mb = mono_array_get (
4699 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4700 mono_image_add_methodimpl (assembly, mb);
4704 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4705 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4706 if (type->methods) {
4707 for (j = 0; j < type->num_methods; ++j) {
4708 MonoReflectionMethodBuilder *mb = mono_array_get (
4709 type->methods, MonoReflectionMethodBuilder*, j);
4711 mono_image_add_methodimpl (assembly, mb);
4716 mono_ptr_array_destroy (types);
4718 fixup_cattrs (assembly);
4721 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4724 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4726 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4729 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4733 guint32 import_lookup_table;
4737 guint32 import_address_table_rva;
4745 #ifndef DISABLE_REFLECTION_EMIT
4748 * mono_image_insert_string:
4749 * @module: module builder object
4752 * Insert @str into the user string stream of @module.
4755 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4757 MonoDynamicImage *assembly;
4762 MONO_ARCH_SAVE_REGS;
4764 if (!module->dynamic_image)
4765 mono_image_module_basic_init (module);
4767 assembly = module->dynamic_image;
4769 if (assembly->save) {
4770 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4771 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4772 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4774 char *swapped = g_malloc (2 * mono_string_length (str));
4775 const char *p = (const char*)mono_string_chars (str);
4777 swap_with_size (swapped, p, 2, mono_string_length (str));
4778 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4782 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4784 mono_image_add_stream_data (&assembly->us, "", 1);
4786 idx = assembly->us.index ++;
4789 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4791 return MONO_TOKEN_STRING | idx;
4795 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4799 MonoMethodSignature *sig;
4801 klass = obj->vtable->klass;
4802 if (strcmp (klass->name, "MonoMethod") == 0) {
4803 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4804 MonoMethodSignature *old;
4805 guint32 sig_token, parent;
4808 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4810 nargs = mono_array_length (opt_param_types);
4811 old = mono_method_signature (method);
4812 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4814 sig->hasthis = old->hasthis;
4815 sig->explicit_this = old->explicit_this;
4816 sig->call_convention = old->call_convention;
4817 sig->generic_param_count = old->generic_param_count;
4818 sig->param_count = old->param_count + nargs;
4819 sig->sentinelpos = old->param_count;
4820 sig->ret = old->ret;
4822 for (i = 0; i < old->param_count; i++)
4823 sig->params [i] = old->params [i];
4825 for (i = 0; i < nargs; i++) {
4826 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4827 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4830 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4831 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4832 parent >>= MONO_TYPEDEFORREF_BITS;
4834 parent <<= MONO_MEMBERREF_PARENT_BITS;
4835 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4837 sig_token = method_encode_signature (assembly, sig);
4838 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4839 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4840 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4841 ReflectionMethodBuilder rmb;
4842 guint32 parent, sig_token;
4843 int nopt_args, nparams, ngparams, i;
4846 reflection_methodbuilder_from_method_builder (&rmb, mb);
4847 rmb.opt_types = opt_param_types;
4848 nopt_args = mono_array_length (opt_param_types);
4850 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4851 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4852 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4854 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4855 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4856 sig->call_convention = rmb.call_conv;
4857 sig->generic_param_count = ngparams;
4858 sig->param_count = nparams + nopt_args;
4859 sig->sentinelpos = nparams;
4860 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4862 for (i = 0; i < nparams; i++) {
4863 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4864 sig->params [i] = mono_reflection_type_get_handle (rt);
4867 for (i = 0; i < nopt_args; i++) {
4868 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4869 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4872 sig_token = method_builder_encode_signature (assembly, &rmb);
4874 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4875 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4877 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4878 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4880 name = mono_string_to_utf8 (rmb.name);
4881 token = mono_image_get_varargs_method_token (
4882 assembly, parent, name, sig_token);
4885 g_error ("requested method token for %s\n", klass->name);
4888 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4889 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4894 * mono_image_create_token:
4895 * @assembly: a dynamic assembly
4897 * @register_token: Whenever to register the token in the assembly->tokens hash.
4899 * Get a token to insert in the IL code stream for the given MemberInfo.
4900 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4901 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4905 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4906 gboolean create_open_instance, gboolean register_token)
4911 klass = obj->vtable->klass;
4913 /* Check for user defined reflection objects */
4914 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4915 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4916 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4918 if (strcmp (klass->name, "MethodBuilder") == 0) {
4919 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4920 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4922 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4923 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4925 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4926 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4927 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4928 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4929 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4931 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4932 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4934 token = mono_image_get_ctorbuilder_token (assembly, mb);
4935 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4936 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4937 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4938 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4939 if (tb->generic_params) {
4940 token = mono_image_get_generic_field_token (assembly, fb);
4942 if ((tb->module->dynamic_image == assembly)) {
4943 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4945 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4948 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4949 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4950 if (create_open_instance && tb->generic_params) {
4952 init_type_builder_generics (obj);
4953 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4954 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4955 token = mono_metadata_token_from_dor (token);
4957 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4959 } else if (strcmp (klass->name, "MonoType") == 0) {
4960 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4961 MonoClass *mc = mono_class_from_mono_type (type);
4962 if (!mono_class_init (mc))
4963 mono_raise_exception (mono_class_get_exception_for_failure (mc));
4965 token = mono_metadata_token_from_dor (
4966 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4967 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4968 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4969 token = mono_metadata_token_from_dor (
4970 mono_image_typedef_or_ref (assembly, type));
4971 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4972 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4973 token = mono_metadata_token_from_dor (
4974 mono_image_typedef_or_ref (assembly, type));
4975 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4976 strcmp (klass->name, "MonoMethod") == 0 ||
4977 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4978 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4979 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4980 if (m->method->is_inflated) {
4981 if (create_open_instance)
4982 token = mono_image_get_methodspec_token (assembly, m->method);
4984 token = mono_image_get_inflated_method_token (assembly, m->method);
4985 } else if ((m->method->klass->image == &assembly->image) &&
4986 !m->method->klass->generic_class) {
4987 static guint32 method_table_idx = 0xffffff;
4988 if (m->method->klass->wastypebuilder) {
4989 /* we use the same token as the one that was assigned
4990 * to the Methodbuilder.
4991 * FIXME: do the equivalent for Fields.
4993 token = m->method->token;
4996 * Each token should have a unique index, but the indexes are
4997 * assigned by managed code, so we don't know about them. An
4998 * easy solution is to count backwards...
5000 method_table_idx --;
5001 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5004 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5006 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5007 } else if (strcmp (klass->name, "MonoField") == 0) {
5008 MonoReflectionField *f = (MonoReflectionField *)obj;
5009 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5010 static guint32 field_table_idx = 0xffffff;
5012 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5014 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5016 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5017 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5018 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5019 token = mono_image_get_array_token (assembly, m);
5020 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5021 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5022 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5023 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5024 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5025 token = mono_metadata_token_from_dor (
5026 mono_image_typedef_or_ref (assembly, type));
5027 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5028 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5029 token = mono_image_get_field_on_inst_token (assembly, f);
5030 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5031 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5032 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5033 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5034 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5035 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5036 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5037 MonoReflectionType *type = (MonoReflectionType *)obj;
5038 token = mono_metadata_token_from_dor (
5039 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5041 g_error ("requested token for %s\n", klass->name);
5045 mono_image_register_token (assembly, token, obj);
5051 * mono_image_register_token:
5053 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5054 * the Module.ResolveXXXToken () methods to work.
5057 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5059 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5061 /* There could be multiple MethodInfo objects with the same token */
5062 //g_assert (prev == obj);
5064 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5068 static MonoDynamicImage*
5069 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5071 static const guchar entrycode [16] = {0xff, 0x25, 0};
5072 MonoDynamicImage *image;
5075 const char *version;
5077 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5078 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5080 version = mono_get_runtime_info ()->runtime_version;
5083 /* The MonoGHashTable's need GC tracking */
5084 image = GC_MALLOC (sizeof (MonoDynamicImage));
5086 image = g_new0 (MonoDynamicImage, 1);
5089 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5091 /*g_print ("created image %p\n", image);*/
5092 /* keep in sync with image.c */
5093 image->image.name = assembly_name;
5094 image->image.assembly_name = image->image.name; /* they may be different */
5095 image->image.module_name = module_name;
5096 image->image.version = g_strdup (version);
5097 image->image.md_version_major = 1;
5098 image->image.md_version_minor = 1;
5099 image->image.dynamic = TRUE;
5101 image->image.references = g_new0 (MonoAssembly*, 1);
5102 image->image.references [0] = NULL;
5104 mono_image_init (&image->image);
5106 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5107 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5108 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5109 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5110 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5111 image->handleref = g_hash_table_new (NULL, NULL);
5112 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5113 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5114 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5115 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5116 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5117 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5118 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5119 image->gen_params = g_ptr_array_new ();
5121 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5122 string_heap_init (&image->sheap);
5123 mono_image_add_stream_data (&image->us, "", 1);
5124 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5125 /* import tables... */
5126 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5127 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5128 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5129 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5130 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5131 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5132 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5133 stream_data_align (&image->code);
5135 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5137 for (i=0; i < MONO_TABLE_NUM; ++i) {
5138 image->tables [i].next_idx = 1;
5139 image->tables [i].columns = table_sizes [i];
5142 image->image.assembly = (MonoAssembly*)assembly;
5143 image->run = assembly->run;
5144 image->save = assembly->save;
5145 image->pe_kind = 0x1; /* ILOnly */
5146 image->machine = 0x14c; /* I386 */
5148 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5155 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5161 mono_dynamic_image_free (MonoDynamicImage *image)
5163 MonoDynamicImage *di = image;
5168 mono_g_hash_table_destroy (di->methodspec);
5170 g_hash_table_destroy (di->typespec);
5172 g_hash_table_destroy (di->typeref);
5174 g_hash_table_destroy (di->handleref);
5175 if (di->handleref_managed)
5176 mono_g_hash_table_destroy (di->handleref_managed);
5178 mono_g_hash_table_destroy (di->tokens);
5179 if (di->generic_def_objects)
5180 mono_g_hash_table_destroy (di->generic_def_objects);
5181 if (di->blob_cache) {
5182 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5183 g_hash_table_destroy (di->blob_cache);
5185 if (di->standalonesig_cache)
5186 g_hash_table_destroy (di->standalonesig_cache);
5187 for (list = di->array_methods; list; list = list->next) {
5188 ArrayMethod *am = (ArrayMethod *)list->data;
5193 g_list_free (di->array_methods);
5194 if (di->gen_params) {
5195 for (i = 0; i < di->gen_params->len; i++) {
5196 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5197 if (entry->gparam->type.type) {
5198 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5199 g_free ((char*)mono_generic_param_info (param)->name);
5202 mono_gc_deregister_root ((char*) &entry->gparam);
5205 g_ptr_array_free (di->gen_params, TRUE);
5207 if (di->token_fixups)
5208 mono_g_hash_table_destroy (di->token_fixups);
5209 if (di->method_to_table_idx)
5210 g_hash_table_destroy (di->method_to_table_idx);
5211 if (di->field_to_table_idx)
5212 g_hash_table_destroy (di->field_to_table_idx);
5213 if (di->method_aux_hash)
5214 g_hash_table_destroy (di->method_aux_hash);
5215 if (di->vararg_aux_hash)
5216 g_hash_table_destroy (di->vararg_aux_hash);
5217 g_free (di->strong_name);
5218 g_free (di->win32_res);
5220 g_free (di->public_key);
5222 /*g_print ("string heap destroy for image %p\n", di);*/
5223 mono_dynamic_stream_reset (&di->sheap);
5224 mono_dynamic_stream_reset (&di->code);
5225 mono_dynamic_stream_reset (&di->resources);
5226 mono_dynamic_stream_reset (&di->us);
5227 mono_dynamic_stream_reset (&di->blob);
5228 mono_dynamic_stream_reset (&di->tstream);
5229 mono_dynamic_stream_reset (&di->guid);
5230 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5231 g_free (di->tables [i].values);
5235 #ifndef DISABLE_REFLECTION_EMIT
5238 * mono_image_basic_init:
5239 * @assembly: an assembly builder object
5241 * Create the MonoImage that represents the assembly builder and setup some
5242 * of the helper hash table and the basic metadata streams.
5245 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5247 MonoDynamicAssembly *assembly;
5248 MonoDynamicImage *image;
5249 MonoDomain *domain = mono_object_domain (assemblyb);
5251 MONO_ARCH_SAVE_REGS;
5253 if (assemblyb->dynamic_assembly)
5257 /* assembly->assembly.image might be GC allocated */
5258 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5260 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5263 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5265 assembly->assembly.ref_count = 1;
5266 assembly->assembly.dynamic = TRUE;
5267 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5268 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5269 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5270 if (assemblyb->culture)
5271 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5273 assembly->assembly.aname.culture = g_strdup ("");
5275 if (assemblyb->version) {
5276 char *vstr = mono_string_to_utf8 (assemblyb->version);
5277 char **version = g_strsplit (vstr, ".", 4);
5278 char **parts = version;
5279 assembly->assembly.aname.major = atoi (*parts++);
5280 assembly->assembly.aname.minor = atoi (*parts++);
5281 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5282 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5284 g_strfreev (version);
5287 assembly->assembly.aname.major = 0;
5288 assembly->assembly.aname.minor = 0;
5289 assembly->assembly.aname.build = 0;
5290 assembly->assembly.aname.revision = 0;
5293 assembly->run = assemblyb->access != 2;
5294 assembly->save = assemblyb->access != 1;
5295 assembly->domain = domain;
5297 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5298 image->initial_image = TRUE;
5299 assembly->assembly.aname.name = image->image.name;
5300 assembly->assembly.image = &image->image;
5301 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5302 /* -1 to correct for the trailing NULL byte */
5303 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5304 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5306 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5309 mono_domain_assemblies_lock (domain);
5310 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5311 mono_domain_assemblies_unlock (domain);
5313 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5315 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5317 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5320 #endif /* !DISABLE_REFLECTION_EMIT */
5322 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5325 calc_section_size (MonoDynamicImage *assembly)
5329 /* alignment constraints */
5330 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5331 g_assert ((assembly->code.index % 4) == 0);
5332 assembly->meta_size += 3;
5333 assembly->meta_size &= ~3;
5334 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5335 g_assert ((assembly->resources.index % 4) == 0);
5337 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5338 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5341 if (assembly->win32_res) {
5342 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5344 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5345 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5349 assembly->sections [MONO_SECTION_RELOC].size = 12;
5350 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5360 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5364 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5366 ResTreeNode *t1 = (ResTreeNode*)a;
5367 ResTreeNode *t2 = (ResTreeNode*)b;
5369 return t1->id - t2->id;
5373 * resource_tree_create:
5375 * Organize the resources into a resource tree.
5377 static ResTreeNode *
5378 resource_tree_create (MonoArray *win32_resources)
5380 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5384 tree = g_new0 (ResTreeNode, 1);
5386 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5387 MonoReflectionWin32Resource *win32_res =
5388 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5392 /* FIXME: BUG: this stores managed references in unmanaged memory */
5393 lang_node = g_new0 (ResTreeNode, 1);
5394 lang_node->id = win32_res->lang_id;
5395 lang_node->win32_res = win32_res;
5397 /* Create type node if neccesary */
5399 for (l = tree->children; l; l = l->next)
5400 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5401 type_node = (ResTreeNode*)l->data;
5406 type_node = g_new0 (ResTreeNode, 1);
5407 type_node->id = win32_res->res_type;
5410 * The resource types have to be sorted otherwise
5411 * Windows Explorer can't display the version information.
5413 tree->children = g_slist_insert_sorted (tree->children,
5414 type_node, resource_tree_compare_by_id);
5417 /* Create res node if neccesary */
5419 for (l = type_node->children; l; l = l->next)
5420 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5421 res_node = (ResTreeNode*)l->data;
5426 res_node = g_new0 (ResTreeNode, 1);
5427 res_node->id = win32_res->res_id;
5428 type_node->children = g_slist_append (type_node->children, res_node);
5431 res_node->children = g_slist_append (res_node->children, lang_node);
5438 * resource_tree_encode:
5440 * Encode the resource tree into the format used in the PE file.
5443 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5446 MonoPEResourceDir dir;
5447 MonoPEResourceDirEntry dir_entry;
5448 MonoPEResourceDataEntry data_entry;
5450 guint32 res_id_entries;
5453 * For the format of the resource directory, see the article
5454 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5458 memset (&dir, 0, sizeof (dir));
5459 memset (&dir_entry, 0, sizeof (dir_entry));
5460 memset (&data_entry, 0, sizeof (data_entry));
5462 g_assert (sizeof (dir) == 16);
5463 g_assert (sizeof (dir_entry) == 8);
5464 g_assert (sizeof (data_entry) == 16);
5466 node->offset = p - begin;
5468 /* IMAGE_RESOURCE_DIRECTORY */
5469 res_id_entries = g_slist_length (node->children);
5470 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5472 memcpy (p, &dir, sizeof (dir));
5475 /* Reserve space for entries */
5477 p += sizeof (dir_entry) * res_id_entries;
5479 /* Write children */
5480 for (l = node->children; l; l = l->next) {
5481 ResTreeNode *child = (ResTreeNode*)l->data;
5483 if (child->win32_res) {
5486 child->offset = p - begin;
5488 /* IMAGE_RESOURCE_DATA_ENTRY */
5489 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5490 size = mono_array_length (child->win32_res->res_data);
5491 data_entry.rde_size = GUINT32_TO_LE (size);
5493 memcpy (p, &data_entry, sizeof (data_entry));
5494 p += sizeof (data_entry);
5496 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5499 resource_tree_encode (child, begin, p, &p);
5503 /* IMAGE_RESOURCE_ENTRY */
5504 for (l = node->children; l; l = l->next) {
5505 ResTreeNode *child = (ResTreeNode*)l->data;
5507 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5508 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5510 memcpy (entries, &dir_entry, sizeof (dir_entry));
5511 entries += sizeof (dir_entry);
5518 resource_tree_free (ResTreeNode * node)
5521 for (list = node->children; list; list = list->next)
5522 resource_tree_free ((ResTreeNode*)list->data);
5523 g_slist_free(node->children);
5528 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5533 MonoReflectionWin32Resource *win32_res;
5536 if (!assemblyb->win32_resources)
5540 * Resources are stored in a three level tree inside the PE file.
5541 * - level one contains a node for each type of resource
5542 * - level two contains a node for each resource
5543 * - level three contains a node for each instance of a resource for a
5544 * specific language.
5547 tree = resource_tree_create (assemblyb->win32_resources);
5549 /* Estimate the size of the encoded tree */
5551 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5552 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5553 size += mono_array_length (win32_res->res_data);
5555 /* Directory structure */
5556 size += mono_array_length (assemblyb->win32_resources) * 256;
5557 p = buf = g_malloc (size);
5559 resource_tree_encode (tree, p, p, &p);
5561 g_assert (p - buf <= size);
5563 assembly->win32_res = g_malloc (p - buf);
5564 assembly->win32_res_size = p - buf;
5565 memcpy (assembly->win32_res, buf, p - buf);
5568 resource_tree_free (tree);
5572 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5574 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5577 p += sizeof (MonoPEResourceDir);
5578 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5579 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5580 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5581 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5582 fixup_resource_directory (res_section, child, rva);
5584 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5585 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5588 p += sizeof (MonoPEResourceDirEntry);
5593 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5596 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5597 g_error ("WriteFile returned %d\n", GetLastError ());
5601 * mono_image_create_pefile:
5602 * @mb: a module builder object
5604 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5605 * assembly->pefile where it can be easily retrieved later in chunks.
5608 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5610 MonoMSDOSHeader *msdos;
5611 MonoDotNetHeader *header;
5612 MonoSectionTable *section;
5613 MonoCLIHeader *cli_header;
5614 guint32 size, image_size, virtual_base, text_offset;
5615 guint32 header_start, section_start, file_offset, virtual_offset;
5616 MonoDynamicImage *assembly;
5617 MonoReflectionAssemblyBuilder *assemblyb;
5618 MonoDynamicStream pefile_stream = {0};
5619 MonoDynamicStream *pefile = &pefile_stream;
5621 guint32 *rva, value;
5623 static const unsigned char msheader[] = {
5624 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5625 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5628 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5629 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5630 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5631 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5634 assemblyb = mb->assemblyb;
5636 mono_image_basic_init (assemblyb);
5637 assembly = mb->dynamic_image;
5639 assembly->pe_kind = assemblyb->pe_kind;
5640 assembly->machine = assemblyb->machine;
5641 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5642 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5644 mono_image_build_metadata (mb);
5646 if (mb->is_main && assemblyb->resources) {
5647 int len = mono_array_length (assemblyb->resources);
5648 for (i = 0; i < len; ++i)
5649 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5652 if (mb->resources) {
5653 int len = mono_array_length (mb->resources);
5654 for (i = 0; i < len; ++i)
5655 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5658 build_compressed_metadata (assembly);
5661 assembly_add_win32_resources (assembly, assemblyb);
5663 nsections = calc_section_size (assembly);
5665 /* The DOS header and stub */
5666 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5667 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5669 /* the dotnet header */
5670 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5672 /* the section tables */
5673 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5675 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5676 virtual_offset = VIRT_ALIGN;
5679 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5680 if (!assembly->sections [i].size)
5683 file_offset += FILE_ALIGN - 1;
5684 file_offset &= ~(FILE_ALIGN - 1);
5685 virtual_offset += VIRT_ALIGN - 1;
5686 virtual_offset &= ~(VIRT_ALIGN - 1);
5688 assembly->sections [i].offset = file_offset;
5689 assembly->sections [i].rva = virtual_offset;
5691 file_offset += assembly->sections [i].size;
5692 virtual_offset += assembly->sections [i].size;
5693 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5696 file_offset += FILE_ALIGN - 1;
5697 file_offset &= ~(FILE_ALIGN - 1);
5699 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5701 /* back-patch info */
5702 msdos = (MonoMSDOSHeader*)pefile->data;
5703 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5705 header = (MonoDotNetHeader*)(pefile->data + header_start);
5706 header->pesig [0] = 'P';
5707 header->pesig [1] = 'E';
5709 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5710 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5711 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5712 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5713 if (assemblyb->pekind == 1) {
5715 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5718 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5721 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5723 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5724 header->pe.pe_major = 6;
5725 header->pe.pe_minor = 0;
5726 size = assembly->sections [MONO_SECTION_TEXT].size;
5727 size += FILE_ALIGN - 1;
5728 size &= ~(FILE_ALIGN - 1);
5729 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5730 size = assembly->sections [MONO_SECTION_RSRC].size;
5731 size += FILE_ALIGN - 1;
5732 size &= ~(FILE_ALIGN - 1);
5733 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5734 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5735 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5736 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5737 /* pe_rva_entry_point always at the beginning of the text section */
5738 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5740 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5741 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5742 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5743 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5744 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5745 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5746 size = section_start;
5747 size += FILE_ALIGN - 1;
5748 size &= ~(FILE_ALIGN - 1);
5749 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5751 size += VIRT_ALIGN - 1;
5752 size &= ~(VIRT_ALIGN - 1);
5753 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5756 // Translate the PEFileKind value to the value expected by the Windows loader
5762 // PEFileKinds.Dll == 1
5763 // PEFileKinds.ConsoleApplication == 2
5764 // PEFileKinds.WindowApplication == 3
5767 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5768 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5770 if (assemblyb->pekind == 3)
5775 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5777 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5778 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5779 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5780 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5781 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5782 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5784 /* fill data directory entries */
5786 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5787 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5789 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5790 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5792 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5793 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5794 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5795 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5796 /* patch entrypoint name */
5797 if (assemblyb->pekind == 1)
5798 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5800 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5801 /* patch imported function RVA name */
5802 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5803 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5805 /* the import table */
5806 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5807 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5808 /* patch imported dll RVA name and other entries in the dir */
5809 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5810 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5811 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5812 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5813 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5814 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5816 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5817 value = (assembly->text_rva + assembly->imp_names_offset);
5818 *p++ = (value) & 0xff;
5819 *p++ = (value >> 8) & (0xff);
5820 *p++ = (value >> 16) & (0xff);
5821 *p++ = (value >> 24) & (0xff);
5823 /* the CLI header info */
5824 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5825 cli_header->ch_size = GUINT32_FROM_LE (72);
5826 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5827 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5828 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5829 if (assemblyb->entry_point) {
5830 guint32 table_idx = 0;
5831 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5832 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5833 table_idx = methodb->table_idx;
5835 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5837 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5839 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5841 /* The embedded managed resources */
5842 text_offset = assembly->text_rva + assembly->code.index;
5843 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5844 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5845 text_offset += assembly->resources.index;
5846 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5847 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5848 text_offset += assembly->meta_size;
5849 if (assembly->strong_name_size) {
5850 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5851 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5852 text_offset += assembly->strong_name_size;
5855 /* write the section tables and section content */
5856 section = (MonoSectionTable*)(pefile->data + section_start);
5857 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5858 static const char section_names [][7] = {
5859 ".text", ".rsrc", ".reloc"
5861 if (!assembly->sections [i].size)
5863 strcpy (section->st_name, section_names [i]);
5864 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5865 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5866 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5867 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5868 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5869 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5870 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5874 checked_write_file (file, pefile->data, pefile->index);
5876 mono_dynamic_stream_reset (pefile);
5878 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5879 if (!assembly->sections [i].size)
5882 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5883 g_error ("SetFilePointer returned %d\n", GetLastError ());
5886 case MONO_SECTION_TEXT:
5887 /* patch entry point */
5888 p = (guchar*)(assembly->code.data + 2);
5889 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5890 *p++ = (value) & 0xff;
5891 *p++ = (value >> 8) & 0xff;
5892 *p++ = (value >> 16) & 0xff;
5893 *p++ = (value >> 24) & 0xff;
5895 checked_write_file (file, assembly->code.data, assembly->code.index);
5896 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5897 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5898 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5901 g_free (assembly->image.raw_metadata);
5903 case MONO_SECTION_RELOC: {
5907 guint16 type_and_offset;
5911 g_assert (sizeof (reloc) == 12);
5913 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5914 reloc.block_size = GUINT32_FROM_LE (12);
5917 * the entrypoint is always at the start of the text section
5918 * 3 is IMAGE_REL_BASED_HIGHLOW
5919 * 2 is patch_size_rva - text_rva
5921 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5924 checked_write_file (file, &reloc, sizeof (reloc));
5928 case MONO_SECTION_RSRC:
5929 if (assembly->win32_res) {
5931 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5932 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5933 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5937 g_assert_not_reached ();
5941 /* check that the file is properly padded */
5942 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5943 g_error ("SetFilePointer returned %d\n", GetLastError ());
5944 if (! SetEndOfFile (file))
5945 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5947 mono_dynamic_stream_reset (&assembly->code);
5948 mono_dynamic_stream_reset (&assembly->us);
5949 mono_dynamic_stream_reset (&assembly->blob);
5950 mono_dynamic_stream_reset (&assembly->guid);
5951 mono_dynamic_stream_reset (&assembly->sheap);
5953 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5954 g_hash_table_destroy (assembly->blob_cache);
5955 assembly->blob_cache = NULL;
5958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5961 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5963 g_assert_not_reached ();
5966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5968 #ifndef DISABLE_REFLECTION_EMIT
5970 MonoReflectionModule *
5971 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5975 MonoImageOpenStatus status;
5976 MonoDynamicAssembly *assembly;
5977 guint32 module_count;
5978 MonoImage **new_modules;
5979 gboolean *new_modules_loaded;
5981 name = mono_string_to_utf8 (fileName);
5983 image = mono_image_open (name, &status);
5986 if (status == MONO_IMAGE_ERROR_ERRNO)
5987 exc = mono_get_exception_file_not_found (fileName);
5989 exc = mono_get_exception_bad_image_format (name);
5991 mono_raise_exception (exc);
5996 assembly = ab->dynamic_assembly;
5997 image->assembly = (MonoAssembly*)assembly;
5999 module_count = image->assembly->image->module_count;
6000 new_modules = g_new0 (MonoImage *, module_count + 1);
6001 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6003 if (image->assembly->image->modules)
6004 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6005 if (image->assembly->image->modules_loaded)
6006 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6007 new_modules [module_count] = image;
6008 new_modules_loaded [module_count] = TRUE;
6009 mono_image_addref (image);
6011 g_free (image->assembly->image->modules);
6012 image->assembly->image->modules = new_modules;
6013 image->assembly->image->modules_loaded = new_modules_loaded;
6014 image->assembly->image->module_count ++;
6016 mono_assembly_load_references (image, &status);
6018 mono_image_close (image);
6019 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6022 return mono_module_get_object (mono_domain_get (), image);
6025 #endif /* DISABLE_REFLECTION_EMIT */
6028 * We need to return always the same object for MethodInfo, FieldInfo etc..
6029 * but we need to consider the reflected type.
6030 * type uses a different hash, since it uses custom hash/equal functions.
6035 MonoClass *refclass;
6039 reflected_equal (gconstpointer a, gconstpointer b) {
6040 const ReflectedEntry *ea = a;
6041 const ReflectedEntry *eb = b;
6043 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6047 reflected_hash (gconstpointer a) {
6048 const ReflectedEntry *ea = a;
6049 return mono_aligned_addr_hash (ea->item);
6052 #define CHECK_OBJECT(t,p,k) \
6058 mono_domain_lock (domain); \
6059 if (!domain->refobject_hash) \
6060 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6061 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6062 mono_domain_unlock (domain); \
6065 mono_domain_unlock (domain); \
6068 #ifdef HAVE_BOEHM_GC
6069 /* ReflectedEntry doesn't need to be GC tracked */
6070 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6071 #define FREE_REFENTRY(entry) g_free ((entry))
6072 #define REFENTRY_REQUIRES_CLEANUP
6074 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6076 #define FREE_REFENTRY(entry)
6079 #define CACHE_OBJECT(t,p,o,k) \
6082 ReflectedEntry pe; \
6084 pe.refclass = (k); \
6085 mono_domain_lock (domain); \
6086 if (!domain->refobject_hash) \
6087 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6088 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6090 ReflectedEntry *e = ALLOC_REFENTRY; \
6092 e->refclass = (k); \
6093 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6096 mono_domain_unlock (domain); \
6101 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6103 mono_domain_lock (domain);
6104 if (domain->refobject_hash) {
6106 gpointer orig_pe, orig_value;
6109 pe.refclass = klass;
6110 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6111 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6112 FREE_REFENTRY (orig_pe);
6115 mono_domain_unlock (domain);
6118 #ifdef REFENTRY_REQUIRES_CLEANUP
6120 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6122 FREE_REFENTRY (key);
6127 mono_reflection_cleanup_domain (MonoDomain *domain)
6129 if (domain->refobject_hash) {
6130 /*let's avoid scanning the whole hashtable if not needed*/
6131 #ifdef REFENTRY_REQUIRES_CLEANUP
6132 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6134 mono_g_hash_table_destroy (domain->refobject_hash);
6135 domain->refobject_hash = NULL;
6139 #ifndef DISABLE_REFLECTION_EMIT
6141 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6143 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6147 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6149 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6153 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6155 MonoDynamicImage *image = moduleb->dynamic_image;
6156 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6160 MonoImage **new_modules;
6162 char *name, *fqname;
6164 * FIXME: we already created an image in mono_image_basic_init (), but
6165 * we don't know which module it belongs to, since that is only
6166 * determined at assembly save time.
6168 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6169 name = mono_string_to_utf8 (ab->name);
6170 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6171 if (!mono_error_ok (&error)) {
6173 mono_error_raise_exception (&error);
6175 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6177 moduleb->module.image = &image->image;
6178 moduleb->dynamic_image = image;
6179 register_module (mono_object_domain (moduleb), moduleb, image);
6181 /* register the module with the assembly */
6182 ass = ab->dynamic_assembly->assembly.image;
6183 module_count = ass->module_count;
6184 new_modules = g_new0 (MonoImage *, module_count + 1);
6187 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6188 new_modules [module_count] = &image->image;
6189 mono_image_addref (&image->image);
6191 g_free (ass->modules);
6192 ass->modules = new_modules;
6193 ass->module_count ++;
6198 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6200 MonoDynamicImage *image = moduleb->dynamic_image;
6202 g_assert (type->type);
6203 image->wrappers_type = mono_class_from_mono_type (type->type);
6209 * mono_assembly_get_object:
6210 * @domain: an app domain
6211 * @assembly: an assembly
6213 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6215 MonoReflectionAssembly*
6216 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6218 static MonoClass *assembly_type;
6219 MonoReflectionAssembly *res;
6221 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6222 if (!assembly_type) {
6223 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6225 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6227 assembly_type = class;
6229 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6230 res->assembly = assembly;
6232 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6237 MonoReflectionModule*
6238 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6240 static MonoClass *module_type;
6241 MonoReflectionModule *res;
6244 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6246 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6248 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6250 module_type = class;
6252 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6255 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6257 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6258 basename = g_path_get_basename (image->name);
6259 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6260 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6264 if (image->assembly->image == image) {
6265 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6269 if (image->assembly->image->modules) {
6270 for (i = 0; i < image->assembly->image->module_count; i++) {
6271 if (image->assembly->image->modules [i] == image)
6272 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6274 g_assert (res->token);
6278 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6281 MonoReflectionModule*
6282 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6284 static MonoClass *module_type;
6285 MonoReflectionModule *res;
6286 MonoTableInfo *table;
6287 guint32 cols [MONO_FILE_SIZE];
6289 guint32 i, name_idx;
6293 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6295 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6297 module_type = class;
6299 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6301 table = &image->tables [MONO_TABLE_FILE];
6302 g_assert (table_index < table->rows);
6303 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6306 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6307 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6309 /* Check whenever the row has a corresponding row in the moduleref table */
6310 table = &image->tables [MONO_TABLE_MODULEREF];
6311 for (i = 0; i < table->rows; ++i) {
6312 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6313 val = mono_metadata_string_heap (image, name_idx);
6314 if (strcmp (val, name) == 0)
6315 res->image = image->modules [i];
6318 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6319 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6320 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6321 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6322 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6328 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6330 if ((t1->type != t2->type) ||
6331 (t1->byref != t2->byref))
6335 case MONO_TYPE_VOID:
6336 case MONO_TYPE_BOOLEAN:
6337 case MONO_TYPE_CHAR:
6348 case MONO_TYPE_STRING:
6351 case MONO_TYPE_OBJECT:
6352 case MONO_TYPE_TYPEDBYREF:
6354 case MONO_TYPE_VALUETYPE:
6355 case MONO_TYPE_CLASS:
6356 case MONO_TYPE_SZARRAY:
6357 return t1->data.klass == t2->data.klass;
6359 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6360 case MONO_TYPE_ARRAY:
6361 if (t1->data.array->rank != t2->data.array->rank)
6363 return t1->data.array->eklass == t2->data.array->eklass;
6364 case MONO_TYPE_GENERICINST: {
6366 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6367 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6368 if (i1->type_argc != i2->type_argc)
6370 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6371 &t2->data.generic_class->container_class->byval_arg))
6373 /* FIXME: we should probably just compare the instance pointers directly. */
6374 for (i = 0; i < i1->type_argc; ++i) {
6375 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6381 case MONO_TYPE_MVAR:
6382 return t1->data.generic_param == t2->data.generic_param;
6384 g_error ("implement type compare for %0x!", t1->type);
6392 mymono_metadata_type_hash (MonoType *t1)
6398 hash |= t1->byref << 6; /* do not collide with t1->type values */
6400 case MONO_TYPE_VALUETYPE:
6401 case MONO_TYPE_CLASS:
6402 case MONO_TYPE_SZARRAY:
6403 /* check if the distribution is good enough */
6404 return ((hash << 5) - hash) ^ mono_aligned_addr_hash (t1->data.klass);
6406 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6407 case MONO_TYPE_GENERICINST: {
6409 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6410 hash += g_str_hash (t1->data.generic_class->container_class->name);
6412 for (i = 0; i < inst->type_argc; ++i) {
6413 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6419 case MONO_TYPE_MVAR:
6420 return ((hash << 5) - hash) ^ GPOINTER_TO_UINT (t1->data.generic_param);
6426 verify_safe_for_managed_space (MonoType *type)
6428 switch (type->type) {
6430 case MONO_TYPE_ARRAY:
6431 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6433 return verify_safe_for_managed_space (type->data.type);
6434 case MONO_TYPE_SZARRAY:
6435 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6436 case MONO_TYPE_GENERICINST: {
6437 MonoGenericInst *inst = type->data.generic_class->inst;
6441 for (i = 0; i < inst->type_argc; ++i)
6442 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6448 case MONO_TYPE_MVAR:
6455 mono_type_normalize (MonoType *type)
6458 MonoGenericClass *gclass;
6459 MonoGenericInst *ginst;
6461 MonoGenericContainer *gcontainer;
6462 MonoType **argv = NULL;
6463 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6465 if (type->type != MONO_TYPE_GENERICINST)
6468 gclass = type->data.generic_class;
6469 ginst = gclass->context.class_inst;
6470 if (!ginst->is_open)
6473 gtd = gclass->container_class;
6474 gcontainer = gtd->generic_container;
6475 argv = g_newa (MonoType*, ginst->type_argc);
6477 for (i = 0; i < ginst->type_argc; ++i) {
6478 MonoType *t = ginst->type_argv [i], *norm;
6479 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6480 is_denorm_gtd = FALSE;
6481 norm = mono_type_normalize (t);
6484 requires_rebind = TRUE;
6488 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6490 if (requires_rebind) {
6491 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6492 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6498 * mono_type_get_object:
6499 * @domain: an app domain
6502 * Return an System.MonoType object representing the type @type.
6505 mono_type_get_object (MonoDomain *domain, MonoType *type)
6507 MonoType *norm_type;
6508 MonoReflectionType *res;
6509 MonoClass *klass = mono_class_from_mono_type (type);
6511 /*we must avoid using @type as it might have come
6512 * from a mono_metadata_type_dup and the caller
6513 * expects that is can be freed.
6514 * Using the right type from
6516 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6518 /* void is very common */
6519 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6520 return (MonoReflectionType*)domain->typeof_void;
6523 * If the vtable of the given class was already created, we can use
6524 * the MonoType from there and avoid all locking and hash table lookups.
6526 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6527 * that the resulting object is different.
6529 if (type == &klass->byval_arg && !klass->image->dynamic) {
6530 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6531 if (vtable && vtable->type)
6532 return vtable->type;
6535 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6536 mono_domain_lock (domain);
6537 if (!domain->type_hash)
6538 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6539 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6540 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6541 mono_domain_unlock (domain);
6542 mono_loader_unlock ();
6546 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6547 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6548 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6549 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6550 * artifact of how generics are encoded and should be transparent to managed code so we
6551 * need to weed out this diference when retrieving managed System.Type objects.
6553 norm_type = mono_type_normalize (type);
6554 if (norm_type != type) {
6555 res = mono_type_get_object (domain, norm_type);
6556 mono_g_hash_table_insert (domain->type_hash, type, res);
6557 mono_domain_unlock (domain);
6558 mono_loader_unlock ();
6562 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6563 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6566 if (!verify_safe_for_managed_space (type)) {
6567 mono_domain_unlock (domain);
6568 mono_loader_unlock ();
6569 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6572 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6573 gboolean is_type_done = TRUE;
6574 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6575 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6576 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6578 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6579 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6581 if (gparam->owner && gparam->owner->is_method) {
6582 MonoMethod *method = gparam->owner->owner.method;
6583 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6584 is_type_done = FALSE;
6585 } else if (gparam->owner && !gparam->owner->is_method) {
6586 MonoClass *klass = gparam->owner->owner.klass;
6587 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6588 is_type_done = FALSE;
6592 /* g_assert_not_reached (); */
6593 /* should this be considered an error condition? */
6594 if (is_type_done && !type->byref) {
6595 mono_domain_unlock (domain);
6596 mono_loader_unlock ();
6597 return mono_class_get_ref_info (klass);
6601 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6603 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6606 mono_g_hash_table_insert (domain->type_hash, type, res);
6608 if (type->type == MONO_TYPE_VOID)
6609 domain->typeof_void = (MonoObject*)res;
6611 mono_domain_unlock (domain);
6612 mono_loader_unlock ();
6617 * mono_method_get_object:
6618 * @domain: an app domain
6620 * @refclass: the reflected type (can be NULL)
6622 * Return an System.Reflection.MonoMethod object representing the method @method.
6624 MonoReflectionMethod*
6625 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6628 * We use the same C representation for methods and constructors, but the type
6629 * name in C# is different.
6631 static MonoClass *System_Reflection_MonoMethod = NULL;
6632 static MonoClass *System_Reflection_MonoCMethod = NULL;
6633 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6634 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6636 MonoReflectionMethod *ret;
6638 if (method->is_inflated) {
6639 MonoReflectionGenericMethod *gret;
6641 refclass = method->klass;
6642 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6643 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6644 if (!System_Reflection_MonoGenericCMethod)
6645 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6646 klass = System_Reflection_MonoGenericCMethod;
6648 if (!System_Reflection_MonoGenericMethod)
6649 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6650 klass = System_Reflection_MonoGenericMethod;
6652 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6653 gret->method.method = method;
6654 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6655 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6656 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6660 refclass = method->klass;
6662 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6663 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6664 if (!System_Reflection_MonoCMethod)
6665 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6666 klass = System_Reflection_MonoCMethod;
6669 if (!System_Reflection_MonoMethod)
6670 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6671 klass = System_Reflection_MonoMethod;
6673 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6674 ret->method = method;
6675 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6676 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6680 * mono_method_clear_object:
6682 * Clear the cached reflection objects for the dynamic method METHOD.
6685 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6688 g_assert (method->dynamic);
6690 klass = method->klass;
6692 clear_cached_object (domain, method, klass);
6693 klass = klass->parent;
6695 /* Added by mono_param_get_objects () */
6696 clear_cached_object (domain, &(method->signature), NULL);
6697 klass = method->klass;
6699 clear_cached_object (domain, &(method->signature), klass);
6700 klass = klass->parent;
6705 * mono_field_get_object:
6706 * @domain: an app domain
6710 * Return an System.Reflection.MonoField object representing the field @field
6713 MonoReflectionField*
6714 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6716 MonoReflectionField *res;
6717 static MonoClass *monofield_klass;
6719 CHECK_OBJECT (MonoReflectionField *, field, klass);
6720 if (!monofield_klass)
6721 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6722 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6725 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6727 if (is_field_on_inst (field)) {
6728 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6729 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6732 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6733 res->attrs = mono_field_get_flags (field);
6735 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6739 * mono_property_get_object:
6740 * @domain: an app domain
6742 * @property: a property
6744 * Return an System.Reflection.MonoProperty object representing the property @property
6747 MonoReflectionProperty*
6748 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6750 MonoReflectionProperty *res;
6751 static MonoClass *monoproperty_klass;
6753 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6754 if (!monoproperty_klass)
6755 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6756 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6758 res->property = property;
6759 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6763 * mono_event_get_object:
6764 * @domain: an app domain
6768 * Return an System.Reflection.MonoEvent object representing the event @event
6771 MonoReflectionEvent*
6772 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6774 MonoReflectionEvent *res;
6775 MonoReflectionMonoEvent *mono_event;
6776 static MonoClass *monoevent_klass;
6778 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6779 if (!monoevent_klass)
6780 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6781 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6782 mono_event->klass = klass;
6783 mono_event->event = event;
6784 res = (MonoReflectionEvent*)mono_event;
6785 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6789 * mono_get_reflection_missing_object:
6790 * @domain: Domain where the object lives
6792 * Returns the System.Reflection.Missing.Value singleton object
6793 * (of type System.Reflection.Missing).
6795 * Used as the value for ParameterInfo.DefaultValue when Optional
6799 mono_get_reflection_missing_object (MonoDomain *domain)
6802 static MonoClassField *missing_value_field = NULL;
6804 if (!missing_value_field) {
6805 MonoClass *missing_klass;
6806 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6807 mono_class_init (missing_klass);
6808 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6809 g_assert (missing_value_field);
6811 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6817 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6820 *dbnull = mono_get_dbnull_object (domain);
6825 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6827 if (!*reflection_missing)
6828 *reflection_missing = mono_get_reflection_missing_object (domain);
6829 return *reflection_missing;
6833 * mono_param_get_objects:
6834 * @domain: an app domain
6837 * Return an System.Reflection.ParameterInfo array object representing the parameters
6838 * in the method @method.
6841 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6843 static MonoClass *System_Reflection_ParameterInfo;
6844 static MonoClass *System_Reflection_ParameterInfo_array;
6846 MonoArray *res = NULL;
6847 MonoReflectionMethod *member = NULL;
6848 MonoReflectionParameter *param = NULL;
6849 char **names, **blobs = NULL;
6850 guint32 *types = NULL;
6851 MonoType *type = NULL;
6852 MonoObject *dbnull = NULL;
6853 MonoObject *missing = NULL;
6854 MonoMarshalSpec **mspecs;
6855 MonoMethodSignature *sig;
6856 MonoVTable *pinfo_vtable;
6859 if (!System_Reflection_ParameterInfo_array) {
6862 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6863 mono_memory_barrier ();
6864 System_Reflection_ParameterInfo = klass;
6866 klass = mono_array_class_get (klass, 1);
6867 mono_memory_barrier ();
6868 System_Reflection_ParameterInfo_array = klass;
6871 sig = mono_method_signature_checked (method, &error);
6872 if (!mono_error_ok (&error))
6873 mono_error_raise_exception (&error);
6875 if (!sig->param_count)
6876 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6878 /* Note: the cache is based on the address of the signature into the method
6879 * since we already cache MethodInfos with the method as keys.
6881 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6883 member = mono_method_get_object (domain, method, refclass);
6884 names = g_new (char *, sig->param_count);
6885 mono_method_get_param_names (method, (const char **) names);
6887 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6888 mono_method_get_marshal_info (method, mspecs);
6890 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6891 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6892 for (i = 0; i < sig->param_count; ++i) {
6893 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6894 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6895 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6896 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6897 param->PositionImpl = i;
6898 param->AttrsImpl = sig->params [i]->attrs;
6900 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6901 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6902 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6904 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6908 blobs = g_new0 (char *, sig->param_count);
6909 types = g_new0 (guint32, sig->param_count);
6910 get_default_param_value_blobs (method, blobs, types);
6913 /* Build MonoType for the type from the Constant Table */
6915 type = g_new0 (MonoType, 1);
6916 type->type = types [i];
6917 type->data.klass = NULL;
6918 if (types [i] == MONO_TYPE_CLASS)
6919 type->data.klass = mono_defaults.object_class;
6920 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6921 /* For enums, types [i] contains the base type */
6923 type->type = MONO_TYPE_VALUETYPE;
6924 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6926 type->data.klass = mono_class_from_mono_type (type);
6928 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6930 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6931 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6932 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6933 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6935 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6941 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6943 mono_array_setref (res, i, param);
6950 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6952 mono_metadata_free_marshal_spec (mspecs [i]);
6955 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6959 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6961 return mono_param_get_objects_internal (domain, method, NULL);
6965 * mono_method_body_get_object:
6966 * @domain: an app domain
6969 * Return an System.Reflection.MethodBody object representing the method @method.
6971 MonoReflectionMethodBody*
6972 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6974 static MonoClass *System_Reflection_MethodBody = NULL;
6975 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6976 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6977 MonoReflectionMethodBody *ret;
6978 MonoMethodHeader *header;
6980 guint32 method_rva, local_var_sig_token;
6982 unsigned char format, flags;
6985 if (!System_Reflection_MethodBody)
6986 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6987 if (!System_Reflection_LocalVariableInfo)
6988 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6989 if (!System_Reflection_ExceptionHandlingClause)
6990 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6992 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6994 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6995 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6996 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6997 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7000 image = method->klass->image;
7001 header = mono_method_get_header (method);
7003 if (!image->dynamic) {
7004 /* Obtain local vars signature token */
7005 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7006 ptr = mono_image_rva_map (image, method_rva);
7007 flags = *(const unsigned char *) ptr;
7008 format = flags & METHOD_HEADER_FORMAT_MASK;
7010 case METHOD_HEADER_TINY_FORMAT:
7011 local_var_sig_token = 0;
7013 case METHOD_HEADER_FAT_FORMAT:
7017 local_var_sig_token = read32 (ptr);
7020 g_assert_not_reached ();
7023 local_var_sig_token = 0; //FIXME
7025 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7027 ret->init_locals = header->init_locals;
7028 ret->max_stack = header->max_stack;
7029 ret->local_var_sig_token = local_var_sig_token;
7030 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7031 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7034 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7035 for (i = 0; i < header->num_locals; ++i) {
7036 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7037 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7038 info->is_pinned = header->locals [i]->pinned;
7039 info->local_index = i;
7040 mono_array_setref (ret->locals, i, info);
7044 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7045 for (i = 0; i < header->num_clauses; ++i) {
7046 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7047 MonoExceptionClause *clause = &header->clauses [i];
7049 info->flags = clause->flags;
7050 info->try_offset = clause->try_offset;
7051 info->try_length = clause->try_len;
7052 info->handler_offset = clause->handler_offset;
7053 info->handler_length = clause->handler_len;
7054 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7055 info->filter_offset = clause->data.filter_offset;
7056 else if (clause->data.catch_class)
7057 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7059 mono_array_setref (ret->clauses, i, info);
7062 mono_metadata_free_mh (header);
7063 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7068 * mono_get_dbnull_object:
7069 * @domain: Domain where the object lives
7071 * Returns the System.DBNull.Value singleton object
7073 * Used as the value for ParameterInfo.DefaultValue
7076 mono_get_dbnull_object (MonoDomain *domain)
7079 static MonoClassField *dbnull_value_field = NULL;
7081 if (!dbnull_value_field) {
7082 MonoClass *dbnull_klass;
7083 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7084 mono_class_init (dbnull_klass);
7085 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7086 g_assert (dbnull_value_field);
7088 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7094 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7096 guint32 param_index, i, lastp, crow = 0;
7097 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7100 MonoClass *klass = method->klass;
7101 MonoImage *image = klass->image;
7102 MonoMethodSignature *methodsig = mono_method_signature (method);
7104 MonoTableInfo *constt;
7105 MonoTableInfo *methodt;
7106 MonoTableInfo *paramt;
7108 if (!methodsig->param_count)
7111 mono_class_init (klass);
7113 if (klass->image->dynamic) {
7114 MonoReflectionMethodAux *aux;
7115 if (method->is_inflated)
7116 method = ((MonoMethodInflated*)method)->declaring;
7117 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7118 if (aux && aux->param_defaults) {
7119 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7120 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7125 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7126 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7127 constt = &image->tables [MONO_TABLE_CONSTANT];
7129 idx = mono_method_get_index (method) - 1;
7130 g_assert (idx != -1);
7132 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7133 if (idx + 1 < methodt->rows)
7134 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7136 lastp = paramt->rows + 1;
7138 for (i = param_index; i < lastp; ++i) {
7141 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7142 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7144 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7147 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7152 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7153 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7154 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7161 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7166 MonoType *basetype = type;
7171 klass = mono_class_from_mono_type (type);
7172 if (klass->valuetype) {
7173 object = mono_object_new (domain, klass);
7174 retval = ((gchar *) object + sizeof (MonoObject));
7175 if (klass->enumtype)
7176 basetype = mono_class_enum_basetype (klass);
7181 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7188 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7191 gboolean quoted = FALSE;
7193 memset (assembly, 0, sizeof (MonoAssemblyName));
7194 assembly->culture = "";
7195 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7202 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7213 /* Remove trailing whitespace */
7215 while (*s && g_ascii_isspace (*s))
7218 while (g_ascii_isspace (*p))
7221 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7223 assembly->major = strtoul (p, &s, 10);
7224 if (s == p || *s != '.')
7227 assembly->minor = strtoul (p, &s, 10);
7228 if (s == p || *s != '.')
7231 assembly->build = strtoul (p, &s, 10);
7232 if (s == p || *s != '.')
7235 assembly->revision = strtoul (p, &s, 10);
7239 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7241 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7242 assembly->culture = "";
7245 assembly->culture = p;
7246 while (*p && *p != ',') {
7250 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7252 if (strncmp (p, "null", 4) == 0) {
7257 while (*p && *p != ',') {
7260 len = (p - start + 1);
7261 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7262 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7263 g_strlcpy ((char*)assembly->public_key_token, start, len);
7266 while (*p && *p != ',')
7270 while (g_ascii_isspace (*p) || *p == ',') {
7284 * mono_reflection_parse_type:
7287 * Parse a type name as accepted by the GetType () method and output the info
7288 * extracted in the info structure.
7289 * the name param will be mangled, so, make a copy before passing it to this function.
7290 * The fields in info will be valid until the memory pointed to by name is valid.
7292 * See also mono_type_get_name () below.
7294 * Returns: 0 on parse error.
7297 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7298 MonoTypeNameParse *info)
7300 char *start, *p, *w, *temp, *last_point, *startn;
7301 int in_modifiers = 0;
7302 int isbyref = 0, rank, arity = 0, i;
7304 start = p = w = name;
7306 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7307 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7308 info->name = info->name_space = NULL;
7309 info->nested = NULL;
7310 info->modifiers = NULL;
7311 info->type_arguments = NULL;
7313 /* last_point separates the namespace from the name */
7316 while (*p == ' ') p++, start++, w++, name++;
7321 *p = 0; /* NULL terminate the name */
7323 info->nested = g_list_append (info->nested, startn);
7324 /* we have parsed the nesting namespace + name */
7328 info->name_space = start;
7330 info->name = last_point + 1;
7332 info->name_space = (char *)"";
7351 i = strtol (p, &temp, 10);
7368 info->name_space = start;
7370 info->name = last_point + 1;
7372 info->name_space = (char *)"";
7379 if (isbyref) /* only one level allowed by the spec */
7382 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7386 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7392 info->type_arguments = g_ptr_array_new ();
7393 for (i = 0; i < arity; i++) {
7394 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7395 gboolean fqname = FALSE;
7397 g_ptr_array_add (info->type_arguments, subinfo);
7404 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7407 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7408 if (fqname && (*p != ']')) {
7416 while (*p && (*p != ']'))
7424 if (g_ascii_isspace (*aname)) {
7431 !assembly_name_to_aname (&subinfo->assembly, aname))
7433 } else if (fqname && (*p == ']')) {
7437 if (i + 1 < arity) {
7457 else if (*p == '*') /* '*' means unknown lower bound */
7458 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7465 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7476 if (g_ascii_isspace (*p)) {
7483 return 0; /* missing assembly name */
7484 if (!assembly_name_to_aname (&info->assembly, p))
7490 if (info->assembly.name)
7493 // *w = 0; /* terminate class name */
7495 if (!info->name || !*info->name)
7499 /* add other consistency checks */
7504 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7506 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7510 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7512 gboolean type_resolve = FALSE;
7514 MonoImage *rootimage = image;
7516 if (info->assembly.name) {
7517 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7518 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7520 * This could happen in the AOT compiler case when the search hook is not
7523 assembly = image->assembly;
7525 /* then we must load the assembly ourselve - see #60439 */
7526 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7530 image = assembly->image;
7531 } else if (!image) {
7532 image = mono_defaults.corlib;
7535 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7536 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7537 image = mono_defaults.corlib;
7538 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7545 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7550 gboolean bounded = FALSE;
7553 image = mono_defaults.corlib;
7556 klass = mono_class_from_name_case (image, info->name_space, info->name);
7558 klass = mono_class_from_name (image, info->name_space, info->name);
7561 for (mod = info->nested; mod; mod = mod->next) {
7562 gpointer iter = NULL;
7566 mono_class_init (parent);
7568 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7570 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7573 if (strcmp (klass->name, mod->data) == 0)
7583 if (info->type_arguments) {
7584 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7585 MonoReflectionType *the_type;
7589 for (i = 0; i < info->type_arguments->len; i++) {
7590 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7592 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7593 if (!type_args [i]) {
7599 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7601 instance = mono_reflection_bind_generic_parameters (
7602 the_type, info->type_arguments->len, type_args);
7608 klass = mono_class_from_mono_type (instance);
7611 for (mod = info->modifiers; mod; mod = mod->next) {
7612 modval = GPOINTER_TO_UINT (mod->data);
7613 if (!modval) { /* byref: must be last modifier */
7614 return &klass->this_arg;
7615 } else if (modval == -1) {
7616 klass = mono_ptr_class_get (&klass->byval_arg);
7617 } else if (modval == -2) {
7619 } else { /* array rank */
7620 klass = mono_bounded_array_class_get (klass, modval, bounded);
7624 return &klass->byval_arg;
7628 * mono_reflection_get_type:
7629 * @image: a metadata context
7630 * @info: type description structure
7631 * @ignorecase: flag for case-insensitive string compares
7632 * @type_resolve: whenever type resolve was already tried
7634 * Build a MonoType from the type description in @info.
7639 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7640 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7644 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7646 MonoReflectionAssemblyBuilder *abuilder;
7650 g_assert (assembly->dynamic);
7651 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7653 /* Enumerate all modules */
7656 if (abuilder->modules) {
7657 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7658 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7659 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7665 if (!type && abuilder->loaded_modules) {
7666 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7667 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7668 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7678 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7681 MonoReflectionAssembly *assembly;
7685 if (image && image->dynamic)
7686 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7688 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7691 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7698 *type_resolve = TRUE;
7701 /* Reconstruct the type name */
7702 fullName = g_string_new ("");
7703 if (info->name_space && (info->name_space [0] != '\0'))
7704 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7706 g_string_printf (fullName, "%s", info->name);
7707 for (mod = info->nested; mod; mod = mod->next)
7708 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7710 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7712 if (assembly->assembly->dynamic)
7713 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7715 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7718 g_string_free (fullName, TRUE);
7723 mono_reflection_free_type_info (MonoTypeNameParse *info)
7725 g_list_free (info->modifiers);
7726 g_list_free (info->nested);
7728 if (info->type_arguments) {
7731 for (i = 0; i < info->type_arguments->len; i++) {
7732 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7734 mono_reflection_free_type_info (subinfo);
7735 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7739 g_ptr_array_free (info->type_arguments, TRUE);
7744 * mono_reflection_type_from_name:
7746 * @image: a metadata context (can be NULL).
7748 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7749 * it defaults to get the type from @image or, if @image is NULL or loading
7750 * from it fails, uses corlib.
7754 mono_reflection_type_from_name (char *name, MonoImage *image)
7756 MonoType *type = NULL;
7757 MonoTypeNameParse info;
7760 /* Make a copy since parse_type modifies its argument */
7761 tmp = g_strdup (name);
7763 /*g_print ("requested type %s\n", str);*/
7764 if (mono_reflection_parse_type (tmp, &info)) {
7765 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7769 mono_reflection_free_type_info (&info);
7774 * mono_reflection_get_token:
7776 * Return the metadata token of OBJ which should be an object
7777 * representing a metadata element.
7780 mono_reflection_get_token (MonoObject *obj)
7785 klass = obj->vtable->klass;
7787 if (strcmp (klass->name, "MethodBuilder") == 0) {
7788 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7790 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7791 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7792 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7794 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7795 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7796 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7798 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7799 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7800 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7801 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7802 } else if (strcmp (klass->name, "MonoType") == 0) {
7803 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7804 MonoClass *mc = mono_class_from_mono_type (type);
7805 if (!mono_class_init (mc))
7806 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7808 token = mc->type_token;
7809 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7810 strcmp (klass->name, "MonoMethod") == 0 ||
7811 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7812 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7813 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7814 if (m->method->is_inflated) {
7815 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7816 return inflated->declaring->token;
7818 token = m->method->token;
7820 } else if (strcmp (klass->name, "MonoField") == 0) {
7821 MonoReflectionField *f = (MonoReflectionField*)obj;
7823 if (is_field_on_inst (f->field)) {
7824 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7825 int field_index = f->field - dgclass->fields;
7828 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7829 obj = dgclass->field_objects [field_index];
7830 return mono_reflection_get_token (obj);
7832 token = mono_class_get_field_token (f->field);
7833 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7834 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7836 token = mono_class_get_property_token (p->property);
7837 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7838 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7840 token = mono_class_get_event_token (p->event);
7841 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7842 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7843 MonoClass *member_class = mono_object_class (p->MemberImpl);
7844 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7846 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7847 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7848 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7851 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7852 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7854 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7855 MonoException *ex = mono_get_exception_not_implemented (msg);
7857 mono_raise_exception (ex);
7864 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7866 int slen, type = t->type;
7867 MonoClass *tklass = t->data.klass;
7873 case MONO_TYPE_BOOLEAN: {
7874 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7879 case MONO_TYPE_CHAR:
7881 case MONO_TYPE_I2: {
7882 guint16 *val = g_malloc (sizeof (guint16));
7887 #if SIZEOF_VOID_P == 4
7893 case MONO_TYPE_I4: {
7894 guint32 *val = g_malloc (sizeof (guint32));
7899 #if SIZEOF_VOID_P == 8
7900 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7904 case MONO_TYPE_I8: {
7905 guint64 *val = g_malloc (sizeof (guint64));
7910 case MONO_TYPE_R8: {
7911 double *val = g_malloc (sizeof (double));
7916 case MONO_TYPE_VALUETYPE:
7917 if (t->data.klass->enumtype) {
7918 type = mono_class_enum_basetype (t->data.klass)->type;
7921 MonoClass *k = t->data.klass;
7923 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7924 guint64 *val = g_malloc (sizeof (guint64));
7930 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7933 case MONO_TYPE_STRING:
7934 if (*p == (char)0xFF) {
7938 slen = mono_metadata_decode_value (p, &p);
7940 return mono_string_new_len (mono_domain_get (), p, slen);
7941 case MONO_TYPE_CLASS: {
7944 if (*p == (char)0xFF) {
7949 slen = mono_metadata_decode_value (p, &p);
7950 n = g_memdup (p, slen + 1);
7952 t = mono_reflection_type_from_name (n, image);
7954 g_warning ("Cannot load type '%s'", n);
7958 return mono_type_get_object (mono_domain_get (), t);
7962 case MONO_TYPE_OBJECT: {
7965 MonoClass *subc = NULL;
7970 } else if (subt == 0x0E) {
7971 type = MONO_TYPE_STRING;
7973 } else if (subt == 0x1D) {
7974 MonoType simple_type = {{0}};
7979 /* See Partition II, Appendix B3 */
7980 etype = MONO_TYPE_OBJECT;
7981 type = MONO_TYPE_SZARRAY;
7982 simple_type.type = etype;
7983 tklass = mono_class_from_mono_type (&simple_type);
7985 } else if (subt == 0x55) {
7988 slen = mono_metadata_decode_value (p, &p);
7989 n = g_memdup (p, slen + 1);
7991 t = mono_reflection_type_from_name (n, image);
7993 g_error ("Cannot load type '%s'", n);
7996 subc = mono_class_from_mono_type (t);
7997 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7998 MonoType simple_type = {{0}};
7999 simple_type.type = subt;
8000 subc = mono_class_from_mono_type (&simple_type);
8002 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8004 val = load_cattr_value (image, &subc->byval_arg, p, end);
8005 obj = mono_object_new (mono_domain_get (), subc);
8006 g_assert (!subc->has_references);
8007 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8011 case MONO_TYPE_SZARRAY: {
8013 guint32 i, alen, basetype;
8016 if (alen == 0xffffffff) {
8020 arr = mono_array_new (mono_domain_get(), tklass, alen);
8021 basetype = tklass->byval_arg.type;
8022 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8023 basetype = mono_class_enum_basetype (tklass)->type;
8028 case MONO_TYPE_BOOLEAN:
8029 for (i = 0; i < alen; i++) {
8030 MonoBoolean val = *p++;
8031 mono_array_set (arr, MonoBoolean, i, val);
8034 case MONO_TYPE_CHAR:
8037 for (i = 0; i < alen; i++) {
8038 guint16 val = read16 (p);
8039 mono_array_set (arr, guint16, i, val);
8046 for (i = 0; i < alen; i++) {
8047 guint32 val = read32 (p);
8048 mono_array_set (arr, guint32, i, val);
8053 for (i = 0; i < alen; i++) {
8056 mono_array_set (arr, double, i, val);
8062 for (i = 0; i < alen; i++) {
8063 guint64 val = read64 (p);
8064 mono_array_set (arr, guint64, i, val);
8068 case MONO_TYPE_CLASS:
8069 case MONO_TYPE_OBJECT:
8070 case MONO_TYPE_STRING:
8071 for (i = 0; i < alen; i++) {
8072 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8073 mono_array_setref (arr, i, item);
8077 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8083 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8089 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8091 static MonoClass *klass;
8092 static MonoMethod *ctor;
8094 void *params [2], *unboxed;
8097 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8099 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8101 params [0] = mono_type_get_object (mono_domain_get (), t);
8103 retval = mono_object_new (mono_domain_get (), klass);
8104 unboxed = mono_object_unbox (retval);
8105 mono_runtime_invoke (ctor, unboxed, params, NULL);
8111 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8113 static MonoClass *klass;
8114 static MonoMethod *ctor;
8116 void *unboxed, *params [2];
8119 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8121 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8124 params [1] = typedarg;
8125 retval = mono_object_new (mono_domain_get (), klass);
8126 unboxed = mono_object_unbox (retval);
8127 mono_runtime_invoke (ctor, unboxed, params, NULL);
8133 type_is_reference (MonoType *type)
8135 switch (type->type) {
8136 case MONO_TYPE_BOOLEAN:
8137 case MONO_TYPE_CHAR:
8150 case MONO_TYPE_VALUETYPE:
8158 free_param_data (MonoMethodSignature *sig, void **params) {
8160 for (i = 0; i < sig->param_count; ++i) {
8161 if (!type_is_reference (sig->params [i]))
8162 g_free (params [i]);
8167 * Find the field index in the metadata FieldDef table.
8170 find_field_index (MonoClass *klass, MonoClassField *field) {
8173 for (i = 0; i < klass->field.count; ++i) {
8174 if (field == &klass->fields [i])
8175 return klass->field.first + 1 + i;
8181 * Find the property index in the metadata Property table.
8184 find_property_index (MonoClass *klass, MonoProperty *property) {
8187 for (i = 0; i < klass->ext->property.count; ++i) {
8188 if (property == &klass->ext->properties [i])
8189 return klass->ext->property.first + 1 + i;
8195 * Find the event index in the metadata Event table.
8198 find_event_index (MonoClass *klass, MonoEvent *event) {
8201 for (i = 0; i < klass->ext->event.count; ++i) {
8202 if (event == &klass->ext->events [i])
8203 return klass->ext->event.first + 1 + i;
8209 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8211 const char *p = (const char*)data;
8213 guint32 i, j, num_named;
8215 void *params_buf [32];
8217 MonoMethodSignature *sig;
8219 mono_class_init (method->klass);
8221 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8225 attr = mono_object_new (mono_domain_get (), method->klass);
8226 mono_runtime_invoke (method, attr, NULL, NULL);
8230 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8233 /*g_print ("got attr %s\n", method->klass->name);*/
8235 sig = mono_method_signature (method);
8236 if (sig->param_count < 32)
8237 params = params_buf;
8239 /* Allocate using GC so it gets GC tracking */
8240 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8244 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8245 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8249 attr = mono_object_new (mono_domain_get (), method->klass);
8250 mono_runtime_invoke (method, attr, params, NULL);
8251 free_param_data (method->signature, params);
8252 num_named = read16 (named);
8254 for (j = 0; j < num_named; j++) {
8256 char *name, named_type, data_type;
8257 named_type = *named++;
8258 data_type = *named++; /* type of data */
8259 if (data_type == MONO_TYPE_SZARRAY)
8260 data_type = *named++;
8261 if (data_type == MONO_TYPE_ENUM) {
8264 type_len = mono_metadata_decode_blob_size (named, &named);
8265 type_name = g_malloc (type_len + 1);
8266 memcpy (type_name, named, type_len);
8267 type_name [type_len] = 0;
8269 /* FIXME: lookup the type and check type consistency */
8272 name_len = mono_metadata_decode_blob_size (named, &named);
8273 name = g_malloc (name_len + 1);
8274 memcpy (name, named, name_len);
8275 name [name_len] = 0;
8277 if (named_type == 0x53) {
8278 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8279 void *val = load_cattr_value (image, field->type, named, &named);
8280 mono_field_set_value (attr, field, val);
8281 if (!type_is_reference (field->type))
8283 } else if (named_type == 0x54) {
8286 MonoType *prop_type;
8288 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8289 /* can we have more that 1 arg in a custom attr named property? */
8290 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8291 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8292 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8293 mono_property_set_value (prop, attr, pparams, NULL);
8294 if (!type_is_reference (prop_type))
8295 g_free (pparams [0]);
8300 if (params != params_buf)
8301 mono_gc_free_fixed (params);
8307 * mono_reflection_create_custom_attr_data_args:
8309 * Create an array of typed and named arguments from the cattr blob given by DATA.
8310 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8311 * NAMED_ARG_INFO will contain information about the named arguments.
8314 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
8316 MonoArray *typedargs, *namedargs;
8317 MonoClass *attrklass;
8319 const char *p = (const char*)data;
8321 guint32 i, j, num_named;
8322 CattrNamedArg *arginfo = NULL;
8324 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8327 mono_class_init (method->klass);
8331 *named_arg_info = NULL;
8333 domain = mono_domain_get ();
8335 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8338 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8342 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8346 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8347 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8348 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8349 mono_array_setref (typedargs, i, obj);
8351 if (!type_is_reference (mono_method_signature (method)->params [i]))
8356 num_named = read16 (named);
8357 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8359 attrklass = method->klass;
8361 arginfo = g_new0 (CattrNamedArg, num_named);
8362 *named_arg_info = arginfo;
8364 for (j = 0; j < num_named; j++) {
8366 char *name, named_type, data_type;
8367 named_type = *named++;
8368 data_type = *named++; /* type of data */
8369 if (data_type == MONO_TYPE_SZARRAY)
8370 data_type = *named++;
8371 if (data_type == MONO_TYPE_ENUM) {
8374 type_len = mono_metadata_decode_blob_size (named, &named);
8375 type_name = g_malloc (type_len + 1);
8376 memcpy (type_name, named, type_len);
8377 type_name [type_len] = 0;
8379 /* FIXME: lookup the type and check type consistency */
8382 name_len = mono_metadata_decode_blob_size (named, &named);
8383 name = g_malloc (name_len + 1);
8384 memcpy (name, named, name_len);
8385 name [name_len] = 0;
8387 if (named_type == 0x53) {
8389 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8392 arginfo [j].type = field->type;
8393 arginfo [j].field = field;
8395 val = load_cattr_value (image, field->type, named, &named);
8396 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8397 mono_array_setref (namedargs, j, obj);
8398 if (!type_is_reference (field->type))
8400 } else if (named_type == 0x54) {
8402 MonoType *prop_type;
8403 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8406 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8407 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8409 arginfo [j].type = prop_type;
8410 arginfo [j].prop = prop;
8412 val = load_cattr_value (image, prop_type, named, &named);
8413 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8414 mono_array_setref (namedargs, j, obj);
8415 if (!type_is_reference (prop_type))
8421 *typed_args = typedargs;
8422 *named_args = namedargs;
8426 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8429 MonoArray *typedargs, *namedargs;
8432 CattrNamedArg *arginfo;
8441 image = assembly->assembly->image;
8442 method = ref_method->method;
8443 domain = mono_object_domain (ref_method);
8445 if (!mono_class_init (method->klass))
8446 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8448 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8449 if (mono_loader_get_last_error ())
8450 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8452 if (!typedargs || !namedargs)
8455 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8456 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8457 MonoObject *typedarg;
8459 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8460 mono_array_setref (typedargs, i, typedarg);
8463 for (i = 0; i < mono_array_length (namedargs); ++i) {
8464 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8465 MonoObject *typedarg, *namedarg, *minfo;
8467 if (arginfo [i].prop)
8468 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8470 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8472 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8473 namedarg = create_cattr_named_arg (minfo, typedarg);
8475 mono_array_setref (namedargs, i, namedarg);
8478 *ctor_args = typedargs;
8479 *named_args = namedargs;
8483 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8485 static MonoMethod *ctor;
8490 g_assert (image->assembly);
8493 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8495 domain = mono_domain_get ();
8496 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8497 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8498 params [1] = mono_assembly_get_object (domain, image->assembly);
8499 params [2] = (gpointer)&cattr->data;
8500 params [3] = &cattr->data_size;
8501 mono_runtime_invoke (ctor, attr, params, NULL);
8506 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8512 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8513 for (i = 0; i < cinfo->num_attrs; ++i) {
8514 if (!cinfo->attrs [i].ctor)
8515 /* The cattr type is not finished yet */
8516 /* We should include the type name but cinfo doesn't contain it */
8517 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8518 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8519 mono_array_setref (result, i, attr);
8525 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8532 for (i = 0; i < cinfo->num_attrs; ++i) {
8533 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8537 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8539 for (i = 0; i < cinfo->num_attrs; ++i) {
8540 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8541 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8542 mono_array_setref (result, n, attr);
8550 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8556 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8557 for (i = 0; i < cinfo->num_attrs; ++i) {
8558 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8559 mono_array_setref (result, i, attr);
8565 * mono_custom_attrs_from_index:
8567 * Returns: NULL if no attributes are found or if a loading error occurs.
8570 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8572 guint32 mtoken, i, len;
8573 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8575 MonoCustomAttrInfo *ainfo;
8576 GList *tmp, *list = NULL;
8579 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8581 i = mono_metadata_custom_attrs_from_index (image, idx);
8585 while (i < ca->rows) {
8586 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8588 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8591 len = g_list_length (list);
8594 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8595 ainfo->num_attrs = len;
8596 ainfo->image = image;
8597 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8598 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8599 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8600 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8601 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8602 mtoken |= MONO_TOKEN_METHOD_DEF;
8604 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8605 mtoken |= MONO_TOKEN_MEMBER_REF;
8608 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8611 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8612 if (!ainfo->attrs [i].ctor) {
8613 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8619 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8620 /*FIXME raising an exception here doesn't make any sense*/
8621 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8626 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8627 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8628 ainfo->attrs [i].data = (guchar*)data;
8636 mono_custom_attrs_from_method (MonoMethod *method)
8641 * An instantiated method has the same cattrs as the generic method definition.
8643 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8644 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8646 if (method->is_inflated)
8647 method = ((MonoMethodInflated *) method)->declaring;
8649 if (method->dynamic || method->klass->image->dynamic)
8650 return lookup_custom_attr (method->klass->image, method);
8653 /* Synthetic methods */
8656 idx = mono_method_get_index (method);
8657 idx <<= MONO_CUSTOM_ATTR_BITS;
8658 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8659 return mono_custom_attrs_from_index (method->klass->image, idx);
8663 mono_custom_attrs_from_class (MonoClass *klass)
8667 if (klass->generic_class)
8668 klass = klass->generic_class->container_class;
8670 if (klass->image->dynamic)
8671 return lookup_custom_attr (klass->image, klass);
8673 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8674 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8675 idx <<= MONO_CUSTOM_ATTR_BITS;
8676 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8678 idx = mono_metadata_token_index (klass->type_token);
8679 idx <<= MONO_CUSTOM_ATTR_BITS;
8680 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8682 return mono_custom_attrs_from_index (klass->image, idx);
8686 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8690 if (assembly->image->dynamic)
8691 return lookup_custom_attr (assembly->image, assembly);
8692 idx = 1; /* there is only one assembly */
8693 idx <<= MONO_CUSTOM_ATTR_BITS;
8694 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8695 return mono_custom_attrs_from_index (assembly->image, idx);
8698 static MonoCustomAttrInfo*
8699 mono_custom_attrs_from_module (MonoImage *image)
8704 return lookup_custom_attr (image, image);
8705 idx = 1; /* there is only one module */
8706 idx <<= MONO_CUSTOM_ATTR_BITS;
8707 idx |= MONO_CUSTOM_ATTR_MODULE;
8708 return mono_custom_attrs_from_index (image, idx);
8712 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8716 if (klass->image->dynamic) {
8717 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8718 return lookup_custom_attr (klass->image, property);
8720 idx = find_property_index (klass, property);
8721 idx <<= MONO_CUSTOM_ATTR_BITS;
8722 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8723 return mono_custom_attrs_from_index (klass->image, idx);
8727 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8731 if (klass->image->dynamic) {
8732 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8733 return lookup_custom_attr (klass->image, event);
8735 idx = find_event_index (klass, event);
8736 idx <<= MONO_CUSTOM_ATTR_BITS;
8737 idx |= MONO_CUSTOM_ATTR_EVENT;
8738 return mono_custom_attrs_from_index (klass->image, idx);
8742 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8745 if (klass->image->dynamic) {
8746 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8747 return lookup_custom_attr (klass->image, field);
8749 idx = find_field_index (klass, field);
8750 idx <<= MONO_CUSTOM_ATTR_BITS;
8751 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8752 return mono_custom_attrs_from_index (klass->image, idx);
8756 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8759 guint32 i, idx, method_index;
8760 guint32 param_list, param_last, param_pos, found;
8762 MonoReflectionMethodAux *aux;
8765 * An instantiated method has the same cattrs as the generic method definition.
8767 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8768 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8770 if (method->is_inflated)
8771 method = ((MonoMethodInflated *) method)->declaring;
8773 if (method->klass->image->dynamic) {
8774 MonoCustomAttrInfo *res, *ainfo;
8777 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8778 if (!aux || !aux->param_cattr)
8781 /* Need to copy since it will be freed later */
8782 ainfo = aux->param_cattr [param];
8785 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8786 res = g_malloc0 (size);
8787 memcpy (res, ainfo, size);
8791 image = method->klass->image;
8792 method_index = mono_method_get_index (method);
8795 ca = &image->tables [MONO_TABLE_METHOD];
8797 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8798 if (method_index == ca->rows) {
8799 ca = &image->tables [MONO_TABLE_PARAM];
8800 param_last = ca->rows + 1;
8802 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8803 ca = &image->tables [MONO_TABLE_PARAM];
8806 for (i = param_list; i < param_last; ++i) {
8807 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8808 if (param_pos == param) {
8816 idx <<= MONO_CUSTOM_ATTR_BITS;
8817 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8818 return mono_custom_attrs_from_index (image, idx);
8822 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8826 for (i = 0; i < ainfo->num_attrs; ++i) {
8827 klass = ainfo->attrs [i].ctor->klass;
8828 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8835 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8842 for (i = 0; i < ainfo->num_attrs; ++i) {
8843 klass = ainfo->attrs [i].ctor->klass;
8844 if (mono_class_has_parent (klass, attr_klass)) {
8849 if (attr_index == -1)
8852 attrs = mono_custom_attrs_construct (ainfo);
8854 return mono_array_get (attrs, MonoObject*, attr_index);
8860 * mono_reflection_get_custom_attrs_info:
8861 * @obj: a reflection object handle
8863 * Return the custom attribute info for attributes defined for the
8864 * reflection handle @obj. The objects.
8866 * FIXME this function leaks like a sieve for SRE objects.
8869 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8872 MonoCustomAttrInfo *cinfo = NULL;
8874 klass = obj->vtable->klass;
8875 if (klass == mono_defaults.monotype_class) {
8876 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8877 klass = mono_class_from_mono_type (type);
8878 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8879 cinfo = mono_custom_attrs_from_class (klass);
8880 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8881 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8882 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8883 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8884 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8885 cinfo = mono_custom_attrs_from_module (module->image);
8886 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8887 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8888 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8889 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8890 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8891 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8892 } else if (strcmp ("MonoField", klass->name) == 0) {
8893 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8894 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8895 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8896 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8897 cinfo = mono_custom_attrs_from_method (rmethod->method);
8898 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8899 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8900 cinfo = mono_custom_attrs_from_method (rmethod->method);
8901 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8902 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8903 MonoClass *member_class = mono_object_class (param->MemberImpl);
8904 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8905 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8906 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8907 } else if (is_sr_mono_property (member_class)) {
8908 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8910 if (!(method = prop->property->get))
8911 method = prop->property->set;
8914 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8916 #ifndef DISABLE_REFLECTION_EMIT
8917 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8918 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8919 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8920 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8921 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8922 MonoMethod *method = NULL;
8923 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8924 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8925 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8926 method = ((MonoReflectionMethod *)c->cb)->method;
8928 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8930 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8934 char *type_name = mono_type_get_full_name (member_class);
8935 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8936 MonoException *ex = mono_get_exception_not_supported (msg);
8939 mono_raise_exception (ex);
8941 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8942 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8943 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8944 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8945 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8946 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8947 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8948 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8949 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8950 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8951 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8952 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8953 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8954 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8955 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8956 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8957 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8958 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8959 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8960 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8961 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8962 } else { /* handle other types here... */
8963 g_error ("get custom attrs not yet supported for %s", klass->name);
8970 * mono_reflection_get_custom_attrs_by_type:
8971 * @obj: a reflection object handle
8973 * Return an array with all the custom attributes defined of the
8974 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8975 * of that type are returned. The objects are fully build. Return NULL if a loading error
8979 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8982 MonoCustomAttrInfo *cinfo;
8984 cinfo = mono_reflection_get_custom_attrs_info (obj);
8987 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8989 result = mono_custom_attrs_construct (cinfo);
8991 mono_custom_attrs_free (cinfo);
8993 if (mono_loader_get_last_error ())
8995 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9002 * mono_reflection_get_custom_attrs:
9003 * @obj: a reflection object handle
9005 * Return an array with all the custom attributes defined of the
9006 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9010 mono_reflection_get_custom_attrs (MonoObject *obj)
9012 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
9016 * mono_reflection_get_custom_attrs_data:
9017 * @obj: a reflection obj handle
9019 * Returns an array of System.Reflection.CustomAttributeData,
9020 * which include information about attributes reflected on
9021 * types loaded using the Reflection Only methods
9024 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9027 MonoCustomAttrInfo *cinfo;
9029 cinfo = mono_reflection_get_custom_attrs_info (obj);
9031 result = mono_custom_attrs_data_construct (cinfo);
9033 mono_custom_attrs_free (cinfo);
9035 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9040 static MonoReflectionType*
9041 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9043 static MonoMethod *method_get_underlying_system_type = NULL;
9044 MonoMethod *usertype_method;
9046 if (!method_get_underlying_system_type)
9047 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9048 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9049 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9054 is_corlib_type (MonoClass *class)
9056 return class->image == mono_defaults.corlib;
9059 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9060 static MonoClass *cached_class; \
9062 return cached_class == _class; \
9063 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9064 cached_class = _class; \
9071 #ifndef DISABLE_REFLECTION_EMIT
9073 is_sre_array (MonoClass *class)
9075 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9079 is_sre_byref (MonoClass *class)
9081 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9085 is_sre_pointer (MonoClass *class)
9087 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9091 is_sre_generic_instance (MonoClass *class)
9093 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9097 is_sre_type_builder (MonoClass *class)
9099 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9103 is_sre_method_builder (MonoClass *class)
9105 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9109 is_sre_ctor_builder (MonoClass *class)
9111 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9115 is_sre_field_builder (MonoClass *class)
9117 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9121 is_sre_method_on_tb_inst (MonoClass *class)
9123 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9127 is_sre_ctor_on_tb_inst (MonoClass *class)
9129 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9133 mono_reflection_type_get_handle (MonoReflectionType* ref)
9141 if (is_usertype (ref)) {
9142 ref = mono_reflection_type_get_underlying_system_type (ref);
9143 if (ref == NULL || is_usertype (ref))
9149 class = mono_object_class (ref);
9151 if (is_sre_array (class)) {
9153 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9154 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9156 if (sre_array->rank == 0) //single dimentional array
9157 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9159 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9160 sre_array->type.type = res;
9162 } else if (is_sre_byref (class)) {
9164 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9165 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9167 res = &mono_class_from_mono_type (base)->this_arg;
9168 sre_byref->type.type = res;
9170 } else if (is_sre_pointer (class)) {
9172 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9173 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9175 res = &mono_ptr_class_get (base)->byval_arg;
9176 sre_pointer->type.type = res;
9178 } else if (is_sre_generic_instance (class)) {
9179 MonoType *res, **types;
9180 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9183 count = mono_array_length (gclass->type_arguments);
9184 types = g_new0 (MonoType*, count);
9185 for (i = 0; i < count; ++i) {
9186 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9187 types [i] = mono_reflection_type_get_handle (t);
9194 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9197 gclass->type.type = res;
9201 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9208 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9210 mono_reflection_type_get_handle (type);
9214 mono_reflection_register_with_runtime (MonoReflectionType *type)
9216 MonoType *res = mono_reflection_type_get_handle (type);
9217 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9221 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9223 class = mono_class_from_mono_type (res);
9225 mono_loader_lock (); /*same locking as mono_type_get_object*/
9226 mono_domain_lock (domain);
9228 if (!class->image->dynamic) {
9229 mono_class_setup_supertypes (class);
9231 if (!domain->type_hash)
9232 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9233 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9234 mono_g_hash_table_insert (domain->type_hash, res, type);
9236 mono_domain_unlock (domain);
9237 mono_loader_unlock ();
9241 * LOCKING: Assumes the loader lock is held.
9243 static MonoMethodSignature*
9244 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9245 MonoMethodSignature *sig;
9248 count = parameters? mono_array_length (parameters): 0;
9250 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9251 sig->param_count = count;
9252 sig->sentinelpos = -1; /* FIXME */
9253 for (i = 0; i < count; ++i)
9254 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9259 * LOCKING: Assumes the loader lock is held.
9261 static MonoMethodSignature*
9262 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9263 MonoMethodSignature *sig;
9265 sig = parameters_to_signature (image, ctor->parameters);
9266 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9267 sig->ret = &mono_defaults.void_class->byval_arg;
9272 * LOCKING: Assumes the loader lock is held.
9274 static MonoMethodSignature*
9275 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9276 MonoMethodSignature *sig;
9278 sig = parameters_to_signature (image, method->parameters);
9279 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9280 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9281 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9285 static MonoMethodSignature*
9286 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9287 MonoMethodSignature *sig;
9289 sig = parameters_to_signature (NULL, method->parameters);
9290 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9291 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9292 sig->generic_param_count = 0;
9297 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9299 MonoClass *klass = mono_object_class (prop);
9300 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9301 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9302 *name = mono_string_to_utf8 (pb->name);
9303 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9305 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9306 *name = g_strdup (p->property->name);
9307 if (p->property->get)
9308 *type = mono_method_signature (p->property->get)->ret;
9310 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9315 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9317 MonoClass *klass = mono_object_class (field);
9318 if (strcmp (klass->name, "FieldBuilder") == 0) {
9319 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9320 *name = mono_string_to_utf8 (fb->name);
9321 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9323 MonoReflectionField *f = (MonoReflectionField *)field;
9324 *name = g_strdup (mono_field_get_name (f->field));
9325 *type = f->field->type;
9329 #else /* DISABLE_REFLECTION_EMIT */
9332 mono_reflection_register_with_runtime (MonoReflectionType *type)
9338 is_sre_type_builder (MonoClass *class)
9344 is_sre_generic_instance (MonoClass *class)
9350 init_type_builder_generics (MonoObject *type)
9354 #endif /* !DISABLE_REFLECTION_EMIT */
9358 is_sr_mono_field (MonoClass *class)
9360 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9364 is_sr_mono_property (MonoClass *class)
9366 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9370 is_sr_mono_method (MonoClass *class)
9372 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9376 is_sr_mono_cmethod (MonoClass *class)
9378 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9382 is_sr_mono_generic_method (MonoClass *class)
9384 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9388 is_sr_mono_generic_cmethod (MonoClass *class)
9390 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9394 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9396 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9400 is_usertype (MonoReflectionType *ref)
9402 MonoClass *class = mono_object_class (ref);
9403 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9406 static MonoReflectionType*
9407 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9409 if (!type || type->type)
9412 if (is_usertype (type)) {
9413 type = mono_reflection_type_get_underlying_system_type (type);
9414 if (is_usertype (type))
9415 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9421 * Encode a value in a custom attribute stream of bytes.
9422 * The value to encode is either supplied as an object in argument val
9423 * (valuetypes are boxed), or as a pointer to the data in the
9425 * @type represents the type of the value
9426 * @buffer is the start of the buffer
9427 * @p the current position in the buffer
9428 * @buflen contains the size of the buffer and is used to return the new buffer size
9429 * if this needs to be realloced.
9430 * @retbuffer and @retp return the start and the position of the buffer
9433 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9435 MonoTypeEnum simple_type;
9437 if ((p-buffer) + 10 >= *buflen) {
9440 newbuf = g_realloc (buffer, *buflen);
9441 p = newbuf + (p-buffer);
9445 argval = ((char*)arg + sizeof (MonoObject));
9446 simple_type = type->type;
9448 switch (simple_type) {
9449 case MONO_TYPE_BOOLEAN:
9454 case MONO_TYPE_CHAR:
9457 swap_with_size (p, argval, 2, 1);
9463 swap_with_size (p, argval, 4, 1);
9467 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9477 swap_with_size (p, argval, 8, 1);
9483 swap_with_size (p, argval, 8, 1);
9486 case MONO_TYPE_VALUETYPE:
9487 if (type->data.klass->enumtype) {
9488 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9491 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9494 case MONO_TYPE_STRING: {
9501 str = mono_string_to_utf8 ((MonoString*)arg);
9502 slen = strlen (str);
9503 if ((p-buffer) + 10 + slen >= *buflen) {
9507 newbuf = g_realloc (buffer, *buflen);
9508 p = newbuf + (p-buffer);
9511 mono_metadata_encode_value (slen, p, &p);
9512 memcpy (p, str, slen);
9517 case MONO_TYPE_CLASS: {
9525 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9526 slen = strlen (str);
9527 if ((p-buffer) + 10 + slen >= *buflen) {
9531 newbuf = g_realloc (buffer, *buflen);
9532 p = newbuf + (p-buffer);
9535 mono_metadata_encode_value (slen, p, &p);
9536 memcpy (p, str, slen);
9541 case MONO_TYPE_SZARRAY: {
9543 MonoClass *eclass, *arg_eclass;
9546 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9549 len = mono_array_length ((MonoArray*)arg);
9551 *p++ = (len >> 8) & 0xff;
9552 *p++ = (len >> 16) & 0xff;
9553 *p++ = (len >> 24) & 0xff;
9555 *retbuffer = buffer;
9556 eclass = type->data.klass;
9557 arg_eclass = mono_object_class (arg)->element_class;
9560 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9561 eclass = mono_defaults.object_class;
9563 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9564 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9565 int elsize = mono_class_array_element_size (arg_eclass);
9566 for (i = 0; i < len; ++i) {
9567 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9570 } else if (eclass->valuetype && arg_eclass->valuetype) {
9571 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9572 int elsize = mono_class_array_element_size (eclass);
9573 for (i = 0; i < len; ++i) {
9574 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9578 for (i = 0; i < len; ++i) {
9579 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9584 case MONO_TYPE_OBJECT: {
9590 * The parameter type is 'object' but the type of the actual
9591 * argument is not. So we have to add type information to the blob
9592 * too. This is completely undocumented in the spec.
9596 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9601 klass = mono_object_class (arg);
9603 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9606 } else if (klass->enumtype) {
9608 } else if (klass == mono_defaults.string_class) {
9609 simple_type = MONO_TYPE_STRING;
9612 } else if (klass->rank == 1) {
9614 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9615 /* See Partition II, Appendix B3 */
9618 *p++ = klass->element_class->byval_arg.type;
9619 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9621 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9622 *p++ = simple_type = klass->byval_arg.type;
9625 g_error ("unhandled type in custom attr");
9627 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9628 slen = strlen (str);
9629 if ((p-buffer) + 10 + slen >= *buflen) {
9633 newbuf = g_realloc (buffer, *buflen);
9634 p = newbuf + (p-buffer);
9637 mono_metadata_encode_value (slen, p, &p);
9638 memcpy (p, str, slen);
9641 simple_type = mono_class_enum_basetype (klass)->type;
9645 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9648 *retbuffer = buffer;
9652 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9654 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9655 char *str = type_get_qualified_name (type, NULL);
9656 int slen = strlen (str);
9660 * This seems to be optional...
9663 mono_metadata_encode_value (slen, p, &p);
9664 memcpy (p, str, slen);
9667 } else if (type->type == MONO_TYPE_OBJECT) {
9669 } else if (type->type == MONO_TYPE_CLASS) {
9670 /* it should be a type: encode_cattr_value () has the check */
9673 mono_metadata_encode_value (type->type, p, &p);
9674 if (type->type == MONO_TYPE_SZARRAY)
9675 /* See the examples in Partition VI, Annex B */
9676 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9682 #ifndef DISABLE_REFLECTION_EMIT
9684 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9687 /* Preallocate a large enough buffer */
9688 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9689 char *str = type_get_qualified_name (type, NULL);
9692 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9693 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9699 len += strlen (name);
9701 if ((p-buffer) + 20 + len >= *buflen) {
9705 newbuf = g_realloc (buffer, *buflen);
9706 p = newbuf + (p-buffer);
9710 encode_field_or_prop_type (type, p, &p);
9712 len = strlen (name);
9713 mono_metadata_encode_value (len, p, &p);
9714 memcpy (p, name, len);
9716 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9718 *retbuffer = buffer;
9722 * mono_reflection_get_custom_attrs_blob:
9723 * @ctor: custom attribute constructor
9724 * @ctorArgs: arguments o the constructor
9730 * Creates the blob of data that needs to be saved in the metadata and that represents
9731 * the custom attributed described by @ctor, @ctorArgs etc.
9732 * Returns: a Byte array representing the blob of data.
9735 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9738 MonoMethodSignature *sig;
9743 MONO_ARCH_SAVE_REGS;
9745 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9746 /* sig is freed later so allocate it in the heap */
9747 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9749 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9752 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9754 p = buffer = g_malloc (buflen);
9755 /* write the prolog */
9758 for (i = 0; i < sig->param_count; ++i) {
9759 arg = mono_array_get (ctorArgs, MonoObject*, i);
9760 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9764 i += mono_array_length (properties);
9766 i += mono_array_length (fields);
9768 *p++ = (i >> 8) & 0xff;
9771 for (i = 0; i < mono_array_length (properties); ++i) {
9775 prop = mono_array_get (properties, gpointer, i);
9776 get_prop_name_and_type (prop, &pname, &ptype);
9777 *p++ = 0x54; /* PROPERTY signature */
9778 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9785 for (i = 0; i < mono_array_length (fields); ++i) {
9789 field = mono_array_get (fields, gpointer, i);
9790 get_field_name_and_type (field, &fname, &ftype);
9791 *p++ = 0x53; /* FIELD signature */
9792 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9797 g_assert (p - buffer <= buflen);
9798 buflen = p - buffer;
9799 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9800 p = mono_array_addr (result, char, 0);
9801 memcpy (p, buffer, buflen);
9803 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9809 * mono_reflection_setup_internal_class:
9810 * @tb: a TypeBuilder object
9812 * Creates a MonoClass that represents the TypeBuilder.
9813 * This is a trick that lets us simplify a lot of reflection code
9814 * (and will allow us to support Build and Run assemblies easier).
9817 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9820 MonoClass *klass, *parent;
9822 MONO_ARCH_SAVE_REGS;
9824 RESOLVE_TYPE (tb->parent);
9826 mono_loader_lock ();
9829 /* check so we can compile corlib correctly */
9830 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9831 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9832 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9834 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9840 /* the type has already being created: it means we just have to change the parent */
9841 if (tb->type.type) {
9842 klass = mono_class_from_mono_type (tb->type.type);
9843 klass->parent = NULL;
9844 /* fool mono_class_setup_parent */
9845 klass->supertypes = NULL;
9846 mono_class_setup_parent (klass, parent);
9847 mono_class_setup_mono_type (klass);
9848 mono_loader_unlock ();
9852 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9854 klass->image = &tb->module->dynamic_image->image;
9856 klass->inited = 1; /* we lie to the runtime */
9857 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9858 if (!mono_error_ok (&error))
9860 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9861 if (!mono_error_ok (&error))
9863 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9864 klass->flags = tb->attrs;
9866 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9868 klass->element_class = klass;
9870 if (mono_class_get_ref_info (klass) == NULL) {
9872 mono_class_set_ref_info (klass, tb);
9874 /* Put into cache so mono_class_get () will find it.
9875 Skip nested types as those should not be available on the global scope. */
9876 if (!tb->nesting_type) {
9877 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9879 klass->image->reflection_info_unregister_classes =
9880 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9883 g_assert (mono_class_get_ref_info (klass) == tb);
9886 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9887 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9889 if (parent != NULL) {
9890 mono_class_setup_parent (klass, parent);
9891 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9892 const char *old_n = klass->name;
9893 /* trick to get relative numbering right when compiling corlib */
9894 klass->name = "BuildingObject";
9895 mono_class_setup_parent (klass, mono_defaults.object_class);
9896 klass->name = old_n;
9899 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9900 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9901 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9902 klass->instance_size = sizeof (MonoObject);
9903 klass->size_inited = 1;
9904 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9907 mono_class_setup_mono_type (klass);
9909 mono_class_setup_supertypes (klass);
9912 * FIXME: handle interfaces.
9915 tb->type.type = &klass->byval_arg;
9917 if (tb->nesting_type) {
9918 g_assert (tb->nesting_type->type);
9919 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9922 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9924 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9926 mono_loader_unlock ();
9930 mono_loader_unlock ();
9931 mono_error_raise_exception (&error);
9935 * mono_reflection_setup_generic_class:
9936 * @tb: a TypeBuilder object
9938 * Setup the generic class before adding the first generic parameter.
9941 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9946 * mono_reflection_create_generic_class:
9947 * @tb: a TypeBuilder object
9949 * Creates the generic class after all generic parameters have been added.
9952 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9957 MONO_ARCH_SAVE_REGS;
9959 klass = mono_class_from_mono_type (tb->type.type);
9961 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9963 if (klass->generic_container || (count == 0))
9966 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9968 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9970 klass->generic_container->owner.klass = klass;
9971 klass->generic_container->type_argc = count;
9972 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9974 klass->is_generic = 1;
9976 for (i = 0; i < count; i++) {
9977 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9978 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9979 klass->generic_container->type_params [i] = *param;
9980 /*Make sure we are a diferent type instance */
9981 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9982 klass->generic_container->type_params [i].info.pklass = NULL;
9983 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9985 g_assert (klass->generic_container->type_params [i].param.owner);
9988 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9992 * mono_reflection_create_internal_class:
9993 * @tb: a TypeBuilder object
9995 * Actually create the MonoClass that is associated with the TypeBuilder.
9998 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10002 MONO_ARCH_SAVE_REGS;
10004 klass = mono_class_from_mono_type (tb->type.type);
10006 mono_loader_lock ();
10007 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10008 MonoReflectionFieldBuilder *fb;
10010 MonoType *enum_basetype;
10012 g_assert (tb->fields != NULL);
10013 g_assert (mono_array_length (tb->fields) >= 1);
10015 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10017 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10018 mono_loader_unlock ();
10022 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10023 klass->element_class = mono_class_from_mono_type (enum_basetype);
10024 if (!klass->element_class)
10025 klass->element_class = mono_class_from_mono_type (enum_basetype);
10028 * get the element_class from the current corlib.
10030 ec = default_class_from_mono_type (enum_basetype);
10031 klass->instance_size = ec->instance_size;
10032 klass->size_inited = 1;
10034 * this is almost safe to do with enums and it's needed to be able
10035 * to create objects of the enum type (for use in SetConstant).
10037 /* FIXME: Does this mean enums can't have method overrides ? */
10038 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10040 mono_loader_unlock ();
10043 static MonoMarshalSpec*
10044 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10045 MonoReflectionMarshal *minfo)
10047 MonoMarshalSpec *res;
10049 res = image_g_new0 (image, MonoMarshalSpec, 1);
10050 res->native = minfo->type;
10052 switch (minfo->type) {
10053 case MONO_NATIVE_LPARRAY:
10054 res->data.array_data.elem_type = minfo->eltype;
10055 if (minfo->has_size) {
10056 res->data.array_data.param_num = minfo->param_num;
10057 res->data.array_data.num_elem = minfo->count;
10058 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10061 res->data.array_data.param_num = -1;
10062 res->data.array_data.num_elem = -1;
10063 res->data.array_data.elem_mult = -1;
10067 case MONO_NATIVE_BYVALTSTR:
10068 case MONO_NATIVE_BYVALARRAY:
10069 res->data.array_data.num_elem = minfo->count;
10072 case MONO_NATIVE_CUSTOM:
10073 if (minfo->marshaltyperef)
10074 res->data.custom_data.custom_name =
10075 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10076 if (minfo->mcookie)
10077 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10086 #endif /* !DISABLE_REFLECTION_EMIT */
10088 MonoReflectionMarshal*
10089 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10090 MonoMarshalSpec *spec)
10092 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10093 MonoReflectionMarshal *minfo;
10096 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10097 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10098 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10099 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10102 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10103 minfo->type = spec->native;
10105 switch (minfo->type) {
10106 case MONO_NATIVE_LPARRAY:
10107 minfo->eltype = spec->data.array_data.elem_type;
10108 minfo->count = spec->data.array_data.num_elem;
10109 minfo->param_num = spec->data.array_data.param_num;
10112 case MONO_NATIVE_BYVALTSTR:
10113 case MONO_NATIVE_BYVALARRAY:
10114 minfo->count = spec->data.array_data.num_elem;
10117 case MONO_NATIVE_CUSTOM:
10118 if (spec->data.custom_data.custom_name) {
10119 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10121 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10123 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10125 if (spec->data.custom_data.cookie)
10126 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10136 #ifndef DISABLE_REFLECTION_EMIT
10138 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10139 ReflectionMethodBuilder *rmb,
10140 MonoMethodSignature *sig)
10144 MonoMethodWrapper *wrapperm;
10145 MonoMarshalSpec **specs;
10146 MonoReflectionMethodAux *method_aux;
10151 mono_error_init (&error);
10153 * Methods created using a MethodBuilder should have their memory allocated
10154 * inside the image mempool, while dynamic methods should have their memory
10157 dynamic = rmb->refs != NULL;
10158 image = dynamic ? NULL : klass->image;
10161 g_assert (!klass->generic_class);
10163 mono_loader_lock ();
10165 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10166 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10167 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10169 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10171 wrapperm = (MonoMethodWrapper*)m;
10173 m->dynamic = dynamic;
10175 m->flags = rmb->attrs;
10176 m->iflags = rmb->iattrs;
10177 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10178 g_assert (mono_error_ok (&error));
10180 m->signature = sig;
10181 m->sre_method = TRUE;
10182 m->skip_visibility = rmb->skip_visibility;
10183 if (rmb->table_idx)
10184 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10186 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10187 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10188 m->string_ctor = 1;
10190 m->signature->pinvoke = 1;
10191 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10192 m->signature->pinvoke = 1;
10194 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10196 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10197 g_assert (mono_error_ok (&error));
10198 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10199 g_assert (mono_error_ok (&error));
10201 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10203 if (klass->image->dynamic)
10204 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10206 mono_loader_unlock ();
10209 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10210 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10211 MonoMethodHeader *header;
10213 gint32 max_stack, i;
10214 gint32 num_locals = 0;
10215 gint32 num_clauses = 0;
10219 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10220 code_size = rmb->ilgen->code_len;
10221 max_stack = rmb->ilgen->max_stack;
10222 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10223 if (rmb->ilgen->ex_handlers)
10224 num_clauses = method_count_clauses (rmb->ilgen);
10227 code = mono_array_addr (rmb->code, guint8, 0);
10228 code_size = mono_array_length (rmb->code);
10229 /* we probably need to run a verifier on the code... */
10239 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10240 header->code_size = code_size;
10241 header->code = image_g_malloc (image, code_size);
10242 memcpy ((char*)header->code, code, code_size);
10243 header->max_stack = max_stack;
10244 header->init_locals = rmb->init_locals;
10245 header->num_locals = num_locals;
10247 for (i = 0; i < num_locals; ++i) {
10248 MonoReflectionLocalBuilder *lb =
10249 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10251 header->locals [i] = image_g_new0 (image, MonoType, 1);
10252 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10255 header->num_clauses = num_clauses;
10257 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10258 rmb->ilgen, num_clauses);
10261 wrapperm->header = header;
10264 if (rmb->generic_params) {
10265 int count = mono_array_length (rmb->generic_params);
10266 MonoGenericContainer *container = rmb->generic_container;
10268 g_assert (container);
10270 container->type_argc = count;
10271 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10272 container->owner.method = m;
10274 m->is_generic = TRUE;
10275 mono_method_set_generic_container (m, container);
10277 for (i = 0; i < count; i++) {
10278 MonoReflectionGenericParam *gp =
10279 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10280 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10281 container->type_params [i] = *param;
10285 * The method signature might have pointers to generic parameters that belong to other methods.
10286 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10287 * generic parameters.
10289 for (i = 0; i < m->signature->param_count; ++i) {
10290 MonoType *t = m->signature->params [i];
10291 if (t->type == MONO_TYPE_MVAR) {
10292 MonoGenericParam *gparam = t->data.generic_param;
10293 if (gparam->num < count) {
10294 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10295 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10301 if (klass->generic_container) {
10302 container->parent = klass->generic_container;
10303 container->context.class_inst = klass->generic_container->context.class_inst;
10305 container->context.method_inst = mono_get_shared_generic_inst (container);
10309 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10313 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10315 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10316 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10317 for (i = 0; i < rmb->nrefs; ++i)
10318 data [i + 1] = rmb->refs [i];
10323 /* Parameter info */
10326 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10327 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10328 for (i = 0; i <= m->signature->param_count; ++i) {
10329 MonoReflectionParamBuilder *pb;
10330 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10331 if ((i > 0) && (pb->attrs)) {
10332 /* Make a copy since it might point to a shared type structure */
10333 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10334 m->signature->params [i - 1]->attrs = pb->attrs;
10337 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10338 MonoDynamicImage *assembly;
10339 guint32 idx, def_type, len;
10343 if (!method_aux->param_defaults) {
10344 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10345 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10347 assembly = (MonoDynamicImage*)klass->image;
10348 idx = encode_constant (assembly, pb->def_value, &def_type);
10349 /* Copy the data from the blob since it might get realloc-ed */
10350 p = assembly->blob.data + idx;
10351 len = mono_metadata_decode_blob_size (p, &p2);
10353 method_aux->param_defaults [i] = image_g_malloc (image, len);
10354 method_aux->param_default_types [i] = def_type;
10355 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10359 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10360 g_assert (mono_error_ok (&error));
10363 if (!method_aux->param_cattr)
10364 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10365 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10371 /* Parameter marshalling */
10374 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10375 MonoReflectionParamBuilder *pb;
10376 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10377 if (pb->marshal_info) {
10379 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10380 specs [pb->position] =
10381 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10385 if (specs != NULL) {
10387 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10388 method_aux->param_marshall = specs;
10391 if (klass->image->dynamic && method_aux)
10392 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10394 mono_loader_unlock ();
10400 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10402 ReflectionMethodBuilder rmb;
10403 MonoMethodSignature *sig;
10405 mono_loader_lock ();
10406 sig = ctor_builder_to_signature (klass->image, mb);
10407 mono_loader_unlock ();
10409 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10411 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10412 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10414 /* If we are in a generic class, we might be called multiple times from inflate_method */
10415 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10416 /* ilgen is no longer needed */
10420 return mb->mhandle;
10424 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10426 ReflectionMethodBuilder rmb;
10427 MonoMethodSignature *sig;
10429 mono_loader_lock ();
10430 sig = method_builder_to_signature (klass->image, mb);
10431 mono_loader_unlock ();
10433 reflection_methodbuilder_from_method_builder (&rmb, mb);
10435 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10436 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10438 /* If we are in a generic class, we might be called multiple times from inflate_method */
10439 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10440 /* ilgen is no longer needed */
10443 return mb->mhandle;
10446 static MonoClassField*
10447 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10449 MonoClassField *field;
10452 field = g_new0 (MonoClassField, 1);
10454 field->name = mono_string_to_utf8 (fb->name);
10455 if (fb->attrs || fb->modreq || fb->modopt) {
10456 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10457 field->type->attrs = fb->attrs;
10459 g_assert (klass->image->dynamic);
10460 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10461 g_free (field->type);
10462 field->type = custom;
10464 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10466 if (fb->offset != -1)
10467 field->offset = fb->offset;
10468 field->parent = klass;
10469 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10471 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10478 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10481 MonoReflectionTypeBuilder *tb = NULL;
10482 gboolean is_dynamic = FALSE;
10483 MonoDomain *domain;
10484 MonoClass *geninst;
10486 mono_loader_lock ();
10488 domain = mono_object_domain (type);
10490 if (is_sre_type_builder (mono_object_class (type))) {
10491 tb = (MonoReflectionTypeBuilder *) type;
10494 } else if (is_sre_generic_instance (mono_object_class (type))) {
10495 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10496 MonoReflectionType *gtd = rgi->generic_type;
10498 if (is_sre_type_builder (mono_object_class (gtd))) {
10499 tb = (MonoReflectionTypeBuilder *)gtd;
10504 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10505 if (tb && tb->generic_container)
10506 mono_reflection_create_generic_class (tb);
10508 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10509 if (!klass->generic_container) {
10510 mono_loader_unlock ();
10514 if (klass->wastypebuilder) {
10515 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10520 mono_loader_unlock ();
10522 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10524 return &geninst->byval_arg;
10528 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10530 MonoGenericClass *gclass;
10531 MonoGenericInst *inst;
10533 g_assert (klass->generic_container);
10535 inst = mono_metadata_get_generic_inst (type_argc, types);
10536 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10538 return mono_generic_class_get_class (gclass);
10541 MonoReflectionMethod*
10542 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10545 MonoMethod *method, *inflated;
10546 MonoMethodInflated *imethod;
10547 MonoGenericContext tmp_context;
10548 MonoGenericInst *ginst;
10549 MonoType **type_argv;
10552 MONO_ARCH_SAVE_REGS;
10554 /*FIXME but this no longer should happen*/
10555 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10556 #ifndef DISABLE_REFLECTION_EMIT
10557 MonoReflectionMethodBuilder *mb = NULL;
10558 MonoReflectionTypeBuilder *tb;
10561 mb = (MonoReflectionMethodBuilder *) rmethod;
10562 tb = (MonoReflectionTypeBuilder *) mb->type;
10563 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10565 method = methodbuilder_to_mono_method (klass, mb);
10567 g_assert_not_reached ();
10571 method = rmethod->method;
10574 klass = method->klass;
10576 if (method->is_inflated)
10577 method = ((MonoMethodInflated *) method)->declaring;
10579 count = mono_method_signature (method)->generic_param_count;
10580 if (count != mono_array_length (types))
10583 type_argv = g_new0 (MonoType *, count);
10584 for (i = 0; i < count; i++) {
10585 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10586 type_argv [i] = mono_reflection_type_get_handle (garg);
10588 ginst = mono_metadata_get_generic_inst (count, type_argv);
10589 g_free (type_argv);
10591 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10592 tmp_context.method_inst = ginst;
10594 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10595 imethod = (MonoMethodInflated *) inflated;
10597 /*FIXME but I think this is no longer necessary*/
10598 if (method->klass->image->dynamic) {
10599 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10601 * This table maps metadata structures representing inflated methods/fields
10602 * to the reflection objects representing their generic definitions.
10604 mono_loader_lock ();
10605 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10606 mono_loader_unlock ();
10609 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10610 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10612 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10615 #ifndef DISABLE_REFLECTION_EMIT
10617 static MonoMethod *
10618 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10620 MonoMethodInflated *imethod;
10621 MonoGenericContext *context;
10625 * With generic code sharing the klass might not be inflated.
10626 * This can happen because classes inflated with their own
10627 * type arguments are "normalized" to the uninflated class.
10629 if (!klass->generic_class)
10632 context = mono_class_get_context (klass);
10634 if (klass->method.count && klass->methods) {
10635 /* Find the already created inflated method */
10636 for (i = 0; i < klass->method.count; ++i) {
10637 g_assert (klass->methods [i]->is_inflated);
10638 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10641 g_assert (i < klass->method.count);
10642 imethod = (MonoMethodInflated*)klass->methods [i];
10644 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10647 if (method->is_generic && method->klass->image->dynamic) {
10648 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10650 mono_loader_lock ();
10651 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10652 mono_loader_unlock ();
10654 return (MonoMethod *) imethod;
10657 static MonoMethod *
10658 inflate_method (MonoReflectionType *type, MonoObject *obj)
10660 MonoMethod *method;
10663 MonoClass *type_class = mono_object_class (type);
10665 if (is_sre_generic_instance (type_class)) {
10666 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10667 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10668 } else if (is_sre_type_builder (type_class)) {
10669 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10670 } else if (type->type) {
10671 gklass = mono_class_from_mono_type (type->type);
10672 gklass = mono_class_get_generic_type_definition (gklass);
10674 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10677 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10678 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10679 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10681 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10682 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10683 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10684 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10685 method = ((MonoReflectionMethod *) obj)->method;
10687 method = NULL; /* prevent compiler warning */
10688 g_error ("can't handle type %s", obj->vtable->klass->name);
10691 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10694 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10696 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10697 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10700 MonoGenericClass *gclass;
10701 MonoDynamicGenericClass *dgclass;
10702 MonoClass *klass, *gklass;
10706 MONO_ARCH_SAVE_REGS;
10708 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10709 klass = mono_class_from_mono_type (gtype);
10710 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10711 gclass = gtype->data.generic_class;
10713 if (!gclass->is_dynamic)
10716 dgclass = (MonoDynamicGenericClass *) gclass;
10718 if (dgclass->initialized)
10721 gklass = gclass->container_class;
10722 mono_class_init (gklass);
10724 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10725 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10726 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10728 dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10729 dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10730 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10731 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10732 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10734 for (i = 0; i < dgclass->count_methods; i++) {
10735 MonoObject *obj = mono_array_get (methods, gpointer, i);
10737 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10740 for (i = 0; i < dgclass->count_ctors; i++) {
10741 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10743 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10746 for (i = 0; i < dgclass->count_fields; i++) {
10747 MonoObject *obj = mono_array_get (fields, gpointer, i);
10748 MonoClassField *field, *inflated_field = NULL;
10750 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10751 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10752 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10753 field = ((MonoReflectionField *) obj)->field;
10755 field = NULL; /* prevent compiler warning */
10756 g_assert_not_reached ();
10759 dgclass->fields [i] = *field;
10760 dgclass->fields [i].parent = klass;
10761 dgclass->fields [i].type = mono_class_inflate_generic_type (
10762 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10763 dgclass->field_generic_types [i] = field->type;
10764 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10765 dgclass->field_objects [i] = obj;
10767 if (inflated_field) {
10768 g_free (inflated_field);
10770 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10774 dgclass->initialized = TRUE;
10778 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10780 MonoDynamicGenericClass *dgclass;
10783 g_assert (gclass->is_dynamic);
10785 dgclass = (MonoDynamicGenericClass *)gclass;
10787 for (i = 0; i < dgclass->count_fields; ++i) {
10788 MonoClassField *field = dgclass->fields + i;
10789 mono_metadata_free_type (field->type);
10791 MONO_GC_UNREGISTER_ROOT (dgclass->field_objects [i]);
10797 fix_partial_generic_class (MonoClass *klass)
10799 MonoClass *gklass = klass->generic_class->container_class;
10800 MonoDynamicGenericClass *dgclass;
10803 if (klass->wastypebuilder)
10806 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10807 if (klass->parent != gklass->parent) {
10809 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10810 if (mono_error_ok (&error)) {
10811 MonoClass *parent = mono_class_from_mono_type (parent_type);
10812 mono_metadata_free_type (parent_type);
10813 if (parent != klass->parent) {
10814 /*fool mono_class_setup_parent*/
10815 klass->supertypes = NULL;
10816 mono_class_setup_parent (klass, parent);
10819 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10820 mono_error_cleanup (&error);
10821 if (gklass->wastypebuilder)
10822 klass->wastypebuilder = TRUE;
10827 if (!dgclass->initialized)
10830 if (klass->method.count != gklass->method.count) {
10831 klass->method.count = gklass->method.count;
10832 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10834 for (i = 0; i < klass->method.count; i++) {
10835 klass->methods [i] = mono_class_inflate_generic_method_full (
10836 gklass->methods [i], klass, mono_class_get_context (klass));
10840 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10841 klass->interface_count = gklass->interface_count;
10842 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10843 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10845 for (i = 0; i < gklass->interface_count; ++i) {
10846 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10847 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10848 mono_metadata_free_type (iface_type);
10850 ensure_runtime_vtable (klass->interfaces [i]);
10852 klass->interfaces_inited = 1;
10855 if (klass->field.count != gklass->field.count) {
10856 klass->field.count = gklass->field.count;
10857 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10859 for (i = 0; i < klass->field.count; i++) {
10860 klass->fields [i] = gklass->fields [i];
10861 klass->fields [i].parent = klass;
10862 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10866 /*We can only finish with this klass once it's parent has as well*/
10867 if (gklass->wastypebuilder)
10868 klass->wastypebuilder = TRUE;
10873 ensure_generic_class_runtime_vtable (MonoClass *klass)
10875 MonoClass *gklass = klass->generic_class->container_class;
10877 ensure_runtime_vtable (gklass);
10879 fix_partial_generic_class (klass);
10883 ensure_runtime_vtable (MonoClass *klass)
10885 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10888 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10891 ensure_runtime_vtable (klass->parent);
10894 num = tb->ctors? mono_array_length (tb->ctors): 0;
10895 num += tb->num_methods;
10896 klass->method.count = num;
10897 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10898 num = tb->ctors? mono_array_length (tb->ctors): 0;
10899 for (i = 0; i < num; ++i)
10900 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10901 num = tb->num_methods;
10903 for (i = 0; i < num; ++i)
10904 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10906 if (tb->interfaces) {
10907 klass->interface_count = mono_array_length (tb->interfaces);
10908 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10909 for (i = 0; i < klass->interface_count; ++i) {
10910 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10911 klass->interfaces [i] = mono_class_from_mono_type (iface);
10912 ensure_runtime_vtable (klass->interfaces [i]);
10914 klass->interfaces_inited = 1;
10916 } else if (klass->generic_class){
10917 ensure_generic_class_runtime_vtable (klass);
10920 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10922 for (i = 0; i < klass->method.count; ++i) {
10923 MonoMethod *im = klass->methods [i];
10924 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10925 im->slot = slot_num++;
10928 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10929 mono_class_setup_interface_offsets (klass);
10930 mono_class_setup_interface_id (klass);
10934 * The generic vtable is needed even if image->run is not set since some
10935 * runtime code like ves_icall_Type_GetMethodsByName depends on
10936 * method->slot being defined.
10940 * tb->methods could not be freed since it is used for determining
10941 * overrides during dynamic vtable construction.
10946 mono_reflection_method_get_handle (MonoObject *method)
10948 MonoClass *class = mono_object_class (method);
10949 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10950 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10951 return sr_method->method;
10953 if (is_sre_method_builder (class)) {
10954 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10955 return mb->mhandle;
10957 if (is_sre_method_on_tb_inst (class)) {
10958 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10959 MonoMethod *result;
10960 /*FIXME move this to a proper method and unify with resolve_object*/
10961 if (m->method_args) {
10962 result = mono_reflection_method_on_tb_inst_get_handle (m);
10964 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10965 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10966 MonoMethod *mono_method;
10968 if (is_sre_method_builder (mono_object_class (m->mb)))
10969 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10970 else if (is_sr_mono_method (mono_object_class (m->mb)))
10971 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10973 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
10975 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10980 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10985 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10987 MonoReflectionTypeBuilder *tb;
10991 *num_overrides = 0;
10993 g_assert (klass->image->dynamic);
10995 if (!mono_class_get_ref_info (klass))
10998 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11000 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11004 for (i = 0; i < tb->num_methods; ++i) {
11005 MonoReflectionMethodBuilder *mb =
11006 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11007 if (mb->override_method)
11013 *overrides = g_new0 (MonoMethod*, onum * 2);
11016 for (i = 0; i < tb->num_methods; ++i) {
11017 MonoReflectionMethodBuilder *mb =
11018 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11019 if (mb->override_method) {
11020 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
11021 (*overrides) [onum * 2 + 1] = mb->mhandle;
11023 g_assert (mb->mhandle);
11030 *num_overrides = onum;
11034 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11036 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11037 MonoReflectionFieldBuilder *fb;
11038 MonoClassField *field;
11039 MonoImage *image = klass->image;
11040 const char *p, *p2;
11042 guint32 len, idx, real_size = 0;
11044 klass->field.count = tb->num_fields;
11045 klass->field.first = 0;
11047 mono_error_init (error);
11049 if (tb->class_size) {
11050 g_assert ((tb->packing_size & 0xfffffff0) == 0);
11051 klass->packing_size = tb->packing_size;
11052 real_size = klass->instance_size + tb->class_size;
11055 if (!klass->field.count) {
11056 klass->instance_size = MAX (klass->instance_size, real_size);
11060 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11061 mono_class_alloc_ext (klass);
11062 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11064 This is, guess what, a hack.
11065 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11066 On the static path no field class is resolved, only types are built. This is the right thing to do
11068 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11070 klass->size_inited = 1;
11072 for (i = 0; i < klass->field.count; ++i) {
11073 fb = mono_array_get (tb->fields, gpointer, i);
11074 field = &klass->fields [i];
11075 field->name = mono_string_to_utf8_image (image, fb->name, error);
11076 if (!mono_error_ok (error))
11079 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11080 field->type->attrs = fb->attrs;
11082 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11084 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
11085 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
11086 if (fb->offset != -1)
11087 field->offset = fb->offset;
11088 field->parent = klass;
11089 fb->handle = field;
11090 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11092 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11093 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11095 if (fb->def_value) {
11096 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11097 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11098 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11099 /* Copy the data from the blob since it might get realloc-ed */
11100 p = assembly->blob.data + idx;
11101 len = mono_metadata_decode_blob_size (p, &p2);
11103 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11104 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11108 klass->instance_size = MAX (klass->instance_size, real_size);
11109 mono_class_layout_fields (klass);
11113 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11115 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11116 MonoReflectionPropertyBuilder *pb;
11117 MonoImage *image = klass->image;
11118 MonoProperty *properties;
11121 mono_error_init (error);
11124 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11126 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11127 klass->ext->property.first = 0;
11129 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11130 klass->ext->properties = properties;
11131 for (i = 0; i < klass->ext->property.count; ++i) {
11132 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11133 properties [i].parent = klass;
11134 properties [i].attrs = pb->attrs;
11135 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11136 if (!mono_error_ok (error))
11138 if (pb->get_method)
11139 properties [i].get = pb->get_method->mhandle;
11140 if (pb->set_method)
11141 properties [i].set = pb->set_method->mhandle;
11143 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11144 if (pb->def_value) {
11146 const char *p, *p2;
11147 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11148 if (!klass->ext->prop_def_values)
11149 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11150 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11151 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11152 /* Copy the data from the blob since it might get realloc-ed */
11153 p = assembly->blob.data + idx;
11154 len = mono_metadata_decode_blob_size (p, &p2);
11156 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11157 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11162 MonoReflectionEvent *
11163 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11165 MonoEvent *event = g_new0 (MonoEvent, 1);
11168 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11170 event->parent = klass;
11171 event->attrs = eb->attrs;
11172 event->name = mono_string_to_utf8 (eb->name);
11173 if (eb->add_method)
11174 event->add = eb->add_method->mhandle;
11175 if (eb->remove_method)
11176 event->remove = eb->remove_method->mhandle;
11177 if (eb->raise_method)
11178 event->raise = eb->raise_method->mhandle;
11180 #ifndef MONO_SMALL_CONFIG
11181 if (eb->other_methods) {
11183 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11184 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11185 MonoReflectionMethodBuilder *mb =
11186 mono_array_get (eb->other_methods,
11187 MonoReflectionMethodBuilder*, j);
11188 event->other [j] = mb->mhandle;
11193 return mono_event_get_object (mono_object_domain (tb), klass, event);
11197 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11199 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11200 MonoReflectionEventBuilder *eb;
11201 MonoImage *image = klass->image;
11205 mono_error_init (error);
11208 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11210 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11211 klass->ext->event.first = 0;
11213 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11214 klass->ext->events = events;
11215 for (i = 0; i < klass->ext->event.count; ++i) {
11216 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11217 events [i].parent = klass;
11218 events [i].attrs = eb->attrs;
11219 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11220 if (!mono_error_ok (error))
11222 if (eb->add_method)
11223 events [i].add = eb->add_method->mhandle;
11224 if (eb->remove_method)
11225 events [i].remove = eb->remove_method->mhandle;
11226 if (eb->raise_method)
11227 events [i].raise = eb->raise_method->mhandle;
11229 #ifndef MONO_SMALL_CONFIG
11230 if (eb->other_methods) {
11232 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11233 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11234 MonoReflectionMethodBuilder *mb =
11235 mono_array_get (eb->other_methods,
11236 MonoReflectionMethodBuilder*, j);
11237 events [i].other [j] = mb->mhandle;
11241 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11246 remove_instantiations_of_and_ensure_contents (gpointer key,
11248 gpointer user_data)
11250 MonoType *type = (MonoType*)key;
11251 MonoClass *klass = (MonoClass*)user_data;
11253 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11254 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11261 check_array_for_usertypes (MonoArray *arr)
11268 for (i = 0; i < mono_array_length (arr); ++i)
11269 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11272 MonoReflectionType*
11273 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11277 MonoDomain* domain;
11278 MonoReflectionType* res;
11281 MONO_ARCH_SAVE_REGS;
11283 domain = mono_object_domain (tb);
11284 klass = mono_class_from_mono_type (tb->type.type);
11287 * Check for user defined Type subclasses.
11289 RESOLVE_TYPE (tb->parent);
11290 check_array_for_usertypes (tb->interfaces);
11292 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11293 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11295 RESOLVE_TYPE (fb->type);
11296 check_array_for_usertypes (fb->modreq);
11297 check_array_for_usertypes (fb->modopt);
11298 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11299 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11304 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11305 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11307 RESOLVE_TYPE (mb->rtype);
11308 check_array_for_usertypes (mb->return_modreq);
11309 check_array_for_usertypes (mb->return_modopt);
11310 check_array_for_usertypes (mb->parameters);
11311 if (mb->param_modreq)
11312 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11313 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11314 if (mb->param_modopt)
11315 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11316 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11321 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11322 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11324 check_array_for_usertypes (mb->parameters);
11325 if (mb->param_modreq)
11326 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11327 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11328 if (mb->param_modopt)
11329 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11330 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11335 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11338 * we need to lock the domain because the lock will be taken inside
11339 * So, we need to keep the locking order correct.
11341 mono_loader_lock ();
11342 mono_domain_lock (domain);
11343 if (klass->wastypebuilder) {
11344 mono_domain_unlock (domain);
11345 mono_loader_unlock ();
11346 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11349 * Fields to set in klass:
11350 * the various flags: delegate/unicode/contextbound etc.
11352 klass->flags = tb->attrs;
11353 klass->has_cctor = 1;
11354 klass->has_finalize = 1;
11356 /* fool mono_class_setup_parent */
11357 klass->supertypes = NULL;
11358 mono_class_setup_parent (klass, klass->parent);
11359 mono_class_setup_mono_type (klass);
11362 if (!((MonoDynamicImage*)klass->image)->run) {
11363 if (klass->generic_container) {
11364 /* FIXME: The code below can't handle generic classes */
11365 klass->wastypebuilder = TRUE;
11366 mono_loader_unlock ();
11367 mono_domain_unlock (domain);
11368 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11373 /* enums are done right away */
11374 if (!klass->enumtype)
11375 ensure_runtime_vtable (klass);
11377 if (tb->subtypes) {
11378 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11379 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11380 mono_class_alloc_ext (klass);
11381 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11385 klass->nested_classes_inited = TRUE;
11387 /* fields and object layout */
11388 if (klass->parent) {
11389 if (!klass->parent->size_inited)
11390 mono_class_init (klass->parent);
11391 klass->instance_size = klass->parent->instance_size;
11392 klass->sizes.class_size = 0;
11393 klass->min_align = klass->parent->min_align;
11394 /* if the type has no fields we won't call the field_setup
11395 * routine which sets up klass->has_references.
11397 klass->has_references |= klass->parent->has_references;
11399 klass->instance_size = sizeof (MonoObject);
11400 klass->min_align = 1;
11403 /* FIXME: handle packing_size and instance_size */
11404 typebuilder_setup_fields (klass, &error);
11405 if (!mono_error_ok (&error))
11407 typebuilder_setup_properties (klass, &error);
11408 if (!mono_error_ok (&error))
11411 typebuilder_setup_events (klass, &error);
11412 if (!mono_error_ok (&error))
11415 klass->wastypebuilder = TRUE;
11418 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11419 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11420 * we want to return normal System.MonoType objects, so clear these out from the cache.
11422 * Together with this we must ensure the contents of all instances to match the created type.
11424 if (domain->type_hash && klass->generic_container)
11425 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11427 mono_domain_unlock (domain);
11428 mono_loader_unlock ();
11430 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11431 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11432 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11435 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11436 g_assert (res != (MonoReflectionType*)tb);
11441 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11442 klass->wastypebuilder = TRUE;
11443 mono_domain_unlock (domain);
11444 mono_loader_unlock ();
11445 mono_error_raise_exception (&error);
11450 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11452 MonoGenericParamFull *param;
11456 MONO_ARCH_SAVE_REGS;
11458 param = g_new0 (MonoGenericParamFull, 1);
11460 if (gparam->mbuilder) {
11461 if (!gparam->mbuilder->generic_container) {
11462 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11463 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11464 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11465 gparam->mbuilder->generic_container->is_method = TRUE;
11467 * Cannot set owner.method, since the MonoMethod is not created yet.
11468 * Set the image field instead, so type_in_image () works.
11470 gparam->mbuilder->generic_container->image = klass->image;
11472 param->param.owner = gparam->mbuilder->generic_container;
11473 } else if (gparam->tbuilder) {
11474 if (!gparam->tbuilder->generic_container) {
11475 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11476 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11477 gparam->tbuilder->generic_container->owner.klass = klass;
11479 param->param.owner = gparam->tbuilder->generic_container;
11482 param->info.name = mono_string_to_utf8 (gparam->name);
11483 param->param.num = gparam->index;
11485 image = &gparam->tbuilder->module->dynamic_image->image;
11486 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11488 gparam->type.type = &pklass->byval_arg;
11490 mono_class_set_ref_info (pklass, gparam);
11491 mono_image_lock (image);
11492 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11493 mono_image_unlock (image);
11497 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11499 MonoReflectionModuleBuilder *module = sig->module;
11500 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11501 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11506 check_array_for_usertypes (sig->arguments);
11508 sigbuffer_init (&buf, 32);
11510 sigbuffer_add_value (&buf, 0x07);
11511 sigbuffer_add_value (&buf, na);
11512 if (assembly != NULL){
11513 for (i = 0; i < na; ++i) {
11514 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11515 encode_reflection_type (assembly, type, &buf);
11519 buflen = buf.p - buf.buf;
11520 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11521 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11522 sigbuffer_free (&buf);
11528 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11530 MonoDynamicImage *assembly = sig->module->dynamic_image;
11531 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11536 check_array_for_usertypes (sig->arguments);
11538 sigbuffer_init (&buf, 32);
11540 sigbuffer_add_value (&buf, 0x06);
11541 for (i = 0; i < na; ++i) {
11542 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11543 encode_reflection_type (assembly, type, &buf);
11546 buflen = buf.p - buf.buf;
11547 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11548 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11549 sigbuffer_free (&buf);
11555 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11557 ReflectionMethodBuilder rmb;
11558 MonoMethodSignature *sig;
11563 sig = dynamic_method_to_signature (mb);
11565 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11568 * Resolve references.
11571 * Every second entry in the refs array is reserved for storing handle_class,
11572 * which is needed by the ldtoken implementation in the JIT.
11574 rmb.nrefs = mb->nrefs;
11575 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11576 for (i = 0; i < mb->nrefs; i += 2) {
11577 MonoClass *handle_class;
11579 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11581 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11582 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11584 * The referenced DynamicMethod should already be created by the managed
11585 * code, except in the case of circular references. In that case, we store
11586 * method in the refs array, and fix it up later when the referenced
11587 * DynamicMethod is created.
11589 if (method->mhandle) {
11590 ref = method->mhandle;
11592 /* FIXME: GC object stored in unmanaged memory */
11595 /* FIXME: GC object stored in unmanaged memory */
11596 method->referenced_by = g_slist_append (method->referenced_by, mb);
11598 handle_class = mono_defaults.methodhandle_class;
11600 MonoException *ex = NULL;
11601 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11603 ex = mono_get_exception_type_load (NULL, NULL);
11604 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11605 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11609 mono_raise_exception (ex);
11614 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11615 rmb.refs [i + 1] = handle_class;
11618 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11620 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11622 /* Fix up refs entries pointing at us */
11623 for (l = mb->referenced_by; l; l = l->next) {
11624 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11625 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11628 g_assert (method->mhandle);
11630 data = (gpointer*)wrapper->method_data;
11631 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11632 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11633 data [i + 1] = mb->mhandle;
11636 g_slist_free (mb->referenced_by);
11640 /* ilgen is no longer needed */
11644 #endif /* DISABLE_REFLECTION_EMIT */
11647 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11652 mono_runtime_free_method (
11653 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11658 * mono_reflection_is_valid_dynamic_token:
11660 * Returns TRUE if token is valid.
11664 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11666 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11669 MonoMethodSignature *
11670 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11672 MonoMethodSignature *sig;
11673 g_assert (image->dynamic);
11675 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11679 return mono_method_signature (method);
11682 #ifndef DISABLE_REFLECTION_EMIT
11685 * mono_reflection_lookup_dynamic_token:
11687 * Finish the Builder object pointed to by TOKEN and return the corresponding
11688 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11689 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11692 * LOCKING: Take the loader lock
11695 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11697 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11701 mono_loader_lock ();
11702 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11703 mono_loader_unlock ();
11706 g_error ("Could not find required dynamic token 0x%08x", token);
11712 handle_class = &klass;
11713 return resolve_object (image, obj, handle_class, context);
11717 * ensure_complete_type:
11719 * Ensure that KLASS is completed if it is a dynamic type, or references
11723 ensure_complete_type (MonoClass *klass)
11725 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11726 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11728 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11730 // Asserting here could break a lot of code
11731 //g_assert (klass->wastypebuilder);
11734 if (klass->generic_class) {
11735 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11738 for (i = 0; i < inst->type_argc; ++i) {
11739 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11745 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11747 gpointer result = NULL;
11749 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11750 result = mono_string_intern ((MonoString*)obj);
11751 *handle_class = mono_defaults.string_class;
11753 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11754 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11755 MonoClass *mc = mono_class_from_mono_type (type);
11756 if (!mono_class_init (mc))
11757 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11760 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11761 result = mono_class_from_mono_type (inflated);
11762 mono_metadata_free_type (inflated);
11764 result = mono_class_from_mono_type (type);
11766 *handle_class = mono_defaults.typehandle_class;
11768 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11769 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11770 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11771 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11772 result = ((MonoReflectionMethod*)obj)->method;
11774 result = mono_class_inflate_generic_method (result, context);
11775 *handle_class = mono_defaults.methodhandle_class;
11777 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11778 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11779 result = mb->mhandle;
11781 /* Type is not yet created */
11782 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11784 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11787 * Hopefully this has been filled in by calling CreateType() on the
11791 * TODO: This won't work if the application finishes another
11792 * TypeBuilder instance instead of this one.
11794 result = mb->mhandle;
11797 result = mono_class_inflate_generic_method (result, context);
11798 *handle_class = mono_defaults.methodhandle_class;
11799 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11800 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11802 result = cb->mhandle;
11804 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11806 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11807 result = cb->mhandle;
11810 result = mono_class_inflate_generic_method (result, context);
11811 *handle_class = mono_defaults.methodhandle_class;
11812 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11813 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11815 ensure_complete_type (field->parent);
11817 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11818 MonoClass *class = mono_class_from_mono_type (inflated);
11819 MonoClassField *inflated_field;
11820 gpointer iter = NULL;
11821 mono_metadata_free_type (inflated);
11822 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11823 if (!strcmp (field->name, inflated_field->name))
11826 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11827 result = inflated_field;
11831 *handle_class = mono_defaults.fieldhandle_class;
11833 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11834 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11835 result = fb->handle;
11838 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11840 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11841 result = fb->handle;
11844 if (fb->handle && fb->handle->parent->generic_container) {
11845 MonoClass *klass = fb->handle->parent;
11846 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11847 MonoClass *inflated = mono_class_from_mono_type (type);
11849 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11851 mono_metadata_free_type (type);
11853 *handle_class = mono_defaults.fieldhandle_class;
11854 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11855 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11856 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11859 klass = type->data.klass;
11860 if (klass->wastypebuilder) {
11861 /* Already created */
11865 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11866 result = type->data.klass;
11869 *handle_class = mono_defaults.typehandle_class;
11870 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11871 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11872 MonoMethodSignature *sig;
11875 if (helper->arguments)
11876 nargs = mono_array_length (helper->arguments);
11880 sig = mono_metadata_signature_alloc (image, nargs);
11881 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11882 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11884 if (helper->unmanaged_call_conv) { /* unmanaged */
11885 sig->call_convention = helper->unmanaged_call_conv - 1;
11886 sig->pinvoke = TRUE;
11887 } else if (helper->call_conv & 0x02) {
11888 sig->call_convention = MONO_CALL_VARARG;
11890 sig->call_convention = MONO_CALL_DEFAULT;
11893 sig->param_count = nargs;
11894 /* TODO: Copy type ? */
11895 sig->ret = helper->return_type->type;
11896 for (i = 0; i < nargs; ++i)
11897 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11900 *handle_class = NULL;
11901 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11902 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11903 /* Already created by the managed code */
11904 g_assert (method->mhandle);
11905 result = method->mhandle;
11906 *handle_class = mono_defaults.methodhandle_class;
11907 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11908 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11909 type = mono_class_inflate_generic_type (type, context);
11910 result = mono_class_from_mono_type (type);
11911 *handle_class = mono_defaults.typehandle_class;
11913 mono_metadata_free_type (type);
11914 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11915 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11916 type = mono_class_inflate_generic_type (type, context);
11917 result = mono_class_from_mono_type (type);
11918 *handle_class = mono_defaults.typehandle_class;
11920 mono_metadata_free_type (type);
11921 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11922 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11923 MonoClass *inflated;
11925 MonoClassField *field;
11927 if (is_sre_field_builder (mono_object_class (f->fb)))
11928 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11929 else if (is_sr_mono_field (mono_object_class (f->fb)))
11930 field = ((MonoReflectionField*)f->fb)->field;
11932 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
11934 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11935 inflated = mono_class_from_mono_type (type);
11937 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11938 ensure_complete_type (field->parent);
11940 mono_metadata_free_type (type);
11941 *handle_class = mono_defaults.fieldhandle_class;
11942 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11943 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11944 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11945 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11946 MonoMethod *method;
11948 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11949 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11950 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11951 method = ((MonoReflectionMethod *)c->cb)->method;
11953 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
11955 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11956 *handle_class = mono_defaults.methodhandle_class;
11957 mono_metadata_free_type (type);
11958 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11959 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11960 if (m->method_args) {
11961 result = mono_reflection_method_on_tb_inst_get_handle (m);
11963 result = mono_class_inflate_generic_method (result, context);
11965 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11966 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11967 MonoMethod *method;
11969 if (is_sre_method_builder (mono_object_class (m->mb)))
11970 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11971 else if (is_sr_mono_method (mono_object_class (m->mb)))
11972 method = ((MonoReflectionMethod *)m->mb)->method;
11974 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11976 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11977 mono_metadata_free_type (type);
11979 *handle_class = mono_defaults.methodhandle_class;
11980 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11981 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11984 MonoMethod *method;
11988 mtype = mono_reflection_type_get_handle (m->parent);
11989 klass = mono_class_from_mono_type (mtype);
11991 /* Find the method */
11993 name = mono_string_to_utf8 (m->name);
11995 while ((method = mono_class_get_methods (klass, &iter))) {
11996 if (!strcmp (method->name, name))
12003 // FIXME: Check parameters/return value etc. match
12006 *handle_class = mono_defaults.methodhandle_class;
12007 } else if (is_sre_array (mono_object_get_class(obj)) ||
12008 is_sre_byref (mono_object_get_class(obj)) ||
12009 is_sre_pointer (mono_object_get_class(obj))) {
12010 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12011 MonoType *type = mono_reflection_type_get_handle (ref_type);
12012 result = mono_class_from_mono_type (type);
12013 *handle_class = mono_defaults.typehandle_class;
12015 g_print ("%s\n", obj->vtable->klass->name);
12016 g_assert_not_reached ();
12021 #else /* DISABLE_REFLECTION_EMIT */
12024 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12026 g_assert_not_reached ();
12031 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12033 g_assert_not_reached ();
12037 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12039 g_assert_not_reached ();
12043 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12045 g_assert_not_reached ();
12049 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12051 g_assert_not_reached ();
12055 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12057 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12061 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12063 g_assert_not_reached ();
12067 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12069 g_assert_not_reached ();
12072 MonoReflectionModule *
12073 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12075 g_assert_not_reached ();
12080 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12082 g_assert_not_reached ();
12087 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12089 g_assert_not_reached ();
12094 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12095 gboolean create_open_instance, gboolean register_token)
12097 g_assert_not_reached ();
12102 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12107 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12108 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12111 g_assert_not_reached ();
12115 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12118 *num_overrides = 0;
12121 MonoReflectionEvent *
12122 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12124 g_assert_not_reached ();
12128 MonoReflectionType*
12129 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12131 g_assert_not_reached ();
12136 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12138 g_assert_not_reached ();
12142 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12144 g_assert_not_reached ();
12149 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12151 g_assert_not_reached ();
12156 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12161 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12167 mono_reflection_type_get_handle (MonoReflectionType* ref)
12175 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12177 g_assert_not_reached ();
12180 #endif /* DISABLE_REFLECTION_EMIT */
12182 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12183 const static guint32 declsec_flags_map[] = {
12184 0x00000000, /* empty */
12185 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12186 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12187 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12188 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12189 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12190 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12191 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12192 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12193 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12194 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12195 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12196 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12197 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12198 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12199 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12200 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12201 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12202 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12206 * Returns flags that includes all available security action associated to the handle.
12207 * @token: metadata token (either for a class or a method)
12208 * @image: image where resides the metadata.
12211 mono_declsec_get_flags (MonoImage *image, guint32 token)
12213 int index = mono_metadata_declsec_from_index (image, token);
12214 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12215 guint32 result = 0;
12219 /* HasSecurity can be present for other, not specially encoded, attributes,
12220 e.g. SuppressUnmanagedCodeSecurityAttribute */
12224 for (i = index; i < t->rows; i++) {
12225 guint32 cols [MONO_DECL_SECURITY_SIZE];
12227 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12228 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12231 action = cols [MONO_DECL_SECURITY_ACTION];
12232 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12233 result |= declsec_flags_map [action];
12235 g_assert_not_reached ();
12242 * Get the security actions (in the form of flags) associated with the specified method.
12244 * @method: The method for which we want the declarative security flags.
12245 * Return the declarative security flags for the method (only).
12247 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12248 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12251 mono_declsec_flags_from_method (MonoMethod *method)
12253 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12254 /* FIXME: No cache (for the moment) */
12255 guint32 idx = mono_method_get_index (method);
12256 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12257 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12258 return mono_declsec_get_flags (method->klass->image, idx);
12264 * Get the security actions (in the form of flags) associated with the specified class.
12266 * @klass: The class for which we want the declarative security flags.
12267 * Return the declarative security flags for the class.
12269 * Note: We cache the flags inside the MonoClass structure as this will get
12270 * called very often (at least for each method).
12273 mono_declsec_flags_from_class (MonoClass *klass)
12275 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12276 if (!klass->ext || !klass->ext->declsec_flags) {
12279 idx = mono_metadata_token_index (klass->type_token);
12280 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12281 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12282 mono_loader_lock ();
12283 mono_class_alloc_ext (klass);
12284 mono_loader_unlock ();
12285 /* we cache the flags on classes */
12286 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12288 return klass->ext->declsec_flags;
12294 * Get the security actions (in the form of flags) associated with the specified assembly.
12296 * @assembly: The assembly for which we want the declarative security flags.
12297 * Return the declarative security flags for the assembly.
12300 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12302 guint32 idx = 1; /* there is only one assembly */
12303 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12304 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12305 return mono_declsec_get_flags (assembly->image, idx);
12310 * Fill actions for the specific index (which may either be an encoded class token or
12311 * an encoded method token) from the metadata image.
12312 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12315 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12316 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12318 MonoBoolean result = FALSE;
12320 guint32 cols [MONO_DECL_SECURITY_SIZE];
12321 int index = mono_metadata_declsec_from_index (image, token);
12324 t = &image->tables [MONO_TABLE_DECLSECURITY];
12325 for (i = index; i < t->rows; i++) {
12326 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12328 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12331 /* if present only replace (class) permissions with method permissions */
12332 /* if empty accept either class or method permissions */
12333 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12334 if (!actions->demand.blob) {
12335 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12336 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12337 actions->demand.blob = (char*) (blob + 2);
12338 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12341 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12342 if (!actions->noncasdemand.blob) {
12343 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12344 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12345 actions->noncasdemand.blob = (char*) (blob + 2);
12346 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12349 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12350 if (!actions->demandchoice.blob) {
12351 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12352 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12353 actions->demandchoice.blob = (char*) (blob + 2);
12354 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12364 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12365 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12367 guint32 idx = mono_metadata_token_index (klass->type_token);
12368 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12369 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12370 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12374 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12375 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12377 guint32 idx = mono_method_get_index (method);
12378 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12379 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12380 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12384 * Collect all actions (that requires to generate code in mini) assigned for
12385 * the specified method.
12386 * Note: Don't use the content of actions if the function return FALSE.
12389 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12391 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12392 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12393 MonoBoolean result = FALSE;
12396 /* quick exit if no declarative security is present in the metadata */
12397 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12400 /* we want the original as the wrapper is "free" of the security informations */
12401 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12402 method = mono_marshal_method_from_wrapper (method);
12407 /* First we look for method-level attributes */
12408 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12409 mono_class_init (method->klass);
12410 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12412 result = mono_declsec_get_method_demands_params (method, demands,
12413 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12416 /* Here we use (or create) the class declarative cache to look for demands */
12417 flags = mono_declsec_flags_from_class (method->klass);
12418 if (flags & mask) {
12420 mono_class_init (method->klass);
12421 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12423 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12424 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12427 /* The boolean return value is used as a shortcut in case nothing needs to
12428 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12434 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12436 * Note: Don't use the content of actions if the function return FALSE.
12439 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12441 MonoBoolean result = FALSE;
12444 /* quick exit if no declarative security is present in the metadata */
12445 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12448 /* we want the original as the wrapper is "free" of the security informations */
12449 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12450 method = mono_marshal_method_from_wrapper (method);
12455 /* results are independant - zeroize both */
12456 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12457 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12459 /* First we look for method-level attributes */
12460 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12461 mono_class_init (method->klass);
12463 result = mono_declsec_get_method_demands_params (method, cmethod,
12464 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12467 /* Here we use (or create) the class declarative cache to look for demands */
12468 flags = mono_declsec_flags_from_class (method->klass);
12469 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12470 mono_class_init (method->klass);
12472 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12473 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12480 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12482 * @klass The inherited class - this is the class that provides the security check (attributes)
12484 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12486 * Note: Don't use the content of actions if the function return FALSE.
12489 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12491 MonoBoolean result = FALSE;
12494 /* quick exit if no declarative security is present in the metadata */
12495 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12498 /* Here we use (or create) the class declarative cache to look for demands */
12499 flags = mono_declsec_flags_from_class (klass);
12500 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12501 mono_class_init (klass);
12502 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12504 result |= mono_declsec_get_class_demands_params (klass, demands,
12505 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12512 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12514 * Note: Don't use the content of actions if the function return FALSE.
12517 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12519 /* quick exit if no declarative security is present in the metadata */
12520 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12523 /* we want the original as the wrapper is "free" of the security informations */
12524 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12525 method = mono_marshal_method_from_wrapper (method);
12530 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12531 mono_class_init (method->klass);
12532 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12534 return mono_declsec_get_method_demands_params (method, demands,
12535 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12542 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12544 guint32 cols [MONO_DECL_SECURITY_SIZE];
12548 int index = mono_metadata_declsec_from_index (image, token);
12552 t = &image->tables [MONO_TABLE_DECLSECURITY];
12553 for (i = index; i < t->rows; i++) {
12554 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12556 /* shortcut - index are ordered */
12557 if (token != cols [MONO_DECL_SECURITY_PARENT])
12560 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12561 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12562 entry->blob = (char*) (metadata + 2);
12563 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12572 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12574 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12575 guint32 idx = mono_method_get_index (method);
12576 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12577 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12578 return get_declsec_action (method->klass->image, idx, action, entry);
12584 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12587 guint32 flags = mono_declsec_flags_from_class (klass);
12588 if (declsec_flags_map [action] & flags) {
12589 guint32 idx = mono_metadata_token_index (klass->type_token);
12590 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12591 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12592 return get_declsec_action (klass->image, idx, action, entry);
12598 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12600 guint32 idx = 1; /* there is only one assembly */
12601 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12602 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12604 return get_declsec_action (assembly->image, idx, action, entry);
12608 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12610 MonoObject *res, *exc;
12612 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12613 static MonoMethod *method = NULL;
12615 if (!System_Reflection_Emit_TypeBuilder) {
12616 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12617 g_assert (System_Reflection_Emit_TypeBuilder);
12619 if (method == NULL) {
12620 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12625 * The result of mono_type_get_object () might be a System.MonoType but we
12626 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12628 g_assert (mono_class_get_ref_info (klass));
12629 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12631 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12633 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12637 return *(MonoBoolean*)mono_object_unbox (res);