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)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
199 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
200 __type = mono_reflection_type_resolve_user_types (__type); \
201 mono_array_set (arr, MonoReflectionType*, index, __type); \
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
218 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
219 static GPtrArray *dynamic_images;
220 static mono_mutex_t dynamic_images_mutex;
223 dynamic_images_lock (void)
225 mono_mutex_lock (&dynamic_images_mutex);
229 dynamic_images_unlock (void)
231 mono_mutex_unlock (&dynamic_images_mutex);
235 * mono_find_dynamic_image_owner:
237 * Find the dynamic image, if any, which a given pointer is located in the memory of.
240 mono_find_dynamic_image_owner (void *ptr)
242 MonoImage *owner = NULL;
245 dynamic_images_lock ();
249 for (i = 0; !owner && i < dynamic_images->len; ++i) {
250 MonoImage *image = g_ptr_array_index (dynamic_images, i);
251 if (mono_mempool_contains_addr (image->mempool, ptr))
256 dynamic_images_unlock ();
262 mono_reflection_init (void)
267 dynamic_image_lock (MonoDynamicImage *image)
270 mono_image_lock ((MonoImage*)image);
271 MONO_FINISH_TRY_BLOCKING;
275 dynamic_image_unlock (MonoDynamicImage *image)
277 mono_image_unlock ((MonoImage*)image);
281 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
283 MONO_REQ_GC_UNSAFE_MODE;
285 dynamic_image_lock (assembly);
286 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
287 dynamic_image_unlock (assembly);
291 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
293 MONO_REQ_GC_UNSAFE_MODE;
297 dynamic_image_lock (assembly);
298 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
299 dynamic_image_unlock (assembly);
305 sigbuffer_init (SigBuffer *buf, int size)
307 MONO_REQ_GC_NEUTRAL_MODE;
309 buf->buf = g_malloc (size);
311 buf->end = buf->buf + size;
315 sigbuffer_make_room (SigBuffer *buf, int size)
317 MONO_REQ_GC_NEUTRAL_MODE;
319 if (buf->end - buf->p < size) {
320 int new_size = buf->end - buf->buf + size + 32;
321 char *p = g_realloc (buf->buf, new_size);
322 size = buf->p - buf->buf;
325 buf->end = buf->buf + new_size;
330 sigbuffer_add_value (SigBuffer *buf, guint32 val)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 sigbuffer_make_room (buf, 6);
335 mono_metadata_encode_value (val, buf->p, &buf->p);
339 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
341 MONO_REQ_GC_NEUTRAL_MODE;
343 sigbuffer_make_room (buf, 1);
349 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
351 MONO_REQ_GC_NEUTRAL_MODE;
353 sigbuffer_make_room (buf, size);
354 memcpy (buf->p, p, size);
359 sigbuffer_free (SigBuffer *buf)
361 MONO_REQ_GC_NEUTRAL_MODE;
366 #ifndef DISABLE_REFLECTION_EMIT
370 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
374 image_g_malloc (MonoImage *image, guint size)
376 MONO_REQ_GC_NEUTRAL_MODE;
379 return mono_image_alloc (image, size);
381 return g_malloc (size);
383 #endif /* !DISABLE_REFLECTION_EMIT */
388 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
392 image_g_malloc0 (MonoImage *image, guint size)
394 MONO_REQ_GC_NEUTRAL_MODE;
397 return mono_image_alloc0 (image, size);
399 return g_malloc0 (size);
402 #ifndef DISABLE_REFLECTION_EMIT
404 image_strdup (MonoImage *image, const char *s)
406 MONO_REQ_GC_NEUTRAL_MODE;
409 return mono_image_strdup (image, s);
415 #define image_g_new(image,struct_type, n_structs) \
416 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
418 #define image_g_new0(image,struct_type, n_structs) \
419 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
423 alloc_table (MonoDynamicTable *table, guint nrows)
425 MONO_REQ_GC_NEUTRAL_MODE;
428 g_assert (table->columns);
429 if (nrows + 1 >= table->alloc_rows) {
430 while (nrows + 1 >= table->alloc_rows) {
431 if (table->alloc_rows == 0)
432 table->alloc_rows = 16;
434 table->alloc_rows *= 2;
437 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
442 make_room_in_stream (MonoDynamicStream *stream, int size)
444 MONO_REQ_GC_NEUTRAL_MODE;
446 if (size <= stream->alloc_size)
449 while (stream->alloc_size <= size) {
450 if (stream->alloc_size < 4096)
451 stream->alloc_size = 4096;
453 stream->alloc_size *= 2;
456 stream->data = g_realloc (stream->data, stream->alloc_size);
460 string_heap_insert (MonoDynamicStream *sh, const char *str)
462 MONO_REQ_GC_NEUTRAL_MODE;
466 gpointer oldkey, oldval;
468 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
469 return GPOINTER_TO_UINT (oldval);
471 len = strlen (str) + 1;
474 make_room_in_stream (sh, idx + len);
477 * We strdup the string even if we already copy them in sh->data
478 * so that the string pointers in the hash remain valid even if
479 * we need to realloc sh->data. We may want to avoid that later.
481 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
482 memcpy (sh->data + idx, str, len);
488 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
490 MONO_REQ_GC_UNSAFE_MODE;
492 char *name = mono_string_to_utf8 (str);
494 idx = string_heap_insert (sh, name);
499 #ifndef DISABLE_REFLECTION_EMIT
501 string_heap_init (MonoDynamicStream *sh)
503 MONO_REQ_GC_NEUTRAL_MODE;
506 sh->alloc_size = 4096;
507 sh->data = g_malloc (4096);
508 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
509 string_heap_insert (sh, "");
514 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
516 MONO_REQ_GC_NEUTRAL_MODE;
520 make_room_in_stream (stream, stream->index + len);
521 memcpy (stream->data + stream->index, data, len);
523 stream->index += len;
525 * align index? Not without adding an additional param that controls it since
526 * we may store a blob value in pieces.
532 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
534 MONO_REQ_GC_NEUTRAL_MODE;
538 make_room_in_stream (stream, stream->index + len);
539 memset (stream->data + stream->index, 0, len);
541 stream->index += len;
546 stream_data_align (MonoDynamicStream *stream)
548 MONO_REQ_GC_NEUTRAL_MODE;
551 guint32 count = stream->index % 4;
553 /* we assume the stream data will be aligned */
555 mono_image_add_stream_data (stream, buf, 4 - count);
558 #ifndef DISABLE_REFLECTION_EMIT
560 mono_blob_entry_hash (const char* str)
562 MONO_REQ_GC_NEUTRAL_MODE;
566 len = mono_metadata_decode_blob_size (str, &str);
570 for (str += 1; str < end; str++)
571 h = (h << 5) - h + *str;
579 mono_blob_entry_equal (const char *str1, const char *str2) {
580 MONO_REQ_GC_NEUTRAL_MODE;
585 len = mono_metadata_decode_blob_size (str1, &end1);
586 len2 = mono_metadata_decode_blob_size (str2, &end2);
589 return memcmp (end1, end2, len) == 0;
593 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
595 MONO_REQ_GC_NEUTRAL_MODE;
599 gpointer oldkey, oldval;
601 copy = g_malloc (s1+s2);
602 memcpy (copy, b1, s1);
603 memcpy (copy + s1, b2, s2);
604 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
606 idx = GPOINTER_TO_UINT (oldval);
608 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
609 mono_image_add_stream_data (&assembly->blob, b2, s2);
610 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
616 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
618 MONO_REQ_GC_NEUTRAL_MODE;
622 guint32 size = buf->p - buf->buf;
624 g_assert (size <= (buf->end - buf->buf));
625 mono_metadata_encode_value (size, b, &b);
626 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
630 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
631 * dest may be misaligned.
634 swap_with_size (char *dest, const char* val, int len, int nelem) {
635 MONO_REQ_GC_NEUTRAL_MODE;
636 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
639 for (elem = 0; elem < nelem; ++elem) {
665 g_assert_not_reached ();
671 memcpy (dest, val, len * nelem);
676 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
678 MONO_REQ_GC_UNSAFE_MODE;
682 guint32 idx = 0, len;
684 len = str->length * 2;
685 mono_metadata_encode_value (len, b, &b);
686 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
688 char *swapped = g_malloc (2 * mono_string_length (str));
689 const char *p = (const char*)mono_string_chars (str);
691 swap_with_size (swapped, p, 2, mono_string_length (str));
692 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
701 #ifndef DISABLE_REFLECTION_EMIT
703 default_class_from_mono_type (MonoType *type)
705 MONO_REQ_GC_NEUTRAL_MODE;
707 switch (type->type) {
708 case MONO_TYPE_OBJECT:
709 return mono_defaults.object_class;
711 return mono_defaults.void_class;
712 case MONO_TYPE_BOOLEAN:
713 return mono_defaults.boolean_class;
715 return mono_defaults.char_class;
717 return mono_defaults.sbyte_class;
719 return mono_defaults.byte_class;
721 return mono_defaults.int16_class;
723 return mono_defaults.uint16_class;
725 return mono_defaults.int32_class;
727 return mono_defaults.uint32_class;
729 return mono_defaults.int_class;
731 return mono_defaults.uint_class;
733 return mono_defaults.int64_class;
735 return mono_defaults.uint64_class;
737 return mono_defaults.single_class;
739 return mono_defaults.double_class;
740 case MONO_TYPE_STRING:
741 return mono_defaults.string_class;
743 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
744 g_assert_not_reached ();
752 * mono_class_get_ref_info:
754 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
757 mono_class_get_ref_info (MonoClass *klass)
759 MONO_REQ_GC_UNSAFE_MODE;
761 if (klass->ref_info_handle == 0)
764 return mono_gchandle_get_target (klass->ref_info_handle);
768 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
770 MONO_REQ_GC_UNSAFE_MODE;
772 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
773 g_assert (klass->ref_info_handle != 0);
777 mono_class_free_ref_info (MonoClass *klass)
779 MONO_REQ_GC_NEUTRAL_MODE;
781 if (klass->ref_info_handle) {
782 mono_gchandle_free (klass->ref_info_handle);
783 klass->ref_info_handle = 0;
788 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
790 MONO_REQ_GC_NEUTRAL_MODE;
793 MonoGenericInst *class_inst;
798 class_inst = gclass->context.class_inst;
800 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
801 klass = gclass->container_class;
802 sigbuffer_add_value (buf, klass->byval_arg.type);
803 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
805 sigbuffer_add_value (buf, class_inst->type_argc);
806 for (i = 0; i < class_inst->type_argc; ++i)
807 encode_type (assembly, class_inst->type_argv [i], buf);
812 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
814 MONO_REQ_GC_NEUTRAL_MODE;
817 g_assert_not_reached ();
822 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
826 case MONO_TYPE_BOOLEAN:
840 case MONO_TYPE_STRING:
841 case MONO_TYPE_OBJECT:
842 case MONO_TYPE_TYPEDBYREF:
843 sigbuffer_add_value (buf, type->type);
846 sigbuffer_add_value (buf, type->type);
847 encode_type (assembly, type->data.type, buf);
849 case MONO_TYPE_SZARRAY:
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, &type->data.klass->byval_arg, buf);
853 case MONO_TYPE_VALUETYPE:
854 case MONO_TYPE_CLASS: {
855 MonoClass *k = mono_class_from_mono_type (type);
857 if (k->generic_container) {
858 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
859 encode_generic_class (assembly, gclass, buf);
862 * Make sure we use the correct type.
864 sigbuffer_add_value (buf, k->byval_arg.type);
866 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
867 * otherwise two typerefs could point to the same type, leading to
868 * verification errors.
870 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
874 case MONO_TYPE_ARRAY:
875 sigbuffer_add_value (buf, type->type);
876 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
877 sigbuffer_add_value (buf, type->data.array->rank);
878 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
879 sigbuffer_add_value (buf, 0);
881 case MONO_TYPE_GENERICINST:
882 encode_generic_class (assembly, type->data.generic_class, buf);
886 sigbuffer_add_value (buf, type->type);
887 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
890 g_error ("need to encode type %x", type->type);
895 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
897 MONO_REQ_GC_UNSAFE_MODE;
900 sigbuffer_add_value (buf, MONO_TYPE_VOID);
904 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
908 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
910 MONO_REQ_GC_UNSAFE_MODE;
915 for (i = 0; i < mono_array_length (modreq); ++i) {
916 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
917 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
918 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
922 for (i = 0; i < mono_array_length (modopt); ++i) {
923 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
924 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
925 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
930 #ifndef DISABLE_REFLECTION_EMIT
932 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
934 MONO_REQ_GC_UNSAFE_MODE;
938 guint32 nparams = sig->param_count;
944 sigbuffer_init (&buf, 32);
946 * FIXME: vararg, explicit_this, differenc call_conv values...
948 idx = sig->call_convention;
950 idx |= 0x20; /* hasthis */
951 if (sig->generic_param_count)
952 idx |= 0x10; /* generic */
953 sigbuffer_add_byte (&buf, idx);
954 if (sig->generic_param_count)
955 sigbuffer_add_value (&buf, sig->generic_param_count);
956 sigbuffer_add_value (&buf, nparams);
957 encode_type (assembly, sig->ret, &buf);
958 for (i = 0; i < nparams; ++i) {
959 if (i == sig->sentinelpos)
960 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
961 encode_type (assembly, sig->params [i], &buf);
963 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
964 sigbuffer_free (&buf);
970 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
972 MONO_REQ_GC_UNSAFE_MODE;
975 * FIXME: reuse code from method_encode_signature().
979 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
980 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
981 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
984 sigbuffer_init (&buf, 32);
985 /* LAMESPEC: all the call conv spec is foobared */
986 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
987 if (mb->call_conv & 2)
988 idx |= 0x5; /* vararg */
989 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
990 idx |= 0x20; /* hasthis */
992 idx |= 0x10; /* generic */
993 sigbuffer_add_byte (&buf, idx);
995 sigbuffer_add_value (&buf, ngparams);
996 sigbuffer_add_value (&buf, nparams + notypes);
997 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
998 encode_reflection_type (assembly, mb->rtype, &buf);
999 for (i = 0; i < nparams; ++i) {
1000 MonoArray *modreq = NULL;
1001 MonoArray *modopt = NULL;
1002 MonoReflectionType *pt;
1004 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1005 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1006 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1007 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1008 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1009 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1010 encode_reflection_type (assembly, pt, &buf);
1013 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1014 for (i = 0; i < notypes; ++i) {
1015 MonoReflectionType *pt;
1017 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1018 encode_reflection_type (assembly, pt, &buf);
1021 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1022 sigbuffer_free (&buf);
1027 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1029 MONO_REQ_GC_UNSAFE_MODE;
1031 MonoDynamicTable *table;
1033 guint32 idx, sig_idx;
1034 guint nl = mono_array_length (ilgen->locals);
1038 sigbuffer_init (&buf, 32);
1039 sigbuffer_add_value (&buf, 0x07);
1040 sigbuffer_add_value (&buf, nl);
1041 for (i = 0; i < nl; ++i) {
1042 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1045 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1047 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1049 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1050 sigbuffer_free (&buf);
1052 if (assembly->standalonesig_cache == NULL)
1053 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1054 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1058 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1059 idx = table->next_idx ++;
1061 alloc_table (table, table->rows);
1062 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1064 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1066 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1072 method_count_clauses (MonoReflectionILGen *ilgen)
1074 MONO_REQ_GC_UNSAFE_MODE;
1076 guint32 num_clauses = 0;
1079 MonoILExceptionInfo *ex_info;
1080 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1081 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1082 if (ex_info->handlers)
1083 num_clauses += mono_array_length (ex_info->handlers);
1091 #ifndef DISABLE_REFLECTION_EMIT
1092 static MonoExceptionClause*
1093 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1095 MONO_REQ_GC_UNSAFE_MODE;
1097 MonoExceptionClause *clauses;
1098 MonoExceptionClause *clause;
1099 MonoILExceptionInfo *ex_info;
1100 MonoILExceptionBlock *ex_block;
1101 guint32 finally_start;
1102 int i, j, clause_index;;
1104 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1107 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1108 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1109 finally_start = ex_info->start + ex_info->len;
1110 if (!ex_info->handlers)
1112 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1113 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1114 clause = &(clauses [clause_index]);
1116 clause->flags = ex_block->type;
1117 clause->try_offset = ex_info->start;
1119 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1120 clause->try_len = finally_start - ex_info->start;
1122 clause->try_len = ex_info->len;
1123 clause->handler_offset = ex_block->start;
1124 clause->handler_len = ex_block->len;
1125 if (ex_block->extype) {
1126 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1128 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129 clause->data.filter_offset = ex_block->filter_offset;
1131 clause->data.filter_offset = 0;
1133 finally_start = ex_block->start + ex_block->len;
1141 #endif /* !DISABLE_REFLECTION_EMIT */
1144 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1146 MONO_REQ_GC_UNSAFE_MODE;
1151 gint32 max_stack, i;
1152 gint32 num_locals = 0;
1153 gint32 num_exception = 0;
1156 char fat_header [12];
1158 guint16 short_value;
1159 guint32 local_sig = 0;
1160 guint32 header_size = 12;
1163 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1164 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1168 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1170 code = mb->ilgen->code;
1171 code_size = mb->ilgen->code_len;
1172 max_stack = mb->ilgen->max_stack;
1173 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1174 if (mb->ilgen->ex_handlers)
1175 num_exception = method_count_clauses (mb->ilgen);
1179 char *name = mono_string_to_utf8 (mb->name);
1180 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1181 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1184 mono_raise_exception (exception);
1187 code_size = mono_array_length (code);
1188 max_stack = 8; /* we probably need to run a verifier on the code... */
1191 stream_data_align (&assembly->code);
1193 /* check for exceptions, maxstack, locals */
1194 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1196 if (code_size < 64 && !(code_size & 1)) {
1197 flags = (code_size << 2) | 0x2;
1198 } else if (code_size < 32 && (code_size & 1)) {
1199 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1203 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1204 /* add to the fixup todo list */
1205 if (mb->ilgen && mb->ilgen->num_token_fixups)
1206 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1207 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1208 return assembly->text_rva + idx;
1212 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1214 * FIXME: need to set also the header size in fat_flags.
1215 * (and more sects and init locals flags)
1219 fat_flags |= METHOD_HEADER_MORE_SECTS;
1220 if (mb->init_locals)
1221 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1222 fat_header [0] = fat_flags;
1223 fat_header [1] = (header_size / 4 ) << 4;
1224 short_value = GUINT16_TO_LE (max_stack);
1225 memcpy (fat_header + 2, &short_value, 2);
1226 int_value = GUINT32_TO_LE (code_size);
1227 memcpy (fat_header + 4, &int_value, 4);
1228 int_value = GUINT32_TO_LE (local_sig);
1229 memcpy (fat_header + 8, &int_value, 4);
1230 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1231 /* add to the fixup todo list */
1232 if (mb->ilgen && mb->ilgen->num_token_fixups)
1233 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1235 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1236 if (num_exception) {
1237 unsigned char sheader [4];
1238 MonoILExceptionInfo * ex_info;
1239 MonoILExceptionBlock * ex_block;
1242 stream_data_align (&assembly->code);
1243 /* always use fat format for now */
1244 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1245 num_exception *= 6 * sizeof (guint32);
1246 num_exception += 4; /* include the size of the header */
1247 sheader [1] = num_exception & 0xff;
1248 sheader [2] = (num_exception >> 8) & 0xff;
1249 sheader [3] = (num_exception >> 16) & 0xff;
1250 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1251 /* fat header, so we are already aligned */
1253 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1254 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1255 if (ex_info->handlers) {
1256 int finally_start = ex_info->start + ex_info->len;
1257 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1259 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1261 val = GUINT32_TO_LE (ex_block->type);
1262 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1264 val = GUINT32_TO_LE (ex_info->start);
1265 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1266 /* need fault, too, probably */
1267 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1268 val = GUINT32_TO_LE (finally_start - ex_info->start);
1270 val = GUINT32_TO_LE (ex_info->len);
1271 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1272 /* handler offset */
1273 val = GUINT32_TO_LE (ex_block->start);
1274 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276 val = GUINT32_TO_LE (ex_block->len);
1277 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1278 finally_start = ex_block->start + ex_block->len;
1279 if (ex_block->extype) {
1280 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1282 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1283 val = ex_block->filter_offset;
1287 val = GUINT32_TO_LE (val);
1288 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1289 /*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",
1290 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);*/
1293 g_error ("No clauses for ex info block %d", i);
1297 return assembly->text_rva + idx;
1301 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1303 MONO_REQ_GC_NEUTRAL_MODE;
1306 MonoDynamicTable *table;
1309 table = &assembly->tables [table_idx];
1311 g_assert (col < table->columns);
1313 values = table->values + table->columns;
1314 for (i = 1; i <= table->rows; ++i) {
1315 if (values [col] == token)
1317 values += table->columns;
1323 * LOCKING: Acquires the loader lock.
1325 static MonoCustomAttrInfo*
1326 lookup_custom_attr (MonoImage *image, gpointer member)
1328 MONO_REQ_GC_NEUTRAL_MODE;
1330 MonoCustomAttrInfo* res;
1332 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1337 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1343 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1345 MONO_REQ_GC_UNSAFE_MODE;
1347 /* FIXME: Need to do more checks */
1348 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1349 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1351 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1358 static MonoCustomAttrInfo*
1359 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1361 MONO_REQ_GC_UNSAFE_MODE;
1363 int i, index, count, not_visible;
1364 MonoCustomAttrInfo *ainfo;
1365 MonoReflectionCustomAttr *cattr;
1369 /* FIXME: check in assembly the Run flag is set */
1371 count = mono_array_length (cattrs);
1373 /* Skip nonpublic attributes since MS.NET seems to do the same */
1374 /* FIXME: This needs to be done more globally */
1376 for (i = 0; i < count; ++i) {
1377 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1378 if (!custom_attr_visible (image, cattr))
1381 count -= not_visible;
1383 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1385 ainfo->image = image;
1386 ainfo->num_attrs = count;
1387 ainfo->cached = alloc_img != NULL;
1389 for (i = 0; i < count; ++i) {
1390 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1391 if (custom_attr_visible (image, cattr)) {
1392 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1393 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1394 ainfo->attrs [index].ctor = cattr->ctor->method;
1395 ainfo->attrs [index].data = saved;
1396 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1404 #ifndef DISABLE_REFLECTION_EMIT
1406 * LOCKING: Acquires the loader lock.
1409 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1411 MONO_REQ_GC_UNSAFE_MODE;
1413 MonoCustomAttrInfo *ainfo, *tmp;
1415 if (!cattrs || !mono_array_length (cattrs))
1418 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1420 mono_loader_lock ();
1421 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1423 mono_custom_attrs_free (tmp);
1424 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1425 mono_loader_unlock ();
1431 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1433 MONO_REQ_GC_NEUTRAL_MODE;
1440 * idx is the table index of the object
1441 * type is one of MONO_CUSTOM_ATTR_*
1444 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1446 MONO_REQ_GC_UNSAFE_MODE;
1448 MonoDynamicTable *table;
1449 MonoReflectionCustomAttr *cattr;
1451 guint32 count, i, token;
1453 char *p = blob_size;
1455 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1458 count = mono_array_length (cattrs);
1459 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1460 table->rows += count;
1461 alloc_table (table, table->rows);
1462 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1463 idx <<= MONO_CUSTOM_ATTR_BITS;
1465 for (i = 0; i < count; ++i) {
1466 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1467 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1468 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1469 type = mono_metadata_token_index (token);
1470 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1471 switch (mono_metadata_token_table (token)) {
1472 case MONO_TABLE_METHOD:
1473 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1475 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1476 * method, not the one returned by mono_image_create_token ().
1478 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1480 case MONO_TABLE_MEMBERREF:
1481 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1484 g_warning ("got wrong token in custom attr");
1487 values [MONO_CUSTOM_ATTR_TYPE] = type;
1489 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1490 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1491 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1492 values += MONO_CUSTOM_ATTR_SIZE;
1498 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1500 MONO_REQ_GC_UNSAFE_MODE;
1502 MonoDynamicTable *table;
1504 guint32 count, i, idx;
1505 MonoReflectionPermissionSet *perm;
1510 count = mono_array_length (permissions);
1511 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1512 table->rows += count;
1513 alloc_table (table, table->rows);
1515 for (i = 0; i < mono_array_length (permissions); ++i) {
1516 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1518 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1520 idx = mono_metadata_token_index (parent_token);
1521 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1522 switch (mono_metadata_token_table (parent_token)) {
1523 case MONO_TABLE_TYPEDEF:
1524 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1526 case MONO_TABLE_METHOD:
1527 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1529 case MONO_TABLE_ASSEMBLY:
1530 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1533 g_assert_not_reached ();
1536 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1537 values [MONO_DECL_SECURITY_PARENT] = idx;
1538 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1545 * Fill in the MethodDef and ParamDef tables for a method.
1546 * This is used for both normal methods and constructors.
1549 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1551 MONO_REQ_GC_UNSAFE_MODE;
1553 MonoDynamicTable *table;
1557 /* room in this table is already allocated */
1558 table = &assembly->tables [MONO_TABLE_METHOD];
1559 *mb->table_idx = table->next_idx ++;
1560 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1561 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1562 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1563 values [MONO_METHOD_FLAGS] = mb->attrs;
1564 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1565 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1566 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1568 table = &assembly->tables [MONO_TABLE_PARAM];
1569 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1571 mono_image_add_decl_security (assembly,
1572 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1575 MonoDynamicTable *mtable;
1578 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1579 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1582 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1583 if (mono_array_get (mb->pinfo, gpointer, i))
1586 table->rows += count;
1587 alloc_table (table, table->rows);
1588 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1589 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1590 MonoReflectionParamBuilder *pb;
1591 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1592 values [MONO_PARAM_FLAGS] = pb->attrs;
1593 values [MONO_PARAM_SEQUENCE] = i;
1594 if (pb->name != NULL) {
1595 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1597 values [MONO_PARAM_NAME] = 0;
1599 values += MONO_PARAM_SIZE;
1600 if (pb->marshal_info) {
1602 alloc_table (mtable, mtable->rows);
1603 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1604 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1605 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1607 pb->table_idx = table->next_idx++;
1608 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1609 guint32 field_type = 0;
1610 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1612 alloc_table (mtable, mtable->rows);
1613 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1614 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1615 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1616 mvalues [MONO_CONSTANT_TYPE] = field_type;
1617 mvalues [MONO_CONSTANT_PADDING] = 0;
1624 #ifndef DISABLE_REFLECTION_EMIT
1626 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1628 MONO_REQ_GC_UNSAFE_MODE;
1630 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1632 rmb->ilgen = mb->ilgen;
1633 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1634 rmb->parameters = mb->parameters;
1635 rmb->generic_params = mb->generic_params;
1636 rmb->generic_container = mb->generic_container;
1637 rmb->opt_types = NULL;
1638 rmb->pinfo = mb->pinfo;
1639 rmb->attrs = mb->attrs;
1640 rmb->iattrs = mb->iattrs;
1641 rmb->call_conv = mb->call_conv;
1642 rmb->code = mb->code;
1643 rmb->type = mb->type;
1644 rmb->name = mb->name;
1645 rmb->table_idx = &mb->table_idx;
1646 rmb->init_locals = mb->init_locals;
1647 rmb->skip_visibility = FALSE;
1648 rmb->return_modreq = mb->return_modreq;
1649 rmb->return_modopt = mb->return_modopt;
1650 rmb->param_modreq = mb->param_modreq;
1651 rmb->param_modopt = mb->param_modopt;
1652 rmb->permissions = mb->permissions;
1653 rmb->mhandle = mb->mhandle;
1658 rmb->charset = mb->charset;
1659 rmb->extra_flags = mb->extra_flags;
1660 rmb->native_cc = mb->native_cc;
1661 rmb->dllentry = mb->dllentry;
1667 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1669 MONO_REQ_GC_UNSAFE_MODE;
1671 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1673 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1675 rmb->ilgen = mb->ilgen;
1676 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1677 rmb->parameters = mb->parameters;
1678 rmb->generic_params = NULL;
1679 rmb->generic_container = NULL;
1680 rmb->opt_types = NULL;
1681 rmb->pinfo = mb->pinfo;
1682 rmb->attrs = mb->attrs;
1683 rmb->iattrs = mb->iattrs;
1684 rmb->call_conv = mb->call_conv;
1686 rmb->type = mb->type;
1687 rmb->name = mono_string_new (mono_domain_get (), name);
1688 rmb->table_idx = &mb->table_idx;
1689 rmb->init_locals = mb->init_locals;
1690 rmb->skip_visibility = FALSE;
1691 rmb->return_modreq = NULL;
1692 rmb->return_modopt = NULL;
1693 rmb->param_modreq = mb->param_modreq;
1694 rmb->param_modopt = mb->param_modopt;
1695 rmb->permissions = mb->permissions;
1696 rmb->mhandle = mb->mhandle;
1702 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1704 MONO_REQ_GC_UNSAFE_MODE;
1706 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1708 rmb->ilgen = mb->ilgen;
1709 rmb->rtype = mb->rtype;
1710 rmb->parameters = mb->parameters;
1711 rmb->generic_params = NULL;
1712 rmb->generic_container = NULL;
1713 rmb->opt_types = NULL;
1715 rmb->attrs = mb->attrs;
1717 rmb->call_conv = mb->call_conv;
1719 rmb->type = (MonoObject *) mb->owner;
1720 rmb->name = mb->name;
1721 rmb->table_idx = NULL;
1722 rmb->init_locals = mb->init_locals;
1723 rmb->skip_visibility = mb->skip_visibility;
1724 rmb->return_modreq = NULL;
1725 rmb->return_modopt = NULL;
1726 rmb->param_modreq = NULL;
1727 rmb->param_modopt = NULL;
1728 rmb->permissions = NULL;
1729 rmb->mhandle = mb->mhandle;
1736 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1738 MONO_REQ_GC_UNSAFE_MODE;
1740 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1741 MonoDynamicTable *table;
1744 MonoReflectionMethod *m;
1747 if (!mb->override_methods)
1750 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1751 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1753 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1755 alloc_table (table, table->rows);
1756 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1757 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1758 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1760 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1761 switch (mono_metadata_token_table (tok)) {
1762 case MONO_TABLE_MEMBERREF:
1763 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1765 case MONO_TABLE_METHOD:
1766 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1769 g_assert_not_reached ();
1771 values [MONO_METHODIMPL_DECLARATION] = tok;
1775 #ifndef DISABLE_REFLECTION_EMIT
1777 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1779 MONO_REQ_GC_UNSAFE_MODE;
1781 MonoDynamicTable *table;
1783 ReflectionMethodBuilder rmb;
1786 reflection_methodbuilder_from_method_builder (&rmb, mb);
1788 mono_image_basic_method (&rmb, assembly);
1789 mb->table_idx = *rmb.table_idx;
1791 if (mb->dll) { /* It's a P/Invoke method */
1793 /* map CharSet values to on-disk values */
1794 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1795 int extra_flags = mb->extra_flags;
1796 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1798 alloc_table (table, table->rows);
1799 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1801 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1802 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1804 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1806 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1807 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1808 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1809 table = &assembly->tables [MONO_TABLE_MODULEREF];
1811 alloc_table (table, table->rows);
1812 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1813 values [MONO_IMPLMAP_SCOPE] = table->rows;
1817 if (mb->generic_params) {
1818 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1819 table->rows += mono_array_length (mb->generic_params);
1820 alloc_table (table, table->rows);
1821 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1822 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1824 mono_image_get_generic_param_info (
1825 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1832 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1834 MONO_REQ_GC_UNSAFE_MODE;
1836 ReflectionMethodBuilder rmb;
1838 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1840 mono_image_basic_method (&rmb, assembly);
1841 mb->table_idx = *rmb.table_idx;
1846 type_get_fully_qualified_name (MonoType *type)
1848 MONO_REQ_GC_NEUTRAL_MODE;
1850 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1854 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1856 MONO_REQ_GC_UNSAFE_MODE;
1861 klass = mono_class_from_mono_type (type);
1863 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1864 ta = klass->image->assembly;
1865 if (assembly_is_dynamic (ta) || (ta == ass)) {
1866 if (klass->generic_class || klass->generic_container)
1867 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1868 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1870 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1873 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1876 #ifndef DISABLE_REFLECTION_EMIT
1877 /*field_image is the image to which the eventual custom mods have been encoded against*/
1879 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1881 MONO_REQ_GC_NEUTRAL_MODE;
1884 guint32 idx, i, token;
1886 if (!assembly->save)
1889 sigbuffer_init (&buf, 32);
1891 sigbuffer_add_value (&buf, 0x06);
1892 /* encode custom attributes before the type */
1893 if (type->num_mods) {
1894 for (i = 0; i < type->num_mods; ++i) {
1897 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1898 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1900 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1902 token = type->modifiers [i].token;
1905 if (type->modifiers [i].required)
1906 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1908 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1910 sigbuffer_add_value (&buf, token);
1913 encode_type (assembly, type, &buf);
1914 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1915 sigbuffer_free (&buf);
1921 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1923 MONO_REQ_GC_UNSAFE_MODE;
1927 guint32 typespec = 0;
1931 init_type_builder_generics (fb->type);
1933 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1934 klass = mono_class_from_mono_type (type);
1936 sigbuffer_init (&buf, 32);
1938 sigbuffer_add_value (&buf, 0x06);
1939 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1940 /* encode custom attributes before the type */
1942 if (klass->generic_container)
1943 typespec = create_typespec (assembly, type);
1946 MonoGenericClass *gclass;
1947 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1948 encode_generic_class (assembly, gclass, &buf);
1950 encode_type (assembly, type, &buf);
1952 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1953 sigbuffer_free (&buf);
1958 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1960 MONO_REQ_GC_UNSAFE_MODE;
1962 char blob_size [64];
1963 char *b = blob_size;
1966 guint32 idx = 0, len = 0, dummy = 0;
1968 buf = g_malloc (64);
1970 *ret_type = MONO_TYPE_CLASS;
1972 box_val = (char*)&dummy;
1974 box_val = ((char*)val) + sizeof (MonoObject);
1975 *ret_type = val->vtable->klass->byval_arg.type;
1978 switch (*ret_type) {
1979 case MONO_TYPE_BOOLEAN:
1984 case MONO_TYPE_CHAR:
2001 case MONO_TYPE_VALUETYPE: {
2002 MonoClass *klass = val->vtable->klass;
2004 if (klass->enumtype) {
2005 *ret_type = mono_class_enum_basetype (klass)->type;
2007 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2010 g_error ("we can't encode valuetypes, we should have never reached this line");
2013 case MONO_TYPE_CLASS:
2015 case MONO_TYPE_STRING: {
2016 MonoString *str = (MonoString*)val;
2017 /* there is no signature */
2018 len = str->length * 2;
2019 mono_metadata_encode_value (len, b, &b);
2020 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2022 char *swapped = g_malloc (2 * mono_string_length (str));
2023 const char *p = (const char*)mono_string_chars (str);
2025 swap_with_size (swapped, p, 2, mono_string_length (str));
2026 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2030 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2036 case MONO_TYPE_GENERICINST:
2037 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2040 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2043 /* there is no signature */
2044 mono_metadata_encode_value (len, b, &b);
2045 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2046 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2047 swap_with_size (blob_size, box_val, len, 1);
2048 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2050 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2058 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2060 MONO_REQ_GC_UNSAFE_MODE;
2066 sigbuffer_init (&buf, 32);
2068 sigbuffer_add_value (&buf, minfo->type);
2070 switch (minfo->type) {
2071 case MONO_NATIVE_BYVALTSTR:
2072 case MONO_NATIVE_BYVALARRAY:
2073 sigbuffer_add_value (&buf, minfo->count);
2075 case MONO_NATIVE_LPARRAY:
2076 if (minfo->eltype || minfo->has_size) {
2077 sigbuffer_add_value (&buf, minfo->eltype);
2078 if (minfo->has_size) {
2079 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2080 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2082 /* LAMESPEC: ElemMult is undocumented */
2083 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2087 case MONO_NATIVE_SAFEARRAY:
2089 sigbuffer_add_value (&buf, minfo->eltype);
2091 case MONO_NATIVE_CUSTOM:
2093 str = mono_string_to_utf8 (minfo->guid);
2095 sigbuffer_add_value (&buf, len);
2096 sigbuffer_add_mem (&buf, str, len);
2099 sigbuffer_add_value (&buf, 0);
2101 /* native type name */
2102 sigbuffer_add_value (&buf, 0);
2103 /* custom marshaler type name */
2104 if (minfo->marshaltype || minfo->marshaltyperef) {
2105 if (minfo->marshaltyperef)
2106 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2108 str = mono_string_to_utf8 (minfo->marshaltype);
2110 sigbuffer_add_value (&buf, len);
2111 sigbuffer_add_mem (&buf, str, len);
2114 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2115 sigbuffer_add_value (&buf, 0);
2117 if (minfo->mcookie) {
2118 str = mono_string_to_utf8 (minfo->mcookie);
2120 sigbuffer_add_value (&buf, len);
2121 sigbuffer_add_mem (&buf, str, len);
2124 sigbuffer_add_value (&buf, 0);
2130 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2131 sigbuffer_free (&buf);
2136 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2138 MONO_REQ_GC_UNSAFE_MODE;
2140 MonoDynamicTable *table;
2143 /* maybe this fixup should be done in the C# code */
2144 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2145 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2146 table = &assembly->tables [MONO_TABLE_FIELD];
2147 fb->table_idx = table->next_idx ++;
2148 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2149 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2150 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2151 values [MONO_FIELD_FLAGS] = fb->attrs;
2152 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2154 if (fb->offset != -1) {
2155 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2157 alloc_table (table, table->rows);
2158 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2159 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2160 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2162 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2163 guint32 field_type = 0;
2164 table = &assembly->tables [MONO_TABLE_CONSTANT];
2166 alloc_table (table, table->rows);
2167 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2168 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2169 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2170 values [MONO_CONSTANT_TYPE] = field_type;
2171 values [MONO_CONSTANT_PADDING] = 0;
2173 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2175 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2177 alloc_table (table, table->rows);
2178 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2179 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2181 * We store it in the code section because it's simpler for now.
2184 if (mono_array_length (fb->rva_data) >= 10)
2185 stream_data_align (&assembly->code);
2186 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2188 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2189 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2191 if (fb->marshal_info) {
2192 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2194 alloc_table (table, table->rows);
2195 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2196 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2197 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2202 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2204 MONO_REQ_GC_UNSAFE_MODE;
2207 guint32 nparams = 0;
2208 MonoReflectionMethodBuilder *mb = fb->get_method;
2209 MonoReflectionMethodBuilder *smb = fb->set_method;
2212 if (mb && mb->parameters)
2213 nparams = mono_array_length (mb->parameters);
2214 if (!mb && smb && smb->parameters)
2215 nparams = mono_array_length (smb->parameters) - 1;
2216 sigbuffer_init (&buf, 32);
2217 if (fb->call_conv & 0x20)
2218 sigbuffer_add_byte (&buf, 0x28);
2220 sigbuffer_add_byte (&buf, 0x08);
2221 sigbuffer_add_value (&buf, nparams);
2223 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2224 for (i = 0; i < nparams; ++i) {
2225 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2226 encode_reflection_type (assembly, pt, &buf);
2228 } else if (smb && smb->parameters) {
2229 /* the property type is the last param */
2230 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2231 for (i = 0; i < nparams; ++i) {
2232 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2233 encode_reflection_type (assembly, pt, &buf);
2236 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2239 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2240 sigbuffer_free (&buf);
2245 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2247 MONO_REQ_GC_UNSAFE_MODE;
2249 MonoDynamicTable *table;
2251 guint num_methods = 0;
2255 * we need to set things in the following tables:
2256 * PROPERTYMAP (info already filled in _get_type_info ())
2257 * PROPERTY (rows already preallocated in _get_type_info ())
2258 * METHOD (method info already done with the generic method code)
2262 table = &assembly->tables [MONO_TABLE_PROPERTY];
2263 pb->table_idx = table->next_idx ++;
2264 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2265 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2266 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2267 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2269 /* FIXME: we still don't handle 'other' methods */
2270 if (pb->get_method) num_methods ++;
2271 if (pb->set_method) num_methods ++;
2273 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2274 table->rows += num_methods;
2275 alloc_table (table, table->rows);
2277 if (pb->get_method) {
2278 semaidx = table->next_idx ++;
2279 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2280 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2281 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2282 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2284 if (pb->set_method) {
2285 semaidx = table->next_idx ++;
2286 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2287 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2288 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2289 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2291 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2292 guint32 field_type = 0;
2293 table = &assembly->tables [MONO_TABLE_CONSTANT];
2295 alloc_table (table, table->rows);
2296 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2297 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2298 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2299 values [MONO_CONSTANT_TYPE] = field_type;
2300 values [MONO_CONSTANT_PADDING] = 0;
2305 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2307 MONO_REQ_GC_UNSAFE_MODE;
2309 MonoDynamicTable *table;
2311 guint num_methods = 0;
2315 * we need to set things in the following tables:
2316 * EVENTMAP (info already filled in _get_type_info ())
2317 * EVENT (rows already preallocated in _get_type_info ())
2318 * METHOD (method info already done with the generic method code)
2321 table = &assembly->tables [MONO_TABLE_EVENT];
2322 eb->table_idx = table->next_idx ++;
2323 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2324 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2325 values [MONO_EVENT_FLAGS] = eb->attrs;
2326 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2329 * FIXME: we still don't handle 'other' methods
2331 if (eb->add_method) num_methods ++;
2332 if (eb->remove_method) num_methods ++;
2333 if (eb->raise_method) num_methods ++;
2335 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2336 table->rows += num_methods;
2337 alloc_table (table, table->rows);
2339 if (eb->add_method) {
2340 semaidx = table->next_idx ++;
2341 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2342 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2343 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2344 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2346 if (eb->remove_method) {
2347 semaidx = table->next_idx ++;
2348 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2349 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2350 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2351 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2353 if (eb->raise_method) {
2354 semaidx = table->next_idx ++;
2355 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2356 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2357 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2358 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2363 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2365 MONO_REQ_GC_UNSAFE_MODE;
2367 MonoDynamicTable *table;
2368 guint32 num_constraints, i;
2372 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2373 num_constraints = gparam->iface_constraints ?
2374 mono_array_length (gparam->iface_constraints) : 0;
2375 table->rows += num_constraints;
2376 if (gparam->base_type)
2378 alloc_table (table, table->rows);
2380 if (gparam->base_type) {
2381 table_idx = table->next_idx ++;
2382 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2384 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2385 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2386 assembly, mono_reflection_type_get_handle (gparam->base_type));
2389 for (i = 0; i < num_constraints; i++) {
2390 MonoReflectionType *constraint = mono_array_get (
2391 gparam->iface_constraints, gpointer, i);
2393 table_idx = table->next_idx ++;
2394 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2396 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2397 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2398 assembly, mono_reflection_type_get_handle (constraint));
2403 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2405 MONO_REQ_GC_UNSAFE_MODE;
2407 GenericParamTableEntry *entry;
2410 * The GenericParam table must be sorted according to the `owner' field.
2411 * We need to do this sorting prior to writing the GenericParamConstraint
2412 * table, since we have to use the final GenericParam table indices there
2413 * and they must also be sorted.
2416 entry = g_new0 (GenericParamTableEntry, 1);
2417 entry->owner = owner;
2418 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2419 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2420 entry->gparam = gparam;
2422 g_ptr_array_add (assembly->gen_params, entry);
2426 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2428 MONO_REQ_GC_UNSAFE_MODE;
2430 MonoDynamicTable *table;
2431 MonoGenericParam *param;
2435 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2436 table_idx = table->next_idx ++;
2437 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2439 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2441 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2442 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2443 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2444 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2446 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2448 encode_constraints (entry->gparam, table_idx, assembly);
2452 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2454 MONO_REQ_GC_UNSAFE_MODE;
2456 MonoDynamicTable *table;
2459 guint32 cols [MONO_ASSEMBLY_SIZE];
2463 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2466 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2467 table = &assembly->tables [MONO_TABLE_MODULEREF];
2468 token = table->next_idx ++;
2470 alloc_table (table, table->rows);
2471 values = table->values + token * MONO_MODULEREF_SIZE;
2472 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2474 token <<= MONO_RESOLUTION_SCOPE_BITS;
2475 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2476 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2481 if (assembly_is_dynamic (image->assembly))
2483 memset (cols, 0, sizeof (cols));
2485 /* image->assembly->image is the manifest module */
2486 image = image->assembly->image;
2487 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2490 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2491 token = table->next_idx ++;
2493 alloc_table (table, table->rows);
2494 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2495 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2496 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2497 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2498 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2499 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2500 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2501 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2502 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2504 if (strcmp ("", image->assembly->aname.culture)) {
2505 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2506 image->assembly->aname.culture);
2509 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2510 guchar pubtoken [9];
2512 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2513 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2515 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2517 token <<= MONO_RESOLUTION_SCOPE_BITS;
2518 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2519 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2524 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2526 MONO_REQ_GC_NEUTRAL_MODE;
2528 MonoDynamicTable *table;
2533 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2536 sigbuffer_init (&buf, 32);
2537 switch (type->type) {
2538 case MONO_TYPE_FNPTR:
2540 case MONO_TYPE_SZARRAY:
2541 case MONO_TYPE_ARRAY:
2543 case MONO_TYPE_MVAR:
2544 case MONO_TYPE_GENERICINST:
2545 encode_type (assembly, type, &buf);
2547 case MONO_TYPE_CLASS:
2548 case MONO_TYPE_VALUETYPE: {
2549 MonoClass *k = mono_class_from_mono_type (type);
2550 if (!k || !k->generic_container) {
2551 sigbuffer_free (&buf);
2554 encode_type (assembly, type, &buf);
2558 sigbuffer_free (&buf);
2562 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2563 if (assembly->save) {
2564 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2567 values [MONO_TYPESPEC_SIGNATURE] = token;
2569 sigbuffer_free (&buf);
2571 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2572 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2578 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2580 MONO_REQ_GC_UNSAFE_MODE;
2582 MonoDynamicTable *table;
2584 guint32 token, scope, enclosing;
2587 /* if the type requires a typespec, we must try that first*/
2588 if (try_typespec && (token = create_typespec (assembly, type)))
2590 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2593 klass = mono_class_from_mono_type (type);
2595 klass = mono_class_from_mono_type (type);
2598 * If it's in the same module and not a generic type parameter:
2600 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2601 (type->type != MONO_TYPE_MVAR)) {
2602 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2603 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2604 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2608 if (klass->nested_in) {
2609 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2610 /* get the typeref idx of the enclosing type */
2611 enclosing >>= MONO_TYPEDEFORREF_BITS;
2612 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2614 scope = resolution_scope_from_image (assembly, klass->image);
2616 table = &assembly->tables [MONO_TABLE_TYPEREF];
2617 if (assembly->save) {
2618 alloc_table (table, table->rows + 1);
2619 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2620 values [MONO_TYPEREF_SCOPE] = scope;
2621 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2622 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2624 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2625 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2627 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2632 * Despite the name, we handle also TypeSpec (with the above helper).
2635 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2637 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2640 #ifndef DISABLE_REFLECTION_EMIT
2642 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2644 MONO_REQ_GC_NEUTRAL_MODE;
2646 MonoDynamicTable *table;
2648 guint32 token, pclass;
2650 switch (parent & MONO_TYPEDEFORREF_MASK) {
2651 case MONO_TYPEDEFORREF_TYPEREF:
2652 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2654 case MONO_TYPEDEFORREF_TYPESPEC:
2655 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2657 case MONO_TYPEDEFORREF_TYPEDEF:
2658 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2661 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2664 /* extract the index */
2665 parent >>= MONO_TYPEDEFORREF_BITS;
2667 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2669 if (assembly->save) {
2670 alloc_table (table, table->rows + 1);
2671 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2672 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2673 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2674 values [MONO_MEMBERREF_SIGNATURE] = sig;
2677 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2684 * Insert a memberef row into the metadata: the token that point to the memberref
2685 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2686 * mono_image_get_fieldref_token()).
2687 * The sig param is an index to an already built signature.
2690 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2692 MONO_REQ_GC_NEUTRAL_MODE;
2694 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2695 return mono_image_add_memberef_row (assembly, parent, name, sig);
2700 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2702 MONO_REQ_GC_NEUTRAL_MODE;
2705 MonoMethodSignature *sig;
2707 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2709 if (create_typespec) {
2710 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2715 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2716 if (token && !create_typespec)
2719 g_assert (!method->is_inflated);
2722 * A methodref signature can't contain an unmanaged calling convention.
2724 sig = mono_metadata_signature_dup (mono_method_signature (method));
2725 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2726 sig->call_convention = MONO_CALL_DEFAULT;
2727 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2728 method->name, method_encode_signature (assembly, sig));
2730 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2733 if (create_typespec) {
2734 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2735 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2736 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2738 if (assembly->save) {
2741 alloc_table (table, table->rows + 1);
2742 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2743 values [MONO_METHODSPEC_METHOD] = token;
2744 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2747 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2749 /*methodspec and memberef tokens are diferent, */
2750 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2757 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2759 guint32 token, parent, sig;
2760 ReflectionMethodBuilder rmb;
2762 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2764 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2768 name = mono_string_to_utf8 (method->name);
2769 reflection_methodbuilder_from_method_builder (&rmb, method);
2772 * A methodref signature can't contain an unmanaged calling convention.
2773 * Since some flags are encoded as part of call_conv, we need to check against it.
2775 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2776 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2778 sig = method_builder_encode_signature (assembly, &rmb);
2780 if (tb->generic_params)
2781 parent = create_generic_typespec (assembly, tb);
2783 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2785 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2788 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2793 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2794 const gchar *name, guint32 sig)
2796 MonoDynamicTable *table;
2800 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2802 if (assembly->save) {
2803 alloc_table (table, table->rows + 1);
2804 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2805 values [MONO_MEMBERREF_CLASS] = original;
2806 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2807 values [MONO_MEMBERREF_SIGNATURE] = sig;
2810 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2817 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2821 guint32 nparams = mono_array_length (mb->generic_params);
2824 if (!assembly->save)
2827 sigbuffer_init (&buf, 32);
2829 sigbuffer_add_value (&buf, 0xa);
2830 sigbuffer_add_value (&buf, nparams);
2832 for (i = 0; i < nparams; i++) {
2833 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2834 sigbuffer_add_value (&buf, i);
2837 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2838 sigbuffer_free (&buf);
2843 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2845 MonoDynamicTable *table;
2847 guint32 token, mtoken = 0;
2849 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2853 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2855 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2856 switch (mono_metadata_token_table (mtoken)) {
2857 case MONO_TABLE_MEMBERREF:
2858 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2860 case MONO_TABLE_METHOD:
2861 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2864 g_assert_not_reached ();
2867 if (assembly->save) {
2868 alloc_table (table, table->rows + 1);
2869 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2870 values [MONO_METHODSPEC_METHOD] = mtoken;
2871 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2874 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2877 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2882 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2886 if (mb->generic_params && create_methodspec)
2887 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2889 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2893 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2894 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2899 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2901 guint32 token, parent, sig;
2902 ReflectionMethodBuilder rmb;
2904 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2906 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2910 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2912 if (tb->generic_params)
2913 parent = create_generic_typespec (assembly, tb);
2915 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2917 name = mono_string_to_utf8 (rmb.name);
2918 sig = method_builder_encode_signature (assembly, &rmb);
2920 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2923 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2929 is_field_on_inst (MonoClassField *field)
2931 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2935 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2938 get_field_on_inst_generic_type (MonoClassField *field)
2940 MonoClass *klass, *gtd;
2941 MonoDynamicGenericClass *dgclass;
2944 g_assert (is_field_on_inst (field));
2946 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2948 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2949 field_index = field - dgclass->fields;
2950 return dgclass->field_generic_types [field_index];
2953 klass = field->parent;
2954 gtd = klass->generic_class->container_class;
2956 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2957 field_index = field - klass->fields;
2958 return gtd->fields [field_index].type;
2961 g_assert_not_reached ();
2965 #ifndef DISABLE_REFLECTION_EMIT
2967 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2973 g_assert (field->parent);
2975 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2979 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2980 int index = field - field->parent->fields;
2981 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2983 if (is_field_on_inst (field))
2984 type = get_field_on_inst_generic_type (field);
2986 type = mono_field_get_type (field);
2988 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2989 mono_field_get_name (field),
2990 fieldref_encode_signature (assembly, field->parent->image, type));
2991 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2996 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3000 MonoGenericClass *gclass;
3004 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3007 if (is_sre_field_builder (mono_object_class (f->fb))) {
3008 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3009 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3010 klass = mono_class_from_mono_type (type);
3011 gclass = type->data.generic_class;
3012 g_assert (gclass->is_dynamic);
3014 name = mono_string_to_utf8 (fb->name);
3015 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3016 field_encode_signature (assembly, fb));
3018 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3020 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3022 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3023 klass = mono_class_from_mono_type (type);
3025 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3026 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3028 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3029 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3032 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3037 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3041 MonoGenericClass *gclass;
3044 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3046 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3050 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3051 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3052 ReflectionMethodBuilder rmb;
3055 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3056 klass = mono_class_from_mono_type (type);
3058 gclass = type->data.generic_class;
3059 g_assert (gclass->is_dynamic);
3061 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3063 name = mono_string_to_utf8 (rmb.name);
3065 sig = method_builder_encode_signature (assembly, &rmb);
3067 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3069 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3070 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3072 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3073 klass = mono_class_from_mono_type (type);
3075 sig = method_encode_signature (assembly, mono_method_signature (mm));
3076 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3078 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3079 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3083 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3088 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3092 MonoGenericContext tmp_context;
3093 MonoType **type_argv;
3094 MonoGenericInst *ginst;
3095 MonoMethod *method, *inflated;
3098 init_type_builder_generics ((MonoObject*)m->inst);
3100 method = inflate_method (m->inst, (MonoObject*)m->mb);
3102 klass = method->klass;
3104 if (m->method_args == NULL)
3107 if (method->is_inflated)
3108 method = ((MonoMethodInflated *) method)->declaring;
3110 count = mono_array_length (m->method_args);
3112 type_argv = g_new0 (MonoType *, count);
3113 for (i = 0; i < count; i++) {
3114 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3115 type_argv [i] = mono_reflection_type_get_handle (garg);
3117 ginst = mono_metadata_get_generic_inst (count, type_argv);
3120 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3121 tmp_context.method_inst = ginst;
3123 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3124 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3129 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3131 guint32 sig, token = 0;
3135 if (m->method_args) {
3136 MonoMethod *inflated;
3138 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3139 if (create_methodspec)
3140 token = mono_image_get_methodspec_token (assembly, inflated);
3142 token = mono_image_get_inflated_method_token (assembly, inflated);
3146 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3150 if (is_sre_method_builder (mono_object_class (m->mb))) {
3151 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3152 MonoGenericClass *gclass;
3153 ReflectionMethodBuilder rmb;
3156 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3157 klass = mono_class_from_mono_type (type);
3158 gclass = type->data.generic_class;
3159 g_assert (gclass->is_dynamic);
3161 reflection_methodbuilder_from_method_builder (&rmb, mb);
3163 name = mono_string_to_utf8 (rmb.name);
3165 sig = method_builder_encode_signature (assembly, &rmb);
3167 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3169 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3170 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3172 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3173 klass = mono_class_from_mono_type (type);
3175 sig = method_encode_signature (assembly, mono_method_signature (mm));
3176 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3178 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3179 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3182 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3187 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3191 guint32 nparams = context->method_inst->type_argc;
3194 if (!assembly->save)
3197 sigbuffer_init (&buf, 32);
3199 * FIXME: vararg, explicit_this, differenc call_conv values...
3201 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3202 sigbuffer_add_value (&buf, nparams);
3204 for (i = 0; i < nparams; i++)
3205 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3207 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3208 sigbuffer_free (&buf);
3213 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3215 MonoDynamicTable *table;
3217 guint32 token, mtoken = 0, sig;
3218 MonoMethodInflated *imethod;
3219 MonoMethod *declaring;
3221 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3223 g_assert (method->is_inflated);
3224 imethod = (MonoMethodInflated *) method;
3225 declaring = imethod->declaring;
3227 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3228 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3230 if (!mono_method_signature (declaring)->generic_param_count)
3233 switch (mono_metadata_token_table (mtoken)) {
3234 case MONO_TABLE_MEMBERREF:
3235 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3237 case MONO_TABLE_METHOD:
3238 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3241 g_assert_not_reached ();
3244 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3246 if (assembly->save) {
3247 alloc_table (table, table->rows + 1);
3248 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3249 values [MONO_METHODSPEC_METHOD] = mtoken;
3250 values [MONO_METHODSPEC_SIGNATURE] = sig;
3253 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3260 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3262 MonoMethodInflated *imethod;
3265 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3269 g_assert (method->is_inflated);
3270 imethod = (MonoMethodInflated *) method;
3272 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3273 token = method_encode_methodspec (assembly, method);
3275 guint32 sig = method_encode_signature (
3276 assembly, mono_method_signature (imethod->declaring));
3277 token = mono_image_get_memberref_token (
3278 assembly, &method->klass->byval_arg, method->name, sig);
3281 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3286 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3288 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3291 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3292 token = mono_image_get_memberref_token (
3293 assembly, &m->klass->byval_arg, m->name, sig);
3299 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3301 MonoDynamicTable *table;
3310 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3311 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3312 * Because of this, we must not insert it into the `typeref' hash table.
3314 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3315 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3319 sigbuffer_init (&buf, 32);
3321 g_assert (tb->generic_params);
3322 klass = mono_class_from_mono_type (type);
3324 if (tb->generic_container)
3325 mono_reflection_create_generic_class (tb);
3327 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3328 g_assert (klass->generic_container);
3329 sigbuffer_add_value (&buf, klass->byval_arg.type);
3330 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3332 count = mono_array_length (tb->generic_params);
3333 sigbuffer_add_value (&buf, count);
3334 for (i = 0; i < count; i++) {
3335 MonoReflectionGenericParam *gparam;
3337 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3339 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3342 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3344 if (assembly->save) {
3345 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3346 alloc_table (table, table->rows + 1);
3347 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3348 values [MONO_TYPESPEC_SIGNATURE] = token;
3350 sigbuffer_free (&buf);
3352 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3353 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3359 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3362 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3364 int i, count, len, pos;
3369 count += mono_array_length (modreq);
3371 count += mono_array_length (modopt);
3374 return mono_metadata_type_dup (NULL, type);
3376 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3378 memcpy (t, type, MONO_SIZEOF_TYPE);
3380 t->num_mods = count;
3383 for (i = 0; i < mono_array_length (modreq); ++i) {
3384 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3385 t->modifiers [pos].required = 1;
3386 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3391 for (i = 0; i < mono_array_length (modopt); ++i) {
3392 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3393 t->modifiers [pos].required = 0;
3394 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3403 init_type_builder_generics (MonoObject *type)
3405 MonoReflectionTypeBuilder *tb;
3407 if (!is_sre_type_builder(mono_object_class (type)))
3409 tb = (MonoReflectionTypeBuilder *)type;
3411 if (tb && tb->generic_container)
3412 mono_reflection_create_generic_class (tb);
3416 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3418 MonoDynamicTable *table;
3419 MonoType *custom = NULL, *type;
3421 guint32 token, pclass, parent, sig;
3424 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3428 /* FIXME: is this call necessary? */
3429 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3430 name = mono_string_to_utf8 (fb->name);
3432 /*FIXME this is one more layer of ugliness due how types are created.*/
3433 init_type_builder_generics (fb->type);
3435 /* fb->type does not include the custom modifiers */
3436 /* FIXME: We should do this in one place when a fieldbuilder is created */
3437 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3438 if (fb->modreq || fb->modopt)
3439 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3441 sig = fieldref_encode_signature (assembly, NULL, type);
3444 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3445 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3447 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3448 parent >>= MONO_TYPEDEFORREF_BITS;
3450 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3452 if (assembly->save) {
3453 alloc_table (table, table->rows + 1);
3454 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3455 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3456 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3457 values [MONO_MEMBERREF_SIGNATURE] = sig;
3460 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3462 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3468 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3474 if (!assembly->save)
3477 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3478 g_assert (helper->type == 2);
3480 if (helper->arguments)
3481 nargs = mono_array_length (helper->arguments);
3485 sigbuffer_init (&buf, 32);
3487 /* Encode calling convention */
3488 /* Change Any to Standard */
3489 if ((helper->call_conv & 0x03) == 0x03)
3490 helper->call_conv = 0x01;
3491 /* explicit_this implies has_this */
3492 if (helper->call_conv & 0x40)
3493 helper->call_conv &= 0x20;
3495 if (helper->call_conv == 0) { /* Unmanaged */
3496 idx = helper->unmanaged_call_conv - 1;
3499 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3500 if (helper->call_conv & 0x02) /* varargs */
3504 sigbuffer_add_byte (&buf, idx);
3505 sigbuffer_add_value (&buf, nargs);
3506 encode_reflection_type (assembly, helper->return_type, &buf);
3507 for (i = 0; i < nargs; ++i) {
3508 MonoArray *modreqs = NULL;
3509 MonoArray *modopts = NULL;
3510 MonoReflectionType *pt;
3512 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3513 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3514 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3515 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3517 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3518 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3519 encode_reflection_type (assembly, pt, &buf);
3521 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3522 sigbuffer_free (&buf);
3528 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3531 MonoDynamicTable *table;
3534 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3535 idx = table->next_idx ++;
3537 alloc_table (table, table->rows);
3538 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3540 values [MONO_STAND_ALONE_SIGNATURE] =
3541 mono_reflection_encode_sighelper (assembly, helper);
3547 reflection_cc_to_file (int call_conv) {
3548 switch (call_conv & 0x3) {
3550 case 1: return MONO_CALL_DEFAULT;
3551 case 2: return MONO_CALL_VARARG;
3553 g_assert_not_reached ();
3557 #endif /* !DISABLE_REFLECTION_EMIT */
3561 MonoMethodSignature *sig;
3566 #ifndef DISABLE_REFLECTION_EMIT
3568 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3573 MonoMethodSignature *sig;
3577 name = mono_string_to_utf8 (m->name);
3578 nparams = mono_array_length (m->parameters);
3579 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3581 sig->sentinelpos = -1;
3582 sig->call_convention = reflection_cc_to_file (m->call_conv);
3583 sig->param_count = nparams;
3584 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3585 mtype = mono_reflection_type_get_handle (m->parent);
3586 for (i = 0; i < nparams; ++i)
3587 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3589 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3591 if (strcmp (name, am->name) == 0 &&
3592 mono_metadata_type_equal (am->parent, mtype) &&
3593 mono_metadata_signature_equal (am->sig, sig)) {
3596 m->table_idx = am->token & 0xffffff;
3600 am = g_new0 (ArrayMethod, 1);
3604 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3605 method_encode_signature (assembly, sig));
3606 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3607 m->table_idx = am->token & 0xffffff;
3612 * Insert into the metadata tables all the info about the TypeBuilder tb.
3613 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3616 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3618 MonoDynamicTable *table;
3620 int i, is_object = 0, is_system = 0;
3623 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3624 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3625 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3626 n = mono_string_to_utf8 (tb->name);
3627 if (strcmp (n, "Object") == 0)
3629 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3631 n = mono_string_to_utf8 (tb->nspace);
3632 if (strcmp (n, "System") == 0)
3634 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3636 if (tb->parent && !(is_system && is_object) &&
3637 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3638 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3640 values [MONO_TYPEDEF_EXTENDS] = 0;
3642 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3643 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3646 * if we have explicitlayout or sequentiallayouts, output data in the
3647 * ClassLayout table.
3649 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3650 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3651 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3653 alloc_table (table, table->rows);
3654 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3655 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3656 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3657 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3660 /* handle interfaces */
3661 if (tb->interfaces) {
3662 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3664 table->rows += mono_array_length (tb->interfaces);
3665 alloc_table (table, table->rows);
3666 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3667 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3668 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3669 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3670 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3671 values += MONO_INTERFACEIMPL_SIZE;
3677 table = &assembly->tables [MONO_TABLE_FIELD];
3678 table->rows += tb->num_fields;
3679 alloc_table (table, table->rows);
3680 for (i = 0; i < tb->num_fields; ++i)
3681 mono_image_get_field_info (
3682 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3685 /* handle constructors */
3687 table = &assembly->tables [MONO_TABLE_METHOD];
3688 table->rows += mono_array_length (tb->ctors);
3689 alloc_table (table, table->rows);
3690 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3691 mono_image_get_ctor_info (domain,
3692 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3695 /* handle methods */
3697 table = &assembly->tables [MONO_TABLE_METHOD];
3698 table->rows += tb->num_methods;
3699 alloc_table (table, table->rows);
3700 for (i = 0; i < tb->num_methods; ++i)
3701 mono_image_get_method_info (
3702 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3705 /* Do the same with properties etc.. */
3706 if (tb->events && mono_array_length (tb->events)) {
3707 table = &assembly->tables [MONO_TABLE_EVENT];
3708 table->rows += mono_array_length (tb->events);
3709 alloc_table (table, table->rows);
3710 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3712 alloc_table (table, table->rows);
3713 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3714 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3715 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3716 for (i = 0; i < mono_array_length (tb->events); ++i)
3717 mono_image_get_event_info (
3718 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3720 if (tb->properties && mono_array_length (tb->properties)) {
3721 table = &assembly->tables [MONO_TABLE_PROPERTY];
3722 table->rows += mono_array_length (tb->properties);
3723 alloc_table (table, table->rows);
3724 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3726 alloc_table (table, table->rows);
3727 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3728 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3729 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3730 for (i = 0; i < mono_array_length (tb->properties); ++i)
3731 mono_image_get_property_info (
3732 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3735 /* handle generic parameters */
3736 if (tb->generic_params) {
3737 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3738 table->rows += mono_array_length (tb->generic_params);
3739 alloc_table (table, table->rows);
3740 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3741 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3743 mono_image_get_generic_param_info (
3744 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3748 mono_image_add_decl_security (assembly,
3749 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3752 MonoDynamicTable *ntable;
3754 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3755 ntable->rows += mono_array_length (tb->subtypes);
3756 alloc_table (ntable, ntable->rows);
3757 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3759 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3760 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3762 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3763 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3764 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3765 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3766 mono_string_to_utf8 (tb->name), tb->table_idx,
3767 ntable->next_idx, ntable->rows);*/
3768 values += MONO_NESTED_CLASS_SIZE;
3776 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3780 mono_ptr_array_append (*types, type);
3782 if (!type->subtypes)
3785 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3786 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3787 collect_types (types, subtype);
3792 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3794 if ((*type1)->table_idx < (*type2)->table_idx)
3797 if ((*type1)->table_idx > (*type2)->table_idx)
3804 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3809 for (i = 0; i < mono_array_length (pinfo); ++i) {
3810 MonoReflectionParamBuilder *pb;
3811 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3814 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3819 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3822 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3824 for (i = 0; i < tb->num_fields; ++i) {
3825 MonoReflectionFieldBuilder* fb;
3826 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3827 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3831 for (i = 0; i < mono_array_length (tb->events); ++i) {
3832 MonoReflectionEventBuilder* eb;
3833 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3834 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3837 if (tb->properties) {
3838 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3839 MonoReflectionPropertyBuilder* pb;
3840 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3841 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3845 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3846 MonoReflectionCtorBuilder* cb;
3847 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3848 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3849 params_add_cattrs (assembly, cb->pinfo);
3854 for (i = 0; i < tb->num_methods; ++i) {
3855 MonoReflectionMethodBuilder* mb;
3856 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3857 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3858 params_add_cattrs (assembly, mb->pinfo);
3863 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3864 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3869 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3873 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3875 if (moduleb->global_methods) {
3876 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3877 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3878 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3879 params_add_cattrs (assembly, mb->pinfo);
3883 if (moduleb->global_fields) {
3884 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3885 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3886 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3890 if (moduleb->types) {
3891 for (i = 0; i < moduleb->num_types; ++i)
3892 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3897 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3899 MonoDynamicTable *table;
3903 char *b = blob_size;
3906 table = &assembly->tables [MONO_TABLE_FILE];
3908 alloc_table (table, table->rows);
3909 values = table->values + table->next_idx * MONO_FILE_SIZE;
3910 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3911 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3912 if (image_is_dynamic (module->image)) {
3913 /* This depends on the fact that the main module is emitted last */
3914 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3915 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3918 path = g_strdup (module->image->name);
3920 mono_sha1_get_digest_from_file (path, hash);
3923 mono_metadata_encode_value (20, b, &b);
3924 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3925 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3930 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3932 MonoDynamicTable *table;
3935 table = &assembly->tables [MONO_TABLE_MODULE];
3936 mb->table_idx = table->next_idx ++;
3937 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3938 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3941 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3942 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3943 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3944 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3948 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3949 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3951 MonoDynamicTable *table;
3955 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3956 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3959 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3961 alloc_table (table, table->rows);
3962 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3964 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3965 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3966 if (klass->nested_in)
3967 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3969 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3970 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3971 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3973 res = table->next_idx;
3977 /* Emit nested types */
3978 if (klass->ext && klass->ext->nested_classes) {
3981 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3982 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3989 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3990 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3995 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3997 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3999 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4000 parent_index, assembly);
4004 * We need to do this ourselves since klass->nested_classes is not set up.
4007 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4008 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4013 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4014 guint32 module_index, MonoDynamicImage *assembly)
4016 MonoImage *image = module->image;
4020 t = &image->tables [MONO_TABLE_TYPEDEF];
4022 for (i = 0; i < t->rows; ++i) {
4024 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4025 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4027 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4028 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4033 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4035 MonoDynamicTable *table;
4037 guint32 scope, scope_idx, impl, current_idx;
4038 gboolean forwarder = TRUE;
4039 gpointer iter = NULL;
4042 if (klass->nested_in) {
4043 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4046 scope = resolution_scope_from_image (assembly, klass->image);
4047 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4048 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4049 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4052 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4055 alloc_table (table, table->rows);
4056 current_idx = table->next_idx;
4057 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4059 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4060 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4061 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4062 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4063 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4067 while ((nested = mono_class_get_nested_types (klass, &iter)))
4068 add_exported_type (assemblyb, assembly, nested, current_idx);
4072 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4077 if (!assemblyb->type_forwarders)
4080 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4081 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4086 type = mono_reflection_type_get_handle (t);
4089 klass = mono_class_from_mono_type (type);
4091 add_exported_type (assemblyb, assembly, klass, 0);
4095 #define align_pointer(base,p)\
4097 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4099 (p) += 4 - (__diff & 3);\
4103 compare_constants (const void *a, const void *b)
4105 const guint32 *a_values = a;
4106 const guint32 *b_values = b;
4107 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4111 compare_semantics (const void *a, const void *b)
4113 const guint32 *a_values = a;
4114 const guint32 *b_values = b;
4115 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4118 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4122 compare_custom_attrs (const void *a, const void *b)
4124 const guint32 *a_values = a;
4125 const guint32 *b_values = b;
4127 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4131 compare_field_marshal (const void *a, const void *b)
4133 const guint32 *a_values = a;
4134 const guint32 *b_values = b;
4136 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4140 compare_nested (const void *a, const void *b)
4142 const guint32 *a_values = a;
4143 const guint32 *b_values = b;
4145 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4149 compare_genericparam (const void *a, const void *b)
4151 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4152 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4154 if ((*b_entry)->owner == (*a_entry)->owner)
4156 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4157 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4159 return (*a_entry)->owner - (*b_entry)->owner;
4163 compare_declsecurity_attrs (const void *a, const void *b)
4165 const guint32 *a_values = a;
4166 const guint32 *b_values = b;
4168 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4172 compare_interface_impl (const void *a, const void *b)
4174 const guint32 *a_values = a;
4175 const guint32 *b_values = b;
4177 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4181 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4185 pad_heap (MonoDynamicStream *sh)
4187 if (sh->index & 3) {
4188 int sz = 4 - (sh->index & 3);
4189 memset (sh->data + sh->index, 0, sz);
4196 MonoDynamicStream *stream;
4200 * build_compressed_metadata() fills in the blob of data that represents the
4201 * raw metadata as it will be saved in the PE file. The five streams are output
4202 * and the metadata tables are comnpressed from the guint32 array representation,
4203 * to the compressed on-disk format.
4206 build_compressed_metadata (MonoDynamicImage *assembly)
4208 MonoDynamicTable *table;
4210 guint64 valid_mask = 0;
4211 guint64 sorted_mask;
4212 guint32 heapt_size = 0;
4213 guint32 meta_size = 256; /* allow for header and other stuff */
4214 guint32 table_offset;
4215 guint32 ntables = 0;
4221 struct StreamDesc stream_desc [5];
4223 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4224 for (i = 0; i < assembly->gen_params->len; i++){
4225 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4226 write_generic_param_entry (assembly, entry);
4229 stream_desc [0].name = "#~";
4230 stream_desc [0].stream = &assembly->tstream;
4231 stream_desc [1].name = "#Strings";
4232 stream_desc [1].stream = &assembly->sheap;
4233 stream_desc [2].name = "#US";
4234 stream_desc [2].stream = &assembly->us;
4235 stream_desc [3].name = "#Blob";
4236 stream_desc [3].stream = &assembly->blob;
4237 stream_desc [4].name = "#GUID";
4238 stream_desc [4].stream = &assembly->guid;
4240 /* tables that are sorted */
4241 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4242 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4243 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4244 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4245 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4246 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4247 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4249 /* Compute table sizes */
4250 /* the MonoImage has already been created in mono_image_basic_init() */
4251 meta = &assembly->image;
4253 /* sizes should be multiple of 4 */
4254 pad_heap (&assembly->blob);
4255 pad_heap (&assembly->guid);
4256 pad_heap (&assembly->sheap);
4257 pad_heap (&assembly->us);
4259 /* Setup the info used by compute_sizes () */
4260 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4261 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4262 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4264 meta_size += assembly->blob.index;
4265 meta_size += assembly->guid.index;
4266 meta_size += assembly->sheap.index;
4267 meta_size += assembly->us.index;
4269 for (i=0; i < MONO_TABLE_NUM; ++i)
4270 meta->tables [i].rows = assembly->tables [i].rows;
4272 for (i = 0; i < MONO_TABLE_NUM; i++){
4273 if (meta->tables [i].rows == 0)
4275 valid_mask |= (guint64)1 << i;
4277 meta->tables [i].row_size = mono_metadata_compute_size (
4278 meta, i, &meta->tables [i].size_bitfield);
4279 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4281 heapt_size += 24; /* #~ header size */
4282 heapt_size += ntables * 4;
4283 /* make multiple of 4 */
4286 meta_size += heapt_size;
4287 meta->raw_metadata = g_malloc0 (meta_size);
4288 p = (unsigned char*)meta->raw_metadata;
4289 /* the metadata signature */
4290 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4291 /* version numbers and 4 bytes reserved */
4292 int16val = (guint16*)p;
4293 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4294 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4296 /* version string */
4297 int32val = (guint32*)p;
4298 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4300 memcpy (p, meta->version, strlen (meta->version));
4301 p += GUINT32_FROM_LE (*int32val);
4302 align_pointer (meta->raw_metadata, p);
4303 int16val = (guint16*)p;
4304 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4305 *int16val = GUINT16_TO_LE (5); /* number of streams */
4309 * write the stream info.
4311 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4312 table_offset += 3; table_offset &= ~3;
4314 assembly->tstream.index = heapt_size;
4315 for (i = 0; i < 5; ++i) {
4316 int32val = (guint32*)p;
4317 stream_desc [i].stream->offset = table_offset;
4318 *int32val++ = GUINT32_TO_LE (table_offset);
4319 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4320 table_offset += GUINT32_FROM_LE (*int32val);
4321 table_offset += 3; table_offset &= ~3;
4323 strcpy ((char*)p, stream_desc [i].name);
4324 p += strlen (stream_desc [i].name) + 1;
4325 align_pointer (meta->raw_metadata, p);
4328 * now copy the data, the table stream header and contents goes first.
4330 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4331 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4332 int32val = (guint32*)p;
4333 *int32val = GUINT32_TO_LE (0); /* reserved */
4336 *p++ = 2; /* version */
4339 if (meta->idx_string_wide)
4341 if (meta->idx_guid_wide)
4343 if (meta->idx_blob_wide)
4346 *p++ = 1; /* reserved */
4347 int64val = (guint64*)p;
4348 *int64val++ = GUINT64_TO_LE (valid_mask);
4349 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4351 int32val = (guint32*)p;
4352 for (i = 0; i < MONO_TABLE_NUM; i++){
4353 if (meta->tables [i].rows == 0)
4355 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4357 p = (unsigned char*)int32val;
4359 /* sort the tables that still need sorting */
4360 table = &assembly->tables [MONO_TABLE_CONSTANT];
4362 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4363 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4365 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4366 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4368 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4369 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4371 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4372 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4374 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4375 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4376 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4378 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4379 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4381 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4383 /* compress the tables */
4384 for (i = 0; i < MONO_TABLE_NUM; i++){
4387 guint32 bitfield = meta->tables [i].size_bitfield;
4388 if (!meta->tables [i].rows)
4390 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4391 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4392 meta->tables [i].base = (char*)p;
4393 for (row = 1; row <= meta->tables [i].rows; ++row) {
4394 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4395 for (col = 0; col < assembly->tables [i].columns; ++col) {
4396 switch (mono_metadata_table_size (bitfield, col)) {
4398 *p++ = values [col];
4401 *p++ = values [col] & 0xff;
4402 *p++ = (values [col] >> 8) & 0xff;
4405 *p++ = values [col] & 0xff;
4406 *p++ = (values [col] >> 8) & 0xff;
4407 *p++ = (values [col] >> 16) & 0xff;
4408 *p++ = (values [col] >> 24) & 0xff;
4411 g_assert_not_reached ();
4415 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4418 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4419 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4420 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4421 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4422 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4424 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4428 * Some tables in metadata need to be sorted according to some criteria, but
4429 * when methods and fields are first created with reflection, they may be assigned a token
4430 * that doesn't correspond to the final token they will get assigned after the sorting.
4431 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4432 * with the reflection objects that represent them. Once all the tables are set up, the
4433 * reflection objects will contains the correct table index. fixup_method() will fixup the
4434 * tokens for the method with ILGenerator @ilgen.
4437 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4439 guint32 code_idx = GPOINTER_TO_UINT (value);
4440 MonoReflectionILTokenInfo *iltoken;
4441 MonoReflectionFieldBuilder *field;
4442 MonoReflectionCtorBuilder *ctor;
4443 MonoReflectionMethodBuilder *method;
4444 MonoReflectionTypeBuilder *tb;
4445 MonoReflectionArrayMethod *am;
4447 unsigned char *target;
4449 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4450 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4451 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4452 switch (target [3]) {
4453 case MONO_TABLE_FIELD:
4454 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4455 field = (MonoReflectionFieldBuilder *)iltoken->member;
4456 idx = field->table_idx;
4457 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4458 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4459 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4461 g_assert_not_reached ();
4464 case MONO_TABLE_METHOD:
4465 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4466 method = (MonoReflectionMethodBuilder *)iltoken->member;
4467 idx = method->table_idx;
4468 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4469 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4470 idx = ctor->table_idx;
4471 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4472 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4473 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4474 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4476 g_assert_not_reached ();
4479 case MONO_TABLE_TYPEDEF:
4480 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4481 g_assert_not_reached ();
4482 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4483 idx = tb->table_idx;
4485 case MONO_TABLE_MEMBERREF:
4486 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4487 am = (MonoReflectionArrayMethod*)iltoken->member;
4488 idx = am->table_idx;
4489 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4490 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4491 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4492 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4493 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4494 g_assert (m->klass->generic_class || m->klass->generic_container);
4496 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4498 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4499 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4500 g_assert (is_field_on_inst (f));
4502 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4503 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4505 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4507 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4509 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4512 g_assert_not_reached ();
4515 case MONO_TABLE_METHODSPEC:
4516 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4517 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4518 g_assert (mono_method_signature (m)->generic_param_count);
4520 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4522 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4525 g_assert_not_reached ();
4529 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4531 target [0] = idx & 0xff;
4532 target [1] = (idx >> 8) & 0xff;
4533 target [2] = (idx >> 16) & 0xff;
4540 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4541 * value is not known when the table is emitted.
4544 fixup_cattrs (MonoDynamicImage *assembly)
4546 MonoDynamicTable *table;
4548 guint32 type, i, idx, token;
4551 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4553 for (i = 0; i < table->rows; ++i) {
4554 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4556 type = values [MONO_CUSTOM_ATTR_TYPE];
4557 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4558 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4559 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4560 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4563 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4564 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4565 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4566 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4567 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4568 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4569 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4570 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4577 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4579 MonoDynamicTable *table;
4582 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4584 alloc_table (table, table->rows);
4585 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4586 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4587 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4588 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4589 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4594 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4596 MonoDynamicTable *table;
4600 char *b = blob_size;
4602 guint32 idx, offset;
4604 if (rsrc->filename) {
4605 name = mono_string_to_utf8 (rsrc->filename);
4606 sname = g_path_get_basename (name);
4608 table = &assembly->tables [MONO_TABLE_FILE];
4610 alloc_table (table, table->rows);
4611 values = table->values + table->next_idx * MONO_FILE_SIZE;
4612 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4613 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4616 mono_sha1_get_digest_from_file (name, hash);
4617 mono_metadata_encode_value (20, b, &b);
4618 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4619 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4621 idx = table->next_idx++;
4623 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4629 data = mono_array_addr (rsrc->data, char, 0);
4630 len = mono_array_length (rsrc->data);
4636 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4637 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4638 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4639 mono_image_add_stream_data (&assembly->resources, data, len);
4643 * The entry should be emitted into the MANIFESTRESOURCE table of
4644 * the main module, but that needs to reference the FILE table
4645 * which isn't emitted yet.
4652 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4656 set_version_from_string (MonoString *version, guint32 *values)
4658 gchar *ver, *p, *str;
4661 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4662 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4663 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4664 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4667 ver = str = mono_string_to_utf8 (version);
4668 for (i = 0; i < 4; ++i) {
4669 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4675 /* handle Revision and Build */
4685 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4689 char *b = blob_size;
4694 len = mono_array_length (pkey);
4695 mono_metadata_encode_value (len, b, &b);
4696 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4697 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4699 assembly->public_key = g_malloc (len);
4700 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4701 assembly->public_key_len = len;
4703 /* Special case: check for ECMA key (16 bytes) */
4704 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4705 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4706 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4707 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4708 /* minimum key size (in 2.0) is 384 bits */
4709 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4711 /* FIXME - verifier */
4712 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4713 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4715 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4721 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4723 MonoDynamicTable *table;
4724 MonoDynamicImage *assembly;
4725 MonoReflectionAssemblyBuilder *assemblyb;
4729 guint32 module_index;
4731 assemblyb = moduleb->assemblyb;
4732 assembly = moduleb->dynamic_image;
4733 domain = mono_object_domain (assemblyb);
4735 /* Emit ASSEMBLY table */
4736 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4737 alloc_table (table, 1);
4738 values = table->values + MONO_ASSEMBLY_SIZE;
4739 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4740 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4741 if (assemblyb->culture) {
4742 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4744 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4746 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4747 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4748 set_version_from_string (assemblyb->version, values);
4750 /* Emit FILE + EXPORTED_TYPE table */
4752 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4754 MonoReflectionModuleBuilder *file_module =
4755 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4756 if (file_module != moduleb) {
4757 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4759 if (file_module->types) {
4760 for (j = 0; j < file_module->num_types; ++j) {
4761 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4762 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4767 if (assemblyb->loaded_modules) {
4768 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4769 MonoReflectionModule *file_module =
4770 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4771 mono_image_fill_file_table (domain, file_module, assembly);
4773 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4776 if (assemblyb->type_forwarders)
4777 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4779 /* Emit MANIFESTRESOURCE table */
4781 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4783 MonoReflectionModuleBuilder *file_module =
4784 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4785 /* The table for the main module is emitted later */
4786 if (file_module != moduleb) {
4788 if (file_module->resources) {
4789 int len = mono_array_length (file_module->resources);
4790 for (j = 0; j < len; ++j) {
4791 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4792 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4799 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4802 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4803 * for the modulebuilder @moduleb.
4804 * At the end of the process, method and field tokens are fixed up and the
4805 * on-disk compressed metadata representation is created.
4808 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4810 MonoDynamicTable *table;
4811 MonoDynamicImage *assembly;
4812 MonoReflectionAssemblyBuilder *assemblyb;
4818 assemblyb = moduleb->assemblyb;
4819 assembly = moduleb->dynamic_image;
4820 domain = mono_object_domain (assemblyb);
4822 if (assembly->text_rva)
4825 assembly->text_rva = START_TEXT_RVA;
4827 if (moduleb->is_main) {
4828 mono_image_emit_manifest (moduleb);
4831 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4832 table->rows = 1; /* .<Module> */
4834 alloc_table (table, table->rows);
4836 * Set the first entry.
4838 values = table->values + table->columns;
4839 values [MONO_TYPEDEF_FLAGS] = 0;
4840 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4841 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4842 values [MONO_TYPEDEF_EXTENDS] = 0;
4843 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4844 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4847 * handle global methods
4848 * FIXME: test what to do when global methods are defined in multiple modules.
4850 if (moduleb->global_methods) {
4851 table = &assembly->tables [MONO_TABLE_METHOD];
4852 table->rows += mono_array_length (moduleb->global_methods);
4853 alloc_table (table, table->rows);
4854 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4855 mono_image_get_method_info (
4856 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4858 if (moduleb->global_fields) {
4859 table = &assembly->tables [MONO_TABLE_FIELD];
4860 table->rows += mono_array_length (moduleb->global_fields);
4861 alloc_table (table, table->rows);
4862 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4863 mono_image_get_field_info (
4864 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4867 table = &assembly->tables [MONO_TABLE_MODULE];
4868 alloc_table (table, 1);
4869 mono_image_fill_module_table (domain, moduleb, assembly);
4871 /* Collect all types into a list sorted by their table_idx */
4872 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4875 for (i = 0; i < moduleb->num_types; ++i) {
4876 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4877 collect_types (&types, type);
4880 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4881 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4882 table->rows += mono_ptr_array_size (types);
4883 alloc_table (table, table->rows);
4886 * Emit type names + namespaces at one place inside the string heap,
4887 * so load_class_names () needs to touch fewer pages.
4889 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4890 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4891 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4893 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4894 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4895 string_heap_insert_mstring (&assembly->sheap, tb->name);
4898 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4899 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4900 mono_image_get_type_info (domain, type, assembly);
4904 * table->rows is already set above and in mono_image_fill_module_table.
4906 /* add all the custom attributes at the end, once all the indexes are stable */
4907 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4909 /* CAS assembly permissions */
4910 if (assemblyb->permissions_minimum)
4911 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4912 if (assemblyb->permissions_optional)
4913 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4914 if (assemblyb->permissions_refused)
4915 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4917 module_add_cattrs (assembly, moduleb);
4920 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4922 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4923 * the final tokens and don't need another fixup pass. */
4925 if (moduleb->global_methods) {
4926 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4927 MonoReflectionMethodBuilder *mb = mono_array_get (
4928 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4929 mono_image_add_methodimpl (assembly, mb);
4933 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4934 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4935 if (type->methods) {
4936 for (j = 0; j < type->num_methods; ++j) {
4937 MonoReflectionMethodBuilder *mb = mono_array_get (
4938 type->methods, MonoReflectionMethodBuilder*, j);
4940 mono_image_add_methodimpl (assembly, mb);
4945 mono_ptr_array_destroy (types);
4947 fixup_cattrs (assembly);
4950 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4953 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4955 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4958 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4962 guint32 import_lookup_table;
4966 guint32 import_address_table_rva;
4974 #ifndef DISABLE_REFLECTION_EMIT
4977 * mono_image_insert_string:
4978 * @module: module builder object
4981 * Insert @str into the user string stream of @module.
4984 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4986 MonoDynamicImage *assembly;
4991 if (!module->dynamic_image)
4992 mono_image_module_basic_init (module);
4994 assembly = module->dynamic_image;
4996 if (assembly->save) {
4997 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4998 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4999 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5001 char *swapped = g_malloc (2 * mono_string_length (str));
5002 const char *p = (const char*)mono_string_chars (str);
5004 swap_with_size (swapped, p, 2, mono_string_length (str));
5005 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5009 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5011 mono_image_add_stream_data (&assembly->us, "", 1);
5013 idx = assembly->us.index ++;
5016 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5018 return MONO_TOKEN_STRING | idx;
5022 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5026 MonoMethodSignature *sig;
5028 klass = obj->vtable->klass;
5029 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5030 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5031 MonoMethodSignature *old;
5032 guint32 sig_token, parent;
5035 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5037 nargs = mono_array_length (opt_param_types);
5038 old = mono_method_signature (method);
5039 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5041 sig->hasthis = old->hasthis;
5042 sig->explicit_this = old->explicit_this;
5043 sig->call_convention = old->call_convention;
5044 sig->generic_param_count = old->generic_param_count;
5045 sig->param_count = old->param_count + nargs;
5046 sig->sentinelpos = old->param_count;
5047 sig->ret = old->ret;
5049 for (i = 0; i < old->param_count; i++)
5050 sig->params [i] = old->params [i];
5052 for (i = 0; i < nargs; i++) {
5053 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5057 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5058 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5059 parent >>= MONO_TYPEDEFORREF_BITS;
5061 parent <<= MONO_MEMBERREF_PARENT_BITS;
5062 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5064 sig_token = method_encode_signature (assembly, sig);
5065 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5066 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5067 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5068 ReflectionMethodBuilder rmb;
5069 guint32 parent, sig_token;
5070 int nopt_args, nparams, ngparams, i;
5073 reflection_methodbuilder_from_method_builder (&rmb, mb);
5074 rmb.opt_types = opt_param_types;
5075 nopt_args = mono_array_length (opt_param_types);
5077 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5078 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5079 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5081 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5082 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5083 sig->call_convention = rmb.call_conv;
5084 sig->generic_param_count = ngparams;
5085 sig->param_count = nparams + nopt_args;
5086 sig->sentinelpos = nparams;
5087 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5089 for (i = 0; i < nparams; i++) {
5090 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5091 sig->params [i] = mono_reflection_type_get_handle (rt);
5094 for (i = 0; i < nopt_args; i++) {
5095 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5096 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5099 sig_token = method_builder_encode_signature (assembly, &rmb);
5101 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5102 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5104 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5105 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5107 name = mono_string_to_utf8 (rmb.name);
5108 token = mono_image_get_varargs_method_token (
5109 assembly, parent, name, sig_token);
5112 g_error ("requested method token for %s\n", klass->name);
5115 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5116 register_dyn_token (assembly, token, obj);
5121 * mono_image_create_token:
5122 * @assembly: a dynamic assembly
5124 * @register_token: Whenever to register the token in the assembly->tokens hash.
5126 * Get a token to insert in the IL code stream for the given MemberInfo.
5127 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5128 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5132 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5133 gboolean create_open_instance, gboolean register_token)
5138 klass = obj->vtable->klass;
5140 /* Check for user defined reflection objects */
5141 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5142 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5143 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5145 if (strcmp (klass->name, "MethodBuilder") == 0) {
5146 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5147 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5149 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5150 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5152 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5153 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5154 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5155 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5156 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5158 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5159 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5161 token = mono_image_get_ctorbuilder_token (assembly, mb);
5162 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5163 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5164 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5165 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5166 if (tb->generic_params) {
5167 token = mono_image_get_generic_field_token (assembly, fb);
5169 if (tb->module->dynamic_image == assembly) {
5170 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5172 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5175 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5176 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5177 if (create_open_instance && tb->generic_params) {
5179 init_type_builder_generics (obj);
5180 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5181 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5182 token = mono_metadata_token_from_dor (token);
5183 } else if (tb->module->dynamic_image == assembly) {
5184 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5187 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5188 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5190 } else if (strcmp (klass->name, "MonoType") == 0) {
5191 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5192 MonoClass *mc = mono_class_from_mono_type (type);
5193 token = mono_metadata_token_from_dor (
5194 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5195 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5196 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5197 token = mono_metadata_token_from_dor (
5198 mono_image_typedef_or_ref (assembly, type));
5199 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5200 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5201 token = mono_metadata_token_from_dor (
5202 mono_image_typedef_or_ref (assembly, type));
5203 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5204 strcmp (klass->name, "MonoMethod") == 0 ||
5205 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5206 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5207 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5208 if (m->method->is_inflated) {
5209 if (create_open_instance)
5210 token = mono_image_get_methodspec_token (assembly, m->method);
5212 token = mono_image_get_inflated_method_token (assembly, m->method);
5213 } else if ((m->method->klass->image == &assembly->image) &&
5214 !m->method->klass->generic_class) {
5215 static guint32 method_table_idx = 0xffffff;
5216 if (m->method->klass->wastypebuilder) {
5217 /* we use the same token as the one that was assigned
5218 * to the Methodbuilder.
5219 * FIXME: do the equivalent for Fields.
5221 token = m->method->token;
5224 * Each token should have a unique index, but the indexes are
5225 * assigned by managed code, so we don't know about them. An
5226 * easy solution is to count backwards...
5228 method_table_idx --;
5229 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5232 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5234 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5235 } else if (strcmp (klass->name, "MonoField") == 0) {
5236 MonoReflectionField *f = (MonoReflectionField *)obj;
5237 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5238 static guint32 field_table_idx = 0xffffff;
5240 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5242 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5244 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5245 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5246 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5247 token = mono_image_get_array_token (assembly, m);
5248 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5249 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5250 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5251 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5252 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5253 token = mono_metadata_token_from_dor (
5254 mono_image_typedef_or_ref (assembly, type));
5255 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5256 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5257 token = mono_image_get_field_on_inst_token (assembly, f);
5258 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5259 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5260 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5261 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5262 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5263 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5264 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5265 MonoReflectionType *type = (MonoReflectionType *)obj;
5266 token = mono_metadata_token_from_dor (
5267 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5269 g_error ("requested token for %s\n", klass->name);
5273 mono_image_register_token (assembly, token, obj);
5279 * mono_image_register_token:
5281 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5282 * the Module.ResolveXXXToken () methods to work.
5285 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5289 dynamic_image_lock (assembly);
5290 prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5292 /* There could be multiple MethodInfo objects with the same token */
5293 //g_assert (prev == obj);
5295 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5297 dynamic_image_unlock (assembly);
5300 static MonoDynamicImage*
5301 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5303 static const guchar entrycode [16] = {0xff, 0x25, 0};
5304 MonoDynamicImage *image;
5307 const char *version;
5309 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5310 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5312 version = mono_get_runtime_info ()->runtime_version;
5315 /* The MonoGHashTable's need GC tracking */
5316 image = GC_MALLOC (sizeof (MonoDynamicImage));
5318 image = g_new0 (MonoDynamicImage, 1);
5321 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5323 /*g_print ("created image %p\n", image);*/
5324 /* keep in sync with image.c */
5325 image->image.name = assembly_name;
5326 image->image.assembly_name = image->image.name; /* they may be different */
5327 image->image.module_name = module_name;
5328 image->image.version = g_strdup (version);
5329 image->image.md_version_major = 1;
5330 image->image.md_version_minor = 1;
5331 image->image.dynamic = TRUE;
5333 image->image.references = g_new0 (MonoAssembly*, 1);
5334 image->image.references [0] = NULL;
5336 mono_image_init (&image->image);
5338 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5339 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5340 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5341 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5342 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5343 image->handleref = g_hash_table_new (NULL, NULL);
5344 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5345 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5346 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5347 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5348 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5349 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5350 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5351 image->gen_params = g_ptr_array_new ();
5352 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5354 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5355 string_heap_init (&image->sheap);
5356 mono_image_add_stream_data (&image->us, "", 1);
5357 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5358 /* import tables... */
5359 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5360 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5361 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5362 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5363 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5364 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5365 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5366 stream_data_align (&image->code);
5368 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5370 for (i=0; i < MONO_TABLE_NUM; ++i) {
5371 image->tables [i].next_idx = 1;
5372 image->tables [i].columns = table_sizes [i];
5375 image->image.assembly = (MonoAssembly*)assembly;
5376 image->run = assembly->run;
5377 image->save = assembly->save;
5378 image->pe_kind = 0x1; /* ILOnly */
5379 image->machine = 0x14c; /* I386 */
5381 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5383 dynamic_images_lock ();
5385 if (!dynamic_images)
5386 dynamic_images = g_ptr_array_new ();
5388 g_ptr_array_add (dynamic_images, image);
5390 dynamic_images_unlock ();
5397 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5403 release_hashtable (MonoGHashTable **hash)
5406 mono_g_hash_table_destroy (*hash);
5412 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5414 release_hashtable (&image->token_fixups);
5415 release_hashtable (&image->handleref_managed);
5416 release_hashtable (&image->tokens);
5417 release_hashtable (&image->remapped_tokens);
5418 release_hashtable (&image->generic_def_objects);
5419 release_hashtable (&image->methodspec);
5422 // Free dynamic image pass one: Free resources but not image itself
5424 mono_dynamic_image_free (MonoDynamicImage *image)
5426 MonoDynamicImage *di = image;
5431 mono_g_hash_table_destroy (di->methodspec);
5433 g_hash_table_destroy (di->typespec);
5435 g_hash_table_destroy (di->typeref);
5437 g_hash_table_destroy (di->handleref);
5438 if (di->handleref_managed)
5439 mono_g_hash_table_destroy (di->handleref_managed);
5441 mono_g_hash_table_destroy (di->tokens);
5442 if (di->remapped_tokens)
5443 mono_g_hash_table_destroy (di->remapped_tokens);
5444 if (di->generic_def_objects)
5445 mono_g_hash_table_destroy (di->generic_def_objects);
5446 if (di->blob_cache) {
5447 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5448 g_hash_table_destroy (di->blob_cache);
5450 if (di->standalonesig_cache)
5451 g_hash_table_destroy (di->standalonesig_cache);
5452 for (list = di->array_methods; list; list = list->next) {
5453 ArrayMethod *am = (ArrayMethod *)list->data;
5458 g_list_free (di->array_methods);
5459 if (di->gen_params) {
5460 for (i = 0; i < di->gen_params->len; i++) {
5461 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5462 mono_gc_deregister_root ((char*) &entry->gparam);
5465 g_ptr_array_free (di->gen_params, TRUE);
5467 if (di->token_fixups)
5468 mono_g_hash_table_destroy (di->token_fixups);
5469 if (di->method_to_table_idx)
5470 g_hash_table_destroy (di->method_to_table_idx);
5471 if (di->field_to_table_idx)
5472 g_hash_table_destroy (di->field_to_table_idx);
5473 if (di->method_aux_hash)
5474 g_hash_table_destroy (di->method_aux_hash);
5475 if (di->vararg_aux_hash)
5476 g_hash_table_destroy (di->vararg_aux_hash);
5477 g_free (di->strong_name);
5478 g_free (di->win32_res);
5480 g_free (di->public_key);
5482 /*g_print ("string heap destroy for image %p\n", di);*/
5483 mono_dynamic_stream_reset (&di->sheap);
5484 mono_dynamic_stream_reset (&di->code);
5485 mono_dynamic_stream_reset (&di->resources);
5486 mono_dynamic_stream_reset (&di->us);
5487 mono_dynamic_stream_reset (&di->blob);
5488 mono_dynamic_stream_reset (&di->tstream);
5489 mono_dynamic_stream_reset (&di->guid);
5490 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5491 g_free (di->tables [i].values);
5494 dynamic_images_lock ();
5497 g_ptr_array_remove (dynamic_images, di);
5499 dynamic_images_unlock ();
5502 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5504 mono_dynamic_image_free_image (MonoDynamicImage *image)
5506 /* See create_dynamic_mono_image () */
5508 /* Allocated using GC_MALLOC */
5514 #ifndef DISABLE_REFLECTION_EMIT
5517 * mono_image_basic_init:
5518 * @assembly: an assembly builder object
5520 * Create the MonoImage that represents the assembly builder and setup some
5521 * of the helper hash table and the basic metadata streams.
5524 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5526 MonoDynamicAssembly *assembly;
5527 MonoDynamicImage *image;
5528 MonoDomain *domain = mono_object_domain (assemblyb);
5530 if (assemblyb->dynamic_assembly)
5534 /* assembly->assembly.image might be GC allocated */
5535 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5537 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5540 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5542 assembly->assembly.ref_count = 1;
5543 assembly->assembly.dynamic = TRUE;
5544 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5545 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5546 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5547 if (assemblyb->culture)
5548 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5550 assembly->assembly.aname.culture = g_strdup ("");
5552 if (assemblyb->version) {
5553 char *vstr = mono_string_to_utf8 (assemblyb->version);
5554 char **version = g_strsplit (vstr, ".", 4);
5555 char **parts = version;
5556 assembly->assembly.aname.major = atoi (*parts++);
5557 assembly->assembly.aname.minor = atoi (*parts++);
5558 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5559 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5561 g_strfreev (version);
5564 assembly->assembly.aname.major = 0;
5565 assembly->assembly.aname.minor = 0;
5566 assembly->assembly.aname.build = 0;
5567 assembly->assembly.aname.revision = 0;
5570 assembly->run = assemblyb->access != 2;
5571 assembly->save = assemblyb->access != 1;
5572 assembly->domain = domain;
5574 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5575 image->initial_image = TRUE;
5576 assembly->assembly.aname.name = image->image.name;
5577 assembly->assembly.image = &image->image;
5578 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5579 /* -1 to correct for the trailing NULL byte */
5580 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5581 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5583 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5586 mono_domain_assemblies_lock (domain);
5587 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5588 mono_domain_assemblies_unlock (domain);
5590 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5592 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5594 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5597 #endif /* !DISABLE_REFLECTION_EMIT */
5599 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5602 calc_section_size (MonoDynamicImage *assembly)
5606 /* alignment constraints */
5607 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5608 g_assert ((assembly->code.index % 4) == 0);
5609 assembly->meta_size += 3;
5610 assembly->meta_size &= ~3;
5611 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5612 g_assert ((assembly->resources.index % 4) == 0);
5614 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5615 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5618 if (assembly->win32_res) {
5619 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5621 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5622 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5626 assembly->sections [MONO_SECTION_RELOC].size = 12;
5627 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5637 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5641 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5643 ResTreeNode *t1 = (ResTreeNode*)a;
5644 ResTreeNode *t2 = (ResTreeNode*)b;
5646 return t1->id - t2->id;
5650 * resource_tree_create:
5652 * Organize the resources into a resource tree.
5654 static ResTreeNode *
5655 resource_tree_create (MonoArray *win32_resources)
5657 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5661 tree = g_new0 (ResTreeNode, 1);
5663 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5664 MonoReflectionWin32Resource *win32_res =
5665 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5669 /* FIXME: BUG: this stores managed references in unmanaged memory */
5670 lang_node = g_new0 (ResTreeNode, 1);
5671 lang_node->id = win32_res->lang_id;
5672 lang_node->win32_res = win32_res;
5674 /* Create type node if neccesary */
5676 for (l = tree->children; l; l = l->next)
5677 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5678 type_node = (ResTreeNode*)l->data;
5683 type_node = g_new0 (ResTreeNode, 1);
5684 type_node->id = win32_res->res_type;
5687 * The resource types have to be sorted otherwise
5688 * Windows Explorer can't display the version information.
5690 tree->children = g_slist_insert_sorted (tree->children,
5691 type_node, resource_tree_compare_by_id);
5694 /* Create res node if neccesary */
5696 for (l = type_node->children; l; l = l->next)
5697 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5698 res_node = (ResTreeNode*)l->data;
5703 res_node = g_new0 (ResTreeNode, 1);
5704 res_node->id = win32_res->res_id;
5705 type_node->children = g_slist_append (type_node->children, res_node);
5708 res_node->children = g_slist_append (res_node->children, lang_node);
5715 * resource_tree_encode:
5717 * Encode the resource tree into the format used in the PE file.
5720 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5723 MonoPEResourceDir dir;
5724 MonoPEResourceDirEntry dir_entry;
5725 MonoPEResourceDataEntry data_entry;
5727 guint32 res_id_entries;
5730 * For the format of the resource directory, see the article
5731 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5735 memset (&dir, 0, sizeof (dir));
5736 memset (&dir_entry, 0, sizeof (dir_entry));
5737 memset (&data_entry, 0, sizeof (data_entry));
5739 g_assert (sizeof (dir) == 16);
5740 g_assert (sizeof (dir_entry) == 8);
5741 g_assert (sizeof (data_entry) == 16);
5743 node->offset = p - begin;
5745 /* IMAGE_RESOURCE_DIRECTORY */
5746 res_id_entries = g_slist_length (node->children);
5747 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5749 memcpy (p, &dir, sizeof (dir));
5752 /* Reserve space for entries */
5754 p += sizeof (dir_entry) * res_id_entries;
5756 /* Write children */
5757 for (l = node->children; l; l = l->next) {
5758 ResTreeNode *child = (ResTreeNode*)l->data;
5760 if (child->win32_res) {
5763 child->offset = p - begin;
5765 /* IMAGE_RESOURCE_DATA_ENTRY */
5766 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5767 size = mono_array_length (child->win32_res->res_data);
5768 data_entry.rde_size = GUINT32_TO_LE (size);
5770 memcpy (p, &data_entry, sizeof (data_entry));
5771 p += sizeof (data_entry);
5773 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5776 resource_tree_encode (child, begin, p, &p);
5780 /* IMAGE_RESOURCE_ENTRY */
5781 for (l = node->children; l; l = l->next) {
5782 ResTreeNode *child = (ResTreeNode*)l->data;
5784 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5785 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5787 memcpy (entries, &dir_entry, sizeof (dir_entry));
5788 entries += sizeof (dir_entry);
5795 resource_tree_free (ResTreeNode * node)
5798 for (list = node->children; list; list = list->next)
5799 resource_tree_free ((ResTreeNode*)list->data);
5800 g_slist_free(node->children);
5805 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5810 MonoReflectionWin32Resource *win32_res;
5813 if (!assemblyb->win32_resources)
5817 * Resources are stored in a three level tree inside the PE file.
5818 * - level one contains a node for each type of resource
5819 * - level two contains a node for each resource
5820 * - level three contains a node for each instance of a resource for a
5821 * specific language.
5824 tree = resource_tree_create (assemblyb->win32_resources);
5826 /* Estimate the size of the encoded tree */
5828 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5829 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5830 size += mono_array_length (win32_res->res_data);
5832 /* Directory structure */
5833 size += mono_array_length (assemblyb->win32_resources) * 256;
5834 p = buf = g_malloc (size);
5836 resource_tree_encode (tree, p, p, &p);
5838 g_assert (p - buf <= size);
5840 assembly->win32_res = g_malloc (p - buf);
5841 assembly->win32_res_size = p - buf;
5842 memcpy (assembly->win32_res, buf, p - buf);
5845 resource_tree_free (tree);
5849 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5851 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5854 p += sizeof (MonoPEResourceDir);
5855 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5856 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5857 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5858 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5859 fixup_resource_directory (res_section, child, rva);
5861 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5862 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5865 p += sizeof (MonoPEResourceDirEntry);
5870 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5873 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5874 g_error ("WriteFile returned %d\n", GetLastError ());
5878 * mono_image_create_pefile:
5879 * @mb: a module builder object
5881 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5882 * assembly->pefile where it can be easily retrieved later in chunks.
5885 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5887 MonoMSDOSHeader *msdos;
5888 MonoDotNetHeader *header;
5889 MonoSectionTable *section;
5890 MonoCLIHeader *cli_header;
5891 guint32 size, image_size, virtual_base, text_offset;
5892 guint32 header_start, section_start, file_offset, virtual_offset;
5893 MonoDynamicImage *assembly;
5894 MonoReflectionAssemblyBuilder *assemblyb;
5895 MonoDynamicStream pefile_stream = {0};
5896 MonoDynamicStream *pefile = &pefile_stream;
5898 guint32 *rva, value;
5900 static const unsigned char msheader[] = {
5901 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5902 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5905 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5906 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5907 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5908 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5911 assemblyb = mb->assemblyb;
5913 mono_image_basic_init (assemblyb);
5914 assembly = mb->dynamic_image;
5916 assembly->pe_kind = assemblyb->pe_kind;
5917 assembly->machine = assemblyb->machine;
5918 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5919 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5921 mono_image_build_metadata (mb);
5923 if (mb->is_main && assemblyb->resources) {
5924 int len = mono_array_length (assemblyb->resources);
5925 for (i = 0; i < len; ++i)
5926 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5929 if (mb->resources) {
5930 int len = mono_array_length (mb->resources);
5931 for (i = 0; i < len; ++i)
5932 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5935 build_compressed_metadata (assembly);
5938 assembly_add_win32_resources (assembly, assemblyb);
5940 nsections = calc_section_size (assembly);
5942 /* The DOS header and stub */
5943 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5944 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5946 /* the dotnet header */
5947 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5949 /* the section tables */
5950 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5952 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5953 virtual_offset = VIRT_ALIGN;
5956 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5957 if (!assembly->sections [i].size)
5960 file_offset += FILE_ALIGN - 1;
5961 file_offset &= ~(FILE_ALIGN - 1);
5962 virtual_offset += VIRT_ALIGN - 1;
5963 virtual_offset &= ~(VIRT_ALIGN - 1);
5965 assembly->sections [i].offset = file_offset;
5966 assembly->sections [i].rva = virtual_offset;
5968 file_offset += assembly->sections [i].size;
5969 virtual_offset += assembly->sections [i].size;
5970 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5973 file_offset += FILE_ALIGN - 1;
5974 file_offset &= ~(FILE_ALIGN - 1);
5976 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5978 /* back-patch info */
5979 msdos = (MonoMSDOSHeader*)pefile->data;
5980 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5982 header = (MonoDotNetHeader*)(pefile->data + header_start);
5983 header->pesig [0] = 'P';
5984 header->pesig [1] = 'E';
5986 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5987 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5988 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5989 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5990 if (assemblyb->pekind == 1) {
5992 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5995 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5998 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6000 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6001 header->pe.pe_major = 6;
6002 header->pe.pe_minor = 0;
6003 size = assembly->sections [MONO_SECTION_TEXT].size;
6004 size += FILE_ALIGN - 1;
6005 size &= ~(FILE_ALIGN - 1);
6006 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6007 size = assembly->sections [MONO_SECTION_RSRC].size;
6008 size += FILE_ALIGN - 1;
6009 size &= ~(FILE_ALIGN - 1);
6010 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6011 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6012 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6013 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6014 /* pe_rva_entry_point always at the beginning of the text section */
6015 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6017 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6018 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6019 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6020 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6021 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6022 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6023 size = section_start;
6024 size += FILE_ALIGN - 1;
6025 size &= ~(FILE_ALIGN - 1);
6026 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6028 size += VIRT_ALIGN - 1;
6029 size &= ~(VIRT_ALIGN - 1);
6030 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6033 // Translate the PEFileKind value to the value expected by the Windows loader
6039 // PEFileKinds.Dll == 1
6040 // PEFileKinds.ConsoleApplication == 2
6041 // PEFileKinds.WindowApplication == 3
6044 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6045 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6047 if (assemblyb->pekind == 3)
6052 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6054 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6055 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6056 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6057 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6058 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6059 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6061 /* fill data directory entries */
6063 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6064 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6066 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6067 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6069 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6070 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6071 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6072 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6073 /* patch entrypoint name */
6074 if (assemblyb->pekind == 1)
6075 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6077 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6078 /* patch imported function RVA name */
6079 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6080 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6082 /* the import table */
6083 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6084 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6085 /* patch imported dll RVA name and other entries in the dir */
6086 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6087 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6088 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6089 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6090 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6091 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6093 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6094 value = (assembly->text_rva + assembly->imp_names_offset);
6095 *p++ = (value) & 0xff;
6096 *p++ = (value >> 8) & (0xff);
6097 *p++ = (value >> 16) & (0xff);
6098 *p++ = (value >> 24) & (0xff);
6100 /* the CLI header info */
6101 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6102 cli_header->ch_size = GUINT32_FROM_LE (72);
6103 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6104 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6105 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6106 if (assemblyb->entry_point) {
6107 guint32 table_idx = 0;
6108 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6109 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6110 table_idx = methodb->table_idx;
6112 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6114 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6116 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6118 /* The embedded managed resources */
6119 text_offset = assembly->text_rva + assembly->code.index;
6120 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6121 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6122 text_offset += assembly->resources.index;
6123 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6124 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6125 text_offset += assembly->meta_size;
6126 if (assembly->strong_name_size) {
6127 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6128 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6129 text_offset += assembly->strong_name_size;
6132 /* write the section tables and section content */
6133 section = (MonoSectionTable*)(pefile->data + section_start);
6134 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6135 static const char section_names [][7] = {
6136 ".text", ".rsrc", ".reloc"
6138 if (!assembly->sections [i].size)
6140 strcpy (section->st_name, section_names [i]);
6141 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6142 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6143 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6144 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6145 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6146 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6147 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6151 checked_write_file (file, pefile->data, pefile->index);
6153 mono_dynamic_stream_reset (pefile);
6155 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6156 if (!assembly->sections [i].size)
6159 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160 g_error ("SetFilePointer returned %d\n", GetLastError ());
6163 case MONO_SECTION_TEXT:
6164 /* patch entry point */
6165 p = (guchar*)(assembly->code.data + 2);
6166 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6167 *p++ = (value) & 0xff;
6168 *p++ = (value >> 8) & 0xff;
6169 *p++ = (value >> 16) & 0xff;
6170 *p++ = (value >> 24) & 0xff;
6172 checked_write_file (file, assembly->code.data, assembly->code.index);
6173 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6174 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6175 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6178 g_free (assembly->image.raw_metadata);
6180 case MONO_SECTION_RELOC: {
6184 guint16 type_and_offset;
6188 g_assert (sizeof (reloc) == 12);
6190 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6191 reloc.block_size = GUINT32_FROM_LE (12);
6194 * the entrypoint is always at the start of the text section
6195 * 3 is IMAGE_REL_BASED_HIGHLOW
6196 * 2 is patch_size_rva - text_rva
6198 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6201 checked_write_file (file, &reloc, sizeof (reloc));
6205 case MONO_SECTION_RSRC:
6206 if (assembly->win32_res) {
6208 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6209 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6210 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6214 g_assert_not_reached ();
6218 /* check that the file is properly padded */
6219 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6220 g_error ("SetFilePointer returned %d\n", GetLastError ());
6221 if (! SetEndOfFile (file))
6222 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6224 mono_dynamic_stream_reset (&assembly->code);
6225 mono_dynamic_stream_reset (&assembly->us);
6226 mono_dynamic_stream_reset (&assembly->blob);
6227 mono_dynamic_stream_reset (&assembly->guid);
6228 mono_dynamic_stream_reset (&assembly->sheap);
6230 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6231 g_hash_table_destroy (assembly->blob_cache);
6232 assembly->blob_cache = NULL;
6235 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6238 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6240 g_assert_not_reached ();
6243 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6245 #ifndef DISABLE_REFLECTION_EMIT
6247 MonoReflectionModule *
6248 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6252 MonoImageOpenStatus status;
6253 MonoDynamicAssembly *assembly;
6254 guint32 module_count;
6255 MonoImage **new_modules;
6256 gboolean *new_modules_loaded;
6258 name = mono_string_to_utf8 (fileName);
6260 image = mono_image_open (name, &status);
6263 if (status == MONO_IMAGE_ERROR_ERRNO)
6264 exc = mono_get_exception_file_not_found (fileName);
6266 exc = mono_get_exception_bad_image_format (name);
6268 mono_raise_exception (exc);
6273 assembly = ab->dynamic_assembly;
6274 image->assembly = (MonoAssembly*)assembly;
6276 module_count = image->assembly->image->module_count;
6277 new_modules = g_new0 (MonoImage *, module_count + 1);
6278 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6280 if (image->assembly->image->modules)
6281 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6282 if (image->assembly->image->modules_loaded)
6283 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6284 new_modules [module_count] = image;
6285 new_modules_loaded [module_count] = TRUE;
6286 mono_image_addref (image);
6288 g_free (image->assembly->image->modules);
6289 image->assembly->image->modules = new_modules;
6290 image->assembly->image->modules_loaded = new_modules_loaded;
6291 image->assembly->image->module_count ++;
6293 mono_assembly_load_references (image, &status);
6295 mono_image_close (image);
6296 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6299 return mono_module_get_object (mono_domain_get (), image);
6302 #endif /* DISABLE_REFLECTION_EMIT */
6305 * We need to return always the same object for MethodInfo, FieldInfo etc..
6306 * but we need to consider the reflected type.
6307 * type uses a different hash, since it uses custom hash/equal functions.
6312 MonoClass *refclass;
6316 reflected_equal (gconstpointer a, gconstpointer b) {
6317 const ReflectedEntry *ea = a;
6318 const ReflectedEntry *eb = b;
6320 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6324 reflected_hash (gconstpointer a) {
6325 const ReflectedEntry *ea = a;
6326 return mono_aligned_addr_hash (ea->item);
6329 #define CHECK_OBJECT(t,p,k) \
6335 mono_domain_lock (domain); \
6336 if (!domain->refobject_hash) \
6337 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6338 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6339 mono_domain_unlock (domain); \
6342 mono_domain_unlock (domain); \
6345 #ifdef HAVE_BOEHM_GC
6346 /* ReflectedEntry doesn't need to be GC tracked */
6347 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6348 #define FREE_REFENTRY(entry) g_free ((entry))
6349 #define REFENTRY_REQUIRES_CLEANUP
6351 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6353 #define FREE_REFENTRY(entry)
6356 #define CACHE_OBJECT(t,p,o,k) \
6359 ReflectedEntry pe; \
6361 pe.refclass = (k); \
6362 mono_domain_lock (domain); \
6363 if (!domain->refobject_hash) \
6364 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6365 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6367 ReflectedEntry *e = ALLOC_REFENTRY; \
6369 e->refclass = (k); \
6370 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6373 mono_domain_unlock (domain); \
6378 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6380 mono_domain_lock (domain);
6381 if (domain->refobject_hash) {
6383 gpointer orig_pe, orig_value;
6386 pe.refclass = klass;
6387 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6388 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6389 FREE_REFENTRY (orig_pe);
6392 mono_domain_unlock (domain);
6395 #ifdef REFENTRY_REQUIRES_CLEANUP
6397 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6399 FREE_REFENTRY (key);
6404 mono_reflection_cleanup_domain (MonoDomain *domain)
6406 if (domain->refobject_hash) {
6407 /*let's avoid scanning the whole hashtable if not needed*/
6408 #ifdef REFENTRY_REQUIRES_CLEANUP
6409 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6411 mono_g_hash_table_destroy (domain->refobject_hash);
6412 domain->refobject_hash = NULL;
6416 #ifndef DISABLE_REFLECTION_EMIT
6418 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6420 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6424 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6426 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6430 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6432 MonoDynamicImage *image = moduleb->dynamic_image;
6433 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6437 MonoImage **new_modules;
6439 char *name, *fqname;
6441 * FIXME: we already created an image in mono_image_basic_init (), but
6442 * we don't know which module it belongs to, since that is only
6443 * determined at assembly save time.
6445 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6446 name = mono_string_to_utf8 (ab->name);
6447 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6448 if (!mono_error_ok (&error)) {
6450 mono_error_raise_exception (&error);
6452 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6454 moduleb->module.image = &image->image;
6455 moduleb->dynamic_image = image;
6456 register_module (mono_object_domain (moduleb), moduleb, image);
6458 /* register the module with the assembly */
6459 ass = ab->dynamic_assembly->assembly.image;
6460 module_count = ass->module_count;
6461 new_modules = g_new0 (MonoImage *, module_count + 1);
6464 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6465 new_modules [module_count] = &image->image;
6466 mono_image_addref (&image->image);
6468 g_free (ass->modules);
6469 ass->modules = new_modules;
6470 ass->module_count ++;
6475 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6477 MonoDynamicImage *image = moduleb->dynamic_image;
6479 g_assert (type->type);
6480 image->wrappers_type = mono_class_from_mono_type (type->type);
6486 * mono_assembly_get_object:
6487 * @domain: an app domain
6488 * @assembly: an assembly
6490 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6492 MonoReflectionAssembly*
6493 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6495 static MonoClass *assembly_type;
6496 MonoReflectionAssembly *res;
6498 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6499 if (!assembly_type) {
6500 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6502 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6504 assembly_type = klass;
6506 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6507 res->assembly = assembly;
6509 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6514 MonoReflectionModule*
6515 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6517 static MonoClass *module_type;
6518 MonoReflectionModule *res;
6521 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6523 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6525 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6527 module_type = klass;
6529 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6532 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6534 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6535 basename = g_path_get_basename (image->name);
6536 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6537 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6541 if (image->assembly->image == image) {
6542 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6546 if (image->assembly->image->modules) {
6547 for (i = 0; i < image->assembly->image->module_count; i++) {
6548 if (image->assembly->image->modules [i] == image)
6549 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6551 g_assert (res->token);
6555 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6558 MonoReflectionModule*
6559 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6561 static MonoClass *module_type;
6562 MonoReflectionModule *res;
6563 MonoTableInfo *table;
6564 guint32 cols [MONO_FILE_SIZE];
6566 guint32 i, name_idx;
6570 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6572 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6574 module_type = klass;
6576 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6578 table = &image->tables [MONO_TABLE_FILE];
6579 g_assert (table_index < table->rows);
6580 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6583 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6584 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6586 /* Check whenever the row has a corresponding row in the moduleref table */
6587 table = &image->tables [MONO_TABLE_MODULEREF];
6588 for (i = 0; i < table->rows; ++i) {
6589 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6590 val = mono_metadata_string_heap (image, name_idx);
6591 if (strcmp (val, name) == 0)
6592 res->image = image->modules [i];
6595 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6596 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6597 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6598 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6599 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6605 verify_safe_for_managed_space (MonoType *type)
6607 switch (type->type) {
6609 case MONO_TYPE_ARRAY:
6610 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6612 return verify_safe_for_managed_space (type->data.type);
6613 case MONO_TYPE_SZARRAY:
6614 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6615 case MONO_TYPE_GENERICINST: {
6616 MonoGenericInst *inst = type->data.generic_class->inst;
6620 for (i = 0; i < inst->type_argc; ++i)
6621 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6627 case MONO_TYPE_MVAR:
6635 mono_type_normalize (MonoType *type)
6638 MonoGenericClass *gclass;
6639 MonoGenericInst *ginst;
6641 MonoGenericContainer *gcontainer;
6642 MonoType **argv = NULL;
6643 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6645 if (type->type != MONO_TYPE_GENERICINST)
6648 gclass = type->data.generic_class;
6649 ginst = gclass->context.class_inst;
6650 if (!ginst->is_open)
6653 gtd = gclass->container_class;
6654 gcontainer = gtd->generic_container;
6655 argv = g_newa (MonoType*, ginst->type_argc);
6657 for (i = 0; i < ginst->type_argc; ++i) {
6658 MonoType *t = ginst->type_argv [i], *norm;
6659 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6660 is_denorm_gtd = FALSE;
6661 norm = mono_type_normalize (t);
6664 requires_rebind = TRUE;
6668 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6670 if (requires_rebind) {
6671 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6672 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6678 * mono_type_get_object:
6679 * @domain: an app domain
6682 * Return an System.MonoType object representing the type @type.
6685 mono_type_get_object (MonoDomain *domain, MonoType *type)
6687 MonoType *norm_type;
6688 MonoReflectionType *res;
6689 MonoClass *klass = mono_class_from_mono_type (type);
6691 /*we must avoid using @type as it might have come
6692 * from a mono_metadata_type_dup and the caller
6693 * expects that is can be freed.
6694 * Using the right type from
6696 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6698 /* void is very common */
6699 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6700 return (MonoReflectionType*)domain->typeof_void;
6703 * If the vtable of the given class was already created, we can use
6704 * the MonoType from there and avoid all locking and hash table lookups.
6706 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6707 * that the resulting object is different.
6709 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6710 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6711 if (vtable && vtable->type)
6712 return vtable->type;
6715 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6716 mono_domain_lock (domain);
6717 if (!domain->type_hash)
6718 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6719 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6720 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6721 mono_domain_unlock (domain);
6722 mono_loader_unlock ();
6726 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6727 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6728 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6729 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6730 * artifact of how generics are encoded and should be transparent to managed code so we
6731 * need to weed out this diference when retrieving managed System.Type objects.
6733 norm_type = mono_type_normalize (type);
6734 if (norm_type != type) {
6735 res = mono_type_get_object (domain, norm_type);
6736 mono_g_hash_table_insert (domain->type_hash, type, res);
6737 mono_domain_unlock (domain);
6738 mono_loader_unlock ();
6742 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6743 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6746 if (!verify_safe_for_managed_space (type)) {
6747 mono_domain_unlock (domain);
6748 mono_loader_unlock ();
6749 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6752 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6753 gboolean is_type_done = TRUE;
6754 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6755 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6756 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6758 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6759 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6761 if (gparam->owner && gparam->owner->is_method) {
6762 MonoMethod *method = gparam->owner->owner.method;
6763 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6764 is_type_done = FALSE;
6765 } else if (gparam->owner && !gparam->owner->is_method) {
6766 MonoClass *klass = gparam->owner->owner.klass;
6767 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6768 is_type_done = FALSE;
6772 /* g_assert_not_reached (); */
6773 /* should this be considered an error condition? */
6774 if (is_type_done && !type->byref) {
6775 mono_domain_unlock (domain);
6776 mono_loader_unlock ();
6777 return mono_class_get_ref_info (klass);
6780 /* This is stored in vtables/JITted code so it has to be pinned */
6781 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6783 mono_g_hash_table_insert (domain->type_hash, type, res);
6785 if (type->type == MONO_TYPE_VOID)
6786 domain->typeof_void = (MonoObject*)res;
6788 mono_domain_unlock (domain);
6789 mono_loader_unlock ();
6794 * mono_method_get_object:
6795 * @domain: an app domain
6797 * @refclass: the reflected type (can be NULL)
6799 * Return an System.Reflection.MonoMethod object representing the method @method.
6801 MonoReflectionMethod*
6802 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6805 * We use the same C representation for methods and constructors, but the type
6806 * name in C# is different.
6808 static MonoClass *System_Reflection_MonoMethod = NULL;
6809 static MonoClass *System_Reflection_MonoCMethod = NULL;
6810 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6811 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6813 MonoReflectionMethod *ret;
6815 if (method->is_inflated) {
6816 MonoReflectionGenericMethod *gret;
6818 refclass = method->klass;
6819 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6820 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6821 if (!System_Reflection_MonoGenericCMethod)
6822 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6823 klass = System_Reflection_MonoGenericCMethod;
6825 if (!System_Reflection_MonoGenericMethod)
6826 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6827 klass = System_Reflection_MonoGenericMethod;
6829 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6830 gret->method.method = method;
6831 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6832 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6833 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6837 refclass = method->klass;
6839 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6840 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6841 if (!System_Reflection_MonoCMethod)
6842 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6843 klass = System_Reflection_MonoCMethod;
6846 if (!System_Reflection_MonoMethod)
6847 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6848 klass = System_Reflection_MonoMethod;
6850 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6851 ret->method = method;
6852 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6853 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6857 * mono_method_clear_object:
6859 * Clear the cached reflection objects for the dynamic method METHOD.
6862 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6865 g_assert (method_is_dynamic (method));
6867 klass = method->klass;
6869 clear_cached_object (domain, method, klass);
6870 klass = klass->parent;
6872 /* Added by mono_param_get_objects () */
6873 clear_cached_object (domain, &(method->signature), NULL);
6874 klass = method->klass;
6876 clear_cached_object (domain, &(method->signature), klass);
6877 klass = klass->parent;
6882 * mono_field_get_object:
6883 * @domain: an app domain
6887 * Return an System.Reflection.MonoField object representing the field @field
6890 MonoReflectionField*
6891 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6893 MonoReflectionField *res;
6894 static MonoClass *monofield_klass;
6896 CHECK_OBJECT (MonoReflectionField *, field, klass);
6897 if (!monofield_klass)
6898 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6899 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6902 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6904 if (is_field_on_inst (field)) {
6905 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6906 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6909 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6910 res->attrs = mono_field_get_flags (field);
6912 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6916 * mono_property_get_object:
6917 * @domain: an app domain
6919 * @property: a property
6921 * Return an System.Reflection.MonoProperty object representing the property @property
6924 MonoReflectionProperty*
6925 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6927 MonoReflectionProperty *res;
6928 static MonoClass *monoproperty_klass;
6930 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6931 if (!monoproperty_klass)
6932 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6933 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6935 res->property = property;
6936 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6940 * mono_event_get_object:
6941 * @domain: an app domain
6945 * Return an System.Reflection.MonoEvent object representing the event @event
6948 MonoReflectionEvent*
6949 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6951 MonoReflectionEvent *res;
6952 MonoReflectionMonoEvent *mono_event;
6953 static MonoClass *monoevent_klass;
6955 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6956 if (!monoevent_klass)
6957 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6958 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6959 mono_event->klass = klass;
6960 mono_event->event = event;
6961 res = (MonoReflectionEvent*)mono_event;
6962 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6966 * mono_get_reflection_missing_object:
6967 * @domain: Domain where the object lives
6969 * Returns the System.Reflection.Missing.Value singleton object
6970 * (of type System.Reflection.Missing).
6972 * Used as the value for ParameterInfo.DefaultValue when Optional
6976 mono_get_reflection_missing_object (MonoDomain *domain)
6979 static MonoClassField *missing_value_field = NULL;
6981 if (!missing_value_field) {
6982 MonoClass *missing_klass;
6983 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6984 mono_class_init (missing_klass);
6985 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6986 g_assert (missing_value_field);
6988 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6994 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6997 *dbnull = mono_get_dbnull_object (domain);
7002 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7004 if (!*reflection_missing)
7005 *reflection_missing = mono_get_reflection_missing_object (domain);
7006 return *reflection_missing;
7010 * mono_param_get_objects:
7011 * @domain: an app domain
7014 * Return an System.Reflection.ParameterInfo array object representing the parameters
7015 * in the method @method.
7018 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7020 static MonoClass *System_Reflection_ParameterInfo;
7021 static MonoClass *System_Reflection_ParameterInfo_array;
7023 MonoArray *res = NULL;
7024 MonoReflectionMethod *member = NULL;
7025 MonoReflectionParameter *param = NULL;
7026 char **names, **blobs = NULL;
7027 guint32 *types = NULL;
7028 MonoType *type = NULL;
7029 MonoObject *dbnull = NULL;
7030 MonoObject *missing = NULL;
7031 MonoMarshalSpec **mspecs;
7032 MonoMethodSignature *sig;
7033 MonoVTable *pinfo_vtable;
7036 if (!System_Reflection_ParameterInfo_array) {
7039 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7041 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7043 mono_memory_barrier ();
7044 System_Reflection_ParameterInfo = klass;
7047 klass = mono_array_class_get (klass, 1);
7048 mono_memory_barrier ();
7049 System_Reflection_ParameterInfo_array = klass;
7052 sig = mono_method_signature_checked (method, &error);
7053 if (!mono_error_ok (&error))
7054 mono_error_raise_exception (&error);
7056 if (!sig->param_count)
7057 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
7059 /* Note: the cache is based on the address of the signature into the method
7060 * since we already cache MethodInfos with the method as keys.
7062 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7064 member = mono_method_get_object (domain, method, refclass);
7065 names = g_new (char *, sig->param_count);
7066 mono_method_get_param_names (method, (const char **) names);
7068 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7069 mono_method_get_marshal_info (method, mspecs);
7071 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7072 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7073 for (i = 0; i < sig->param_count; ++i) {
7074 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7075 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7076 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7077 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7078 param->PositionImpl = i;
7079 param->AttrsImpl = sig->params [i]->attrs;
7081 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7082 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7083 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7085 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7089 blobs = g_new0 (char *, sig->param_count);
7090 types = g_new0 (guint32, sig->param_count);
7091 get_default_param_value_blobs (method, blobs, types);
7094 /* Build MonoType for the type from the Constant Table */
7096 type = g_new0 (MonoType, 1);
7097 type->type = types [i];
7098 type->data.klass = NULL;
7099 if (types [i] == MONO_TYPE_CLASS)
7100 type->data.klass = mono_defaults.object_class;
7101 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7102 /* For enums, types [i] contains the base type */
7104 type->type = MONO_TYPE_VALUETYPE;
7105 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7107 type->data.klass = mono_class_from_mono_type (type);
7109 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7111 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7112 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7113 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7114 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7116 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7122 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7124 mono_array_setref (res, i, param);
7131 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7133 mono_metadata_free_marshal_spec (mspecs [i]);
7136 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7140 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7142 return mono_param_get_objects_internal (domain, method, NULL);
7146 * mono_method_body_get_object:
7147 * @domain: an app domain
7150 * Return an System.Reflection.MethodBody object representing the method @method.
7152 MonoReflectionMethodBody*
7153 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7155 static MonoClass *System_Reflection_MethodBody = NULL;
7156 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7157 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7158 MonoReflectionMethodBody *ret;
7159 MonoMethodHeader *header;
7161 guint32 method_rva, local_var_sig_token;
7163 unsigned char format, flags;
7166 /* for compatibility with .net */
7167 if (method_is_dynamic (method))
7168 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7170 if (!System_Reflection_MethodBody)
7171 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7172 if (!System_Reflection_LocalVariableInfo)
7173 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7174 if (!System_Reflection_ExceptionHandlingClause)
7175 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7177 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7179 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7180 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7181 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7182 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7183 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7186 image = method->klass->image;
7187 header = mono_method_get_header (method);
7189 if (!image_is_dynamic (image)) {
7190 /* Obtain local vars signature token */
7191 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7192 ptr = mono_image_rva_map (image, method_rva);
7193 flags = *(const unsigned char *) ptr;
7194 format = flags & METHOD_HEADER_FORMAT_MASK;
7196 case METHOD_HEADER_TINY_FORMAT:
7197 local_var_sig_token = 0;
7199 case METHOD_HEADER_FAT_FORMAT:
7203 local_var_sig_token = read32 (ptr);
7206 g_assert_not_reached ();
7209 local_var_sig_token = 0; //FIXME
7211 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7213 ret->init_locals = header->init_locals;
7214 ret->max_stack = header->max_stack;
7215 ret->local_var_sig_token = local_var_sig_token;
7216 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7217 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7220 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7221 for (i = 0; i < header->num_locals; ++i) {
7222 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7223 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7224 info->is_pinned = header->locals [i]->pinned;
7225 info->local_index = i;
7226 mono_array_setref (ret->locals, i, info);
7230 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7231 for (i = 0; i < header->num_clauses; ++i) {
7232 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7233 MonoExceptionClause *clause = &header->clauses [i];
7235 info->flags = clause->flags;
7236 info->try_offset = clause->try_offset;
7237 info->try_length = clause->try_len;
7238 info->handler_offset = clause->handler_offset;
7239 info->handler_length = clause->handler_len;
7240 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7241 info->filter_offset = clause->data.filter_offset;
7242 else if (clause->data.catch_class)
7243 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7245 mono_array_setref (ret->clauses, i, info);
7248 mono_metadata_free_mh (header);
7249 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7254 * mono_get_dbnull_object:
7255 * @domain: Domain where the object lives
7257 * Returns the System.DBNull.Value singleton object
7259 * Used as the value for ParameterInfo.DefaultValue
7262 mono_get_dbnull_object (MonoDomain *domain)
7265 static MonoClassField *dbnull_value_field = NULL;
7267 if (!dbnull_value_field) {
7268 MonoClass *dbnull_klass;
7269 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7270 mono_class_init (dbnull_klass);
7271 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7272 g_assert (dbnull_value_field);
7274 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7280 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7282 guint32 param_index, i, lastp, crow = 0;
7283 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7286 MonoClass *klass = method->klass;
7287 MonoImage *image = klass->image;
7288 MonoMethodSignature *methodsig = mono_method_signature (method);
7290 MonoTableInfo *constt;
7291 MonoTableInfo *methodt;
7292 MonoTableInfo *paramt;
7294 if (!methodsig->param_count)
7297 mono_class_init (klass);
7299 if (image_is_dynamic (klass->image)) {
7300 MonoReflectionMethodAux *aux;
7301 if (method->is_inflated)
7302 method = ((MonoMethodInflated*)method)->declaring;
7303 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7304 if (aux && aux->param_defaults) {
7305 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7306 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7311 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7312 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7313 constt = &image->tables [MONO_TABLE_CONSTANT];
7315 idx = mono_method_get_index (method) - 1;
7316 g_assert (idx != -1);
7318 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7319 if (idx + 1 < methodt->rows)
7320 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7322 lastp = paramt->rows + 1;
7324 for (i = param_index; i < lastp; ++i) {
7327 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7328 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7330 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7333 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7338 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7339 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7340 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7347 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7352 MonoType *basetype = type;
7357 klass = mono_class_from_mono_type (type);
7358 if (klass->valuetype) {
7359 object = mono_object_new (domain, klass);
7360 retval = ((gchar *) object + sizeof (MonoObject));
7361 if (klass->enumtype)
7362 basetype = mono_class_enum_basetype (klass);
7367 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7374 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7377 gboolean quoted = FALSE;
7379 memset (assembly, 0, sizeof (MonoAssemblyName));
7380 assembly->culture = "";
7381 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7388 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7399 /* Remove trailing whitespace */
7401 while (*s && g_ascii_isspace (*s))
7404 while (g_ascii_isspace (*p))
7407 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7409 assembly->major = strtoul (p, &s, 10);
7410 if (s == p || *s != '.')
7413 assembly->minor = strtoul (p, &s, 10);
7414 if (s == p || *s != '.')
7417 assembly->build = strtoul (p, &s, 10);
7418 if (s == p || *s != '.')
7421 assembly->revision = strtoul (p, &s, 10);
7425 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7427 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7428 assembly->culture = "";
7431 assembly->culture = p;
7432 while (*p && *p != ',') {
7436 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7438 if (strncmp (p, "null", 4) == 0) {
7443 while (*p && *p != ',') {
7446 len = (p - start + 1);
7447 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7448 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7449 g_strlcpy ((char*)assembly->public_key_token, start, len);
7452 while (*p && *p != ',')
7456 while (g_ascii_isspace (*p) || *p == ',') {
7470 * mono_reflection_parse_type:
7473 * Parse a type name as accepted by the GetType () method and output the info
7474 * extracted in the info structure.
7475 * the name param will be mangled, so, make a copy before passing it to this function.
7476 * The fields in info will be valid until the memory pointed to by name is valid.
7478 * See also mono_type_get_name () below.
7480 * Returns: 0 on parse error.
7483 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7484 MonoTypeNameParse *info)
7486 char *start, *p, *w, *last_point, *startn;
7487 int in_modifiers = 0;
7488 int isbyref = 0, rank = 0, isptr = 0;
7490 start = p = w = name;
7492 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7493 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7494 info->name = info->name_space = NULL;
7495 info->nested = NULL;
7496 info->modifiers = NULL;
7497 info->type_arguments = NULL;
7499 /* last_point separates the namespace from the name */
7502 while (*p == ' ') p++, start++, w++, name++;
7507 *p = 0; /* NULL terminate the name */
7509 info->nested = g_list_append (info->nested, startn);
7510 /* we have parsed the nesting namespace + name */
7514 info->name_space = start;
7516 info->name = last_point + 1;
7518 info->name_space = (char *)"";
7546 info->name_space = start;
7548 info->name = last_point + 1;
7550 info->name_space = (char *)"";
7557 if (isbyref) /* only one level allowed by the spec */
7561 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7565 if (isbyref) /* pointer to ref not okay */
7567 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7572 if (isbyref) /* array of ref and generic ref are not okay */
7574 //Decide if it's an array of a generic argument list
7579 if (*p == ',' || *p == '*' || *p == ']') { //array
7587 else if (*p == '*') /* '*' means unknown lower bound */
7588 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7595 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7597 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7600 info->type_arguments = g_ptr_array_new ();
7602 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7603 gboolean fqname = FALSE;
7605 g_ptr_array_add (info->type_arguments, subinfo);
7607 while (*p == ' ') p++;
7613 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7616 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7617 if (fqname && (*p != ']')) {
7625 while (*p && (*p != ']'))
7633 if (g_ascii_isspace (*aname)) {
7640 !assembly_name_to_aname (&subinfo->assembly, aname))
7642 } else if (fqname && (*p == ']')) {
7664 if (g_ascii_isspace (*p)) {
7671 return 0; /* missing assembly name */
7672 if (!assembly_name_to_aname (&info->assembly, p))
7678 if (info->assembly.name)
7681 // *w = 0; /* terminate class name */
7683 if (!info->name || !*info->name)
7687 /* add other consistency checks */
7693 * mono_identifier_unescape_type_name_chars:
7694 * @identifier: the display name of a mono type
7697 * The name in internal form, that is without escaping backslashes.
7699 * The string is modified in place!
7702 mono_identifier_unescape_type_name_chars(char* identifier)
7707 for (w = r = identifier; *r != 0; r++)
7725 mono_identifier_unescape_info (MonoTypeNameParse* info);
7728 unescape_each_type_argument(void* data, void* user_data)
7730 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7731 mono_identifier_unescape_info (info);
7735 unescape_each_nested_name (void* data, void* user_data)
7737 char* nested_name = (char*) data;
7738 mono_identifier_unescape_type_name_chars(nested_name);
7742 * mono_identifier_unescape_info:
7744 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7748 * Destructively updates the info by unescaping the identifiers that
7749 * comprise the type namespace, name, nested types (if any) and
7750 * generic type arguments (if any).
7752 * The resulting info has the names in internal form.
7756 mono_identifier_unescape_info (MonoTypeNameParse *info)
7760 mono_identifier_unescape_type_name_chars(info->name_space);
7761 mono_identifier_unescape_type_name_chars(info->name);
7762 // but don't escape info->assembly
7763 if (info->type_arguments)
7764 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7766 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7770 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7772 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7774 mono_identifier_unescape_info (info);
7780 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7782 gboolean type_resolve = FALSE;
7784 MonoImage *rootimage = image;
7786 if (info->assembly.name) {
7787 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7788 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7790 * This could happen in the AOT compiler case when the search hook is not
7793 assembly = image->assembly;
7795 /* then we must load the assembly ourselve - see #60439 */
7796 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7800 image = assembly->image;
7801 } else if (!image) {
7802 image = mono_defaults.corlib;
7805 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7806 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7807 image = mono_defaults.corlib;
7808 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7815 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7820 gboolean bounded = FALSE;
7823 image = mono_defaults.corlib;
7826 rootimage = mono_defaults.corlib;
7830 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7831 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7833 klass = mono_class_from_name (image, info->name_space, info->name);
7837 for (mod = info->nested; mod; mod = mod->next) {
7838 gpointer iter = NULL;
7842 mono_class_init (parent);
7844 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7846 char *nested_name, *nested_nspace;
7847 gboolean match = TRUE;
7849 lastp = strrchr (mod->data, '.');
7851 /* Nested classes can have namespaces */
7854 nested_name = g_strdup (lastp + 1);
7855 nspace_len = lastp - (char*)mod->data;
7856 nested_nspace = g_malloc (nspace_len + 1);
7857 memcpy (nested_nspace, mod->data, nspace_len);
7858 nested_nspace [nspace_len] = '\0';
7861 nested_name = mod->data;
7862 nested_nspace = NULL;
7865 if (nested_nspace) {
7867 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7870 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7876 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7879 if (strcmp (klass->name, nested_name) != 0)
7884 g_free (nested_name);
7885 g_free (nested_nspace);
7897 if (info->type_arguments) {
7898 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7899 MonoReflectionType *the_type;
7903 for (i = 0; i < info->type_arguments->len; i++) {
7904 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7906 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7907 if (!type_args [i]) {
7913 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7915 instance = mono_reflection_bind_generic_parameters (
7916 the_type, info->type_arguments->len, type_args);
7922 klass = mono_class_from_mono_type (instance);
7925 for (mod = info->modifiers; mod; mod = mod->next) {
7926 modval = GPOINTER_TO_UINT (mod->data);
7927 if (!modval) { /* byref: must be last modifier */
7928 return &klass->this_arg;
7929 } else if (modval == -1) {
7930 klass = mono_ptr_class_get (&klass->byval_arg);
7931 } else if (modval == -2) {
7933 } else { /* array rank */
7934 klass = mono_bounded_array_class_get (klass, modval, bounded);
7938 return &klass->byval_arg;
7942 * mono_reflection_get_type:
7943 * @image: a metadata context
7944 * @info: type description structure
7945 * @ignorecase: flag for case-insensitive string compares
7946 * @type_resolve: whenever type resolve was already tried
7948 * Build a MonoType from the type description in @info.
7953 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7954 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7958 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7960 MonoReflectionAssemblyBuilder *abuilder;
7964 g_assert (assembly_is_dynamic (assembly));
7965 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7967 /* Enumerate all modules */
7970 if (abuilder->modules) {
7971 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7972 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7973 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7979 if (!type && abuilder->loaded_modules) {
7980 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7981 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7982 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7992 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7995 MonoReflectionAssembly *assembly;
7999 if (image && image_is_dynamic (image))
8000 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8002 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8005 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8012 *type_resolve = TRUE;
8015 /* Reconstruct the type name */
8016 fullName = g_string_new ("");
8017 if (info->name_space && (info->name_space [0] != '\0'))
8018 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8020 g_string_printf (fullName, "%s", info->name);
8021 for (mod = info->nested; mod; mod = mod->next)
8022 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8024 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8026 if (assembly_is_dynamic (assembly->assembly))
8027 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8029 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8032 g_string_free (fullName, TRUE);
8037 mono_reflection_free_type_info (MonoTypeNameParse *info)
8039 g_list_free (info->modifiers);
8040 g_list_free (info->nested);
8042 if (info->type_arguments) {
8045 for (i = 0; i < info->type_arguments->len; i++) {
8046 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
8048 mono_reflection_free_type_info (subinfo);
8049 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8053 g_ptr_array_free (info->type_arguments, TRUE);
8058 * mono_reflection_type_from_name:
8060 * @image: a metadata context (can be NULL).
8062 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8063 * it defaults to get the type from @image or, if @image is NULL or loading
8064 * from it fails, uses corlib.
8068 mono_reflection_type_from_name (char *name, MonoImage *image)
8070 MonoType *type = NULL;
8071 MonoTypeNameParse info;
8074 /* Make a copy since parse_type modifies its argument */
8075 tmp = g_strdup (name);
8077 /*g_print ("requested type %s\n", str);*/
8078 if (mono_reflection_parse_type (tmp, &info)) {
8079 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8083 mono_reflection_free_type_info (&info);
8088 * mono_reflection_get_token:
8090 * Return the metadata token of OBJ which should be an object
8091 * representing a metadata element.
8094 mono_reflection_get_token (MonoObject *obj)
8099 klass = obj->vtable->klass;
8101 if (strcmp (klass->name, "MethodBuilder") == 0) {
8102 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8104 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8105 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8106 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8108 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8109 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8110 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8112 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8113 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8114 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8115 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8116 } else if (strcmp (klass->name, "MonoType") == 0) {
8117 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8118 MonoClass *mc = mono_class_from_mono_type (type);
8119 if (!mono_class_init (mc))
8120 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8122 token = mc->type_token;
8123 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8124 strcmp (klass->name, "MonoMethod") == 0 ||
8125 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8126 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8127 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8128 if (m->method->is_inflated) {
8129 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8130 return inflated->declaring->token;
8132 token = m->method->token;
8134 } else if (strcmp (klass->name, "MonoField") == 0) {
8135 MonoReflectionField *f = (MonoReflectionField*)obj;
8137 if (is_field_on_inst (f->field)) {
8138 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8140 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8141 int field_index = f->field - dgclass->fields;
8144 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8145 obj = dgclass->field_objects [field_index];
8146 return mono_reflection_get_token (obj);
8149 token = mono_class_get_field_token (f->field);
8150 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8151 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8153 token = mono_class_get_property_token (p->property);
8154 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8155 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8157 token = mono_class_get_event_token (p->event);
8158 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8159 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8160 MonoClass *member_class = mono_object_class (p->MemberImpl);
8161 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8163 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8164 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8165 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8168 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8169 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8171 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8172 MonoException *ex = mono_get_exception_not_implemented (msg);
8174 mono_raise_exception (ex);
8181 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8185 int slen = mono_metadata_decode_value (p, &p);
8187 mono_error_init (error);
8189 n = g_memdup (p, slen + 1);
8191 t = mono_reflection_type_from_name (n, image);
8193 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8194 /* We don't free n, it's consumed by mono_error */
8195 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8201 return mono_class_from_mono_type (t);
8205 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8207 int slen, type = t->type;
8208 MonoClass *tklass = t->data.klass;
8210 mono_error_init (error);
8216 case MONO_TYPE_BOOLEAN: {
8217 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8222 case MONO_TYPE_CHAR:
8224 case MONO_TYPE_I2: {
8225 guint16 *val = g_malloc (sizeof (guint16));
8230 #if SIZEOF_VOID_P == 4
8236 case MONO_TYPE_I4: {
8237 guint32 *val = g_malloc (sizeof (guint32));
8242 #if SIZEOF_VOID_P == 8
8243 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8247 case MONO_TYPE_I8: {
8248 guint64 *val = g_malloc (sizeof (guint64));
8253 case MONO_TYPE_R8: {
8254 double *val = g_malloc (sizeof (double));
8259 case MONO_TYPE_VALUETYPE:
8260 if (t->data.klass->enumtype) {
8261 type = mono_class_enum_basetype (t->data.klass)->type;
8264 MonoClass *k = t->data.klass;
8266 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8267 guint64 *val = g_malloc (sizeof (guint64));
8273 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8276 case MONO_TYPE_STRING:
8277 if (*p == (char)0xFF) {
8281 slen = mono_metadata_decode_value (p, &p);
8283 return mono_string_new_len (mono_domain_get (), p, slen);
8284 case MONO_TYPE_CLASS: {
8287 if (*p == (char)0xFF) {
8292 slen = mono_metadata_decode_value (p, &p);
8293 n = g_memdup (p, slen + 1);
8295 t = mono_reflection_type_from_name (n, image);
8297 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8298 /* We don't free n, it's consumed by mono_error */
8299 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8304 return mono_type_get_object (mono_domain_get (), t);
8306 case MONO_TYPE_OBJECT: {
8309 MonoClass *subc = NULL;
8314 } else if (subt == 0x0E) {
8315 type = MONO_TYPE_STRING;
8317 } else if (subt == 0x1D) {
8318 MonoType simple_type = {{0}};
8322 type = MONO_TYPE_SZARRAY;
8323 if (etype == 0x50) {
8324 tklass = mono_defaults.systemtype_class;
8325 } else if (etype == 0x55) {
8326 tklass = load_cattr_enum_type (image, p, &p, error);
8327 if (!mono_error_ok (error))
8331 /* See Partition II, Appendix B3 */
8332 etype = MONO_TYPE_OBJECT;
8333 simple_type.type = etype;
8334 tklass = mono_class_from_mono_type (&simple_type);
8337 } else if (subt == 0x55) {
8340 slen = mono_metadata_decode_value (p, &p);
8341 n = g_memdup (p, slen + 1);
8343 t = mono_reflection_type_from_name (n, image);
8345 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8346 /* We don't free n, it's consumed by mono_error */
8347 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8352 subc = mono_class_from_mono_type (t);
8353 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8354 MonoType simple_type = {{0}};
8355 simple_type.type = subt;
8356 subc = mono_class_from_mono_type (&simple_type);
8358 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8360 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8362 if (mono_error_ok (error)) {
8363 obj = mono_object_new (mono_domain_get (), subc);
8364 g_assert (!subc->has_references);
8365 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8371 case MONO_TYPE_SZARRAY: {
8373 guint32 i, alen, basetype;
8376 if (alen == 0xffffffff) {
8380 arr = mono_array_new (mono_domain_get(), tklass, alen);
8381 basetype = tklass->byval_arg.type;
8382 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8383 basetype = mono_class_enum_basetype (tklass)->type;
8388 case MONO_TYPE_BOOLEAN:
8389 for (i = 0; i < alen; i++) {
8390 MonoBoolean val = *p++;
8391 mono_array_set (arr, MonoBoolean, i, val);
8394 case MONO_TYPE_CHAR:
8397 for (i = 0; i < alen; i++) {
8398 guint16 val = read16 (p);
8399 mono_array_set (arr, guint16, i, val);
8406 for (i = 0; i < alen; i++) {
8407 guint32 val = read32 (p);
8408 mono_array_set (arr, guint32, i, val);
8413 for (i = 0; i < alen; i++) {
8416 mono_array_set (arr, double, i, val);
8422 for (i = 0; i < alen; i++) {
8423 guint64 val = read64 (p);
8424 mono_array_set (arr, guint64, i, val);
8428 case MONO_TYPE_CLASS:
8429 case MONO_TYPE_OBJECT:
8430 case MONO_TYPE_STRING:
8431 case MONO_TYPE_SZARRAY:
8432 for (i = 0; i < alen; i++) {
8433 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8434 if (!mono_error_ok (error))
8436 mono_array_setref (arr, i, item);
8440 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8446 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8452 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8454 static MonoClass *klass;
8455 static MonoMethod *ctor;
8457 void *params [2], *unboxed;
8460 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8462 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8464 params [0] = mono_type_get_object (mono_domain_get (), t);
8466 retval = mono_object_new (mono_domain_get (), klass);
8467 unboxed = mono_object_unbox (retval);
8468 mono_runtime_invoke (ctor, unboxed, params, NULL);
8474 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8476 static MonoClass *klass;
8477 static MonoMethod *ctor;
8479 void *unboxed, *params [2];
8482 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8484 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8487 params [1] = typedarg;
8488 retval = mono_object_new (mono_domain_get (), klass);
8489 unboxed = mono_object_unbox (retval);
8490 mono_runtime_invoke (ctor, unboxed, params, NULL);
8496 type_is_reference (MonoType *type)
8498 switch (type->type) {
8499 case MONO_TYPE_BOOLEAN:
8500 case MONO_TYPE_CHAR:
8513 case MONO_TYPE_VALUETYPE:
8521 free_param_data (MonoMethodSignature *sig, void **params) {
8523 for (i = 0; i < sig->param_count; ++i) {
8524 if (!type_is_reference (sig->params [i]))
8525 g_free (params [i]);
8530 * Find the field index in the metadata FieldDef table.
8533 find_field_index (MonoClass *klass, MonoClassField *field) {
8536 for (i = 0; i < klass->field.count; ++i) {
8537 if (field == &klass->fields [i])
8538 return klass->field.first + 1 + i;
8544 * Find the property index in the metadata Property table.
8547 find_property_index (MonoClass *klass, MonoProperty *property) {
8550 for (i = 0; i < klass->ext->property.count; ++i) {
8551 if (property == &klass->ext->properties [i])
8552 return klass->ext->property.first + 1 + i;
8558 * Find the event index in the metadata Event table.
8561 find_event_index (MonoClass *klass, MonoEvent *event) {
8564 for (i = 0; i < klass->ext->event.count; ++i) {
8565 if (event == &klass->ext->events [i])
8566 return klass->ext->event.first + 1 + i;
8572 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8574 const char *p = (const char*)data;
8576 guint32 i, j, num_named;
8578 void *params_buf [32];
8579 void **params = NULL;
8580 MonoMethodSignature *sig;
8581 MonoObject *exc = NULL;
8583 mono_error_init (error);
8585 mono_class_init (method->klass);
8587 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8588 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8593 attr = mono_object_new (mono_domain_get (), method->klass);
8594 mono_runtime_invoke (method, attr, NULL, NULL);
8598 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8601 /*g_print ("got attr %s\n", method->klass->name);*/
8603 sig = mono_method_signature (method);
8604 if (sig->param_count < 32) {
8605 params = params_buf;
8606 memset (params, 0, sizeof (void*) * sig->param_count);
8608 /* Allocate using GC so it gets GC tracking */
8609 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8614 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8615 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8616 if (!mono_error_ok (error))
8621 attr = mono_object_new (mono_domain_get (), method->klass);
8623 mono_runtime_invoke (method, attr, params, &exc);
8626 num_named = read16 (named);
8628 for (j = 0; j < num_named; j++) {
8630 char *name, named_type, data_type;
8631 named_type = *named++;
8632 data_type = *named++; /* type of data */
8633 if (data_type == MONO_TYPE_SZARRAY)
8634 data_type = *named++;
8635 if (data_type == MONO_TYPE_ENUM) {
8638 type_len = mono_metadata_decode_blob_size (named, &named);
8639 type_name = g_malloc (type_len + 1);
8640 memcpy (type_name, named, type_len);
8641 type_name [type_len] = 0;
8643 /* FIXME: lookup the type and check type consistency */
8646 name_len = mono_metadata_decode_blob_size (named, &named);
8647 name = g_malloc (name_len + 1);
8648 memcpy (name, named, name_len);
8649 name [name_len] = 0;
8651 if (named_type == 0x53) {
8652 MonoClassField *field;
8655 /* how this fail is a blackbox */
8656 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8658 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8663 val = load_cattr_value (image, field->type, named, &named, error);
8664 if (!mono_error_ok (error)) {
8666 if (!type_is_reference (field->type))
8671 mono_field_set_value (attr, field, val);
8672 if (!type_is_reference (field->type))
8674 } else if (named_type == 0x54) {
8677 MonoType *prop_type;
8679 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8682 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8688 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8693 /* can we have more that 1 arg in a custom attr named property? */
8694 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8695 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8697 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8698 if (!mono_error_ok (error)) {
8700 if (!type_is_reference (prop_type))
8701 g_free (pparams [0]);
8706 mono_property_set_value (prop, attr, pparams, NULL);
8707 if (!type_is_reference (prop_type))
8708 g_free (pparams [0]);
8713 free_param_data (method->signature, params);
8714 if (params != params_buf)
8715 mono_gc_free_fixed (params);
8720 free_param_data (method->signature, params);
8721 if (params != params_buf)
8722 mono_gc_free_fixed (params);
8724 mono_raise_exception ((MonoException*)exc);
8729 * mono_reflection_create_custom_attr_data_args:
8731 * Create an array of typed and named arguments from the cattr blob given by DATA.
8732 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8733 * NAMED_ARG_INFO will contain information about the named arguments.
8736 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, MonoError *error)
8738 MonoArray *typedargs, *namedargs;
8739 MonoClass *attrklass;
8741 const char *p = (const char*)data;
8743 guint32 i, j, num_named;
8744 CattrNamedArg *arginfo = NULL;
8748 *named_arg_info = NULL;
8750 mono_error_init (error);
8752 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8753 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8757 mono_class_init (method->klass);
8759 domain = mono_domain_get ();
8761 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8764 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8768 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8772 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8773 if (!mono_error_ok (error)) {
8774 if (!type_is_reference (mono_method_signature (method)->params [i]))
8779 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8780 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8781 mono_array_setref (typedargs, i, obj);
8783 if (!type_is_reference (mono_method_signature (method)->params [i]))
8788 num_named = read16 (named);
8789 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8791 attrklass = method->klass;
8793 arginfo = g_new0 (CattrNamedArg, num_named);
8794 *named_arg_info = arginfo;
8796 for (j = 0; j < num_named; j++) {
8798 char *name, named_type, data_type;
8799 named_type = *named++;
8800 data_type = *named++; /* type of data */
8801 if (data_type == MONO_TYPE_SZARRAY)
8802 data_type = *named++;
8803 if (data_type == MONO_TYPE_ENUM) {
8806 type_len = mono_metadata_decode_blob_size (named, &named);
8807 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8810 type_name = g_malloc (type_len + 1);
8811 memcpy (type_name, named, type_len);
8812 type_name [type_len] = 0;
8814 /* FIXME: lookup the type and check type consistency */
8817 name_len = mono_metadata_decode_blob_size (named, &named);
8818 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8820 name = g_malloc (name_len + 1);
8821 memcpy (name, named, name_len);
8822 name [name_len] = 0;
8824 if (named_type == 0x53) {
8826 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8834 arginfo [j].type = field->type;
8835 arginfo [j].field = field;
8837 val = load_cattr_value (image, field->type, named, &named, error);
8838 if (!mono_error_ok (error)) {
8839 if (!type_is_reference (field->type))
8845 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8846 mono_array_setref (namedargs, j, obj);
8847 if (!type_is_reference (field->type))
8849 } else if (named_type == 0x54) {
8851 MonoType *prop_type;
8852 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8855 if (!prop || !prop->set) {
8860 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8861 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8863 arginfo [j].type = prop_type;
8864 arginfo [j].prop = prop;
8866 val = load_cattr_value (image, prop_type, named, &named, error);
8867 if (!mono_error_ok (error)) {
8868 if (!type_is_reference (prop_type))
8874 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8875 mono_array_setref (namedargs, j, obj);
8876 if (!type_is_reference (prop_type))
8882 *typed_args = typedargs;
8883 *named_args = namedargs;
8886 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8888 *named_arg_info = NULL;
8892 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8895 MonoArray *typedargs, *namedargs;
8898 CattrNamedArg *arginfo = NULL;
8908 image = assembly->assembly->image;
8909 method = ref_method->method;
8910 domain = mono_object_domain (ref_method);
8912 if (!mono_class_init (method->klass))
8913 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8915 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8916 if (!mono_error_ok (&error))
8917 mono_error_raise_exception (&error);
8918 if (mono_loader_get_last_error ())
8919 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8921 if (!typedargs || !namedargs) {
8926 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8927 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8928 MonoObject *typedarg;
8930 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8931 mono_array_setref (typedargs, i, typedarg);
8934 for (i = 0; i < mono_array_length (namedargs); ++i) {
8935 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8936 MonoObject *typedarg, *namedarg, *minfo;
8938 if (arginfo [i].prop)
8939 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8941 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8943 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8944 namedarg = create_cattr_named_arg (minfo, typedarg);
8946 mono_array_setref (namedargs, i, namedarg);
8949 *ctor_args = typedargs;
8950 *named_args = namedargs;
8955 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8957 static MonoMethod *ctor;
8962 g_assert (image->assembly);
8965 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8967 domain = mono_domain_get ();
8968 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8969 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8970 params [1] = mono_assembly_get_object (domain, image->assembly);
8971 params [2] = (gpointer)&cattr->data;
8972 params [3] = &cattr->data_size;
8973 mono_runtime_invoke (ctor, attr, params, NULL);
8978 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8984 mono_error_init (error);
8987 for (i = 0; i < cinfo->num_attrs; ++i) {
8988 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8992 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8994 for (i = 0; i < cinfo->num_attrs; ++i) {
8995 if (!cinfo->attrs [i].ctor)
8996 /* The cattr type is not finished yet */
8997 /* We should include the type name but cinfo doesn't contain it */
8998 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8999 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9000 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9001 if (!mono_error_ok (error))
9003 mono_array_setref (result, n, attr);
9011 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9014 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9015 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9021 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9027 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9028 for (i = 0; i < cinfo->num_attrs; ++i) {
9029 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9030 mono_array_setref (result, i, attr);
9036 * mono_custom_attrs_from_index:
9038 * Returns: NULL if no attributes are found or if a loading error occurs.
9041 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9043 guint32 mtoken, i, len;
9044 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9046 MonoCustomAttrInfo *ainfo;
9047 GList *tmp, *list = NULL;
9049 MonoCustomAttrEntry* attr;
9051 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9053 i = mono_metadata_custom_attrs_from_index (image, idx);
9057 while (i < ca->rows) {
9058 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9060 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9063 len = g_list_length (list);
9066 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9067 ainfo->num_attrs = len;
9068 ainfo->image = image;
9069 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9070 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9071 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9072 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9073 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9074 mtoken |= MONO_TOKEN_METHOD_DEF;
9076 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9077 mtoken |= MONO_TOKEN_MEMBER_REF;
9080 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9083 attr = &ainfo->attrs [i - 1];
9084 attr->ctor = mono_get_method (image, mtoken, NULL);
9086 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9092 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9093 /*FIXME raising an exception here doesn't make any sense*/
9094 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9099 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9100 attr->data_size = mono_metadata_decode_value (data, &data);
9101 attr->data = (guchar*)data;
9109 mono_custom_attrs_from_method (MonoMethod *method)
9114 * An instantiated method has the same cattrs as the generic method definition.
9116 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9117 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9119 if (method->is_inflated)
9120 method = ((MonoMethodInflated *) method)->declaring;
9122 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9123 return lookup_custom_attr (method->klass->image, method);
9126 /* Synthetic methods */
9129 idx = mono_method_get_index (method);
9130 idx <<= MONO_CUSTOM_ATTR_BITS;
9131 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9132 return mono_custom_attrs_from_index (method->klass->image, idx);
9136 mono_custom_attrs_from_class (MonoClass *klass)
9140 if (klass->generic_class)
9141 klass = klass->generic_class->container_class;
9143 if (image_is_dynamic (klass->image))
9144 return lookup_custom_attr (klass->image, klass);
9146 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9147 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9148 idx <<= MONO_CUSTOM_ATTR_BITS;
9149 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9151 idx = mono_metadata_token_index (klass->type_token);
9152 idx <<= MONO_CUSTOM_ATTR_BITS;
9153 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9155 return mono_custom_attrs_from_index (klass->image, idx);
9159 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9163 if (image_is_dynamic (assembly->image))
9164 return lookup_custom_attr (assembly->image, assembly);
9165 idx = 1; /* there is only one assembly */
9166 idx <<= MONO_CUSTOM_ATTR_BITS;
9167 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9168 return mono_custom_attrs_from_index (assembly->image, idx);
9171 static MonoCustomAttrInfo*
9172 mono_custom_attrs_from_module (MonoImage *image)
9176 if (image_is_dynamic (image))
9177 return lookup_custom_attr (image, image);
9178 idx = 1; /* there is only one module */
9179 idx <<= MONO_CUSTOM_ATTR_BITS;
9180 idx |= MONO_CUSTOM_ATTR_MODULE;
9181 return mono_custom_attrs_from_index (image, idx);
9185 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9189 if (image_is_dynamic (klass->image)) {
9190 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9191 return lookup_custom_attr (klass->image, property);
9193 idx = find_property_index (klass, property);
9194 idx <<= MONO_CUSTOM_ATTR_BITS;
9195 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9196 return mono_custom_attrs_from_index (klass->image, idx);
9200 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9204 if (image_is_dynamic (klass->image)) {
9205 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9206 return lookup_custom_attr (klass->image, event);
9208 idx = find_event_index (klass, event);
9209 idx <<= MONO_CUSTOM_ATTR_BITS;
9210 idx |= MONO_CUSTOM_ATTR_EVENT;
9211 return mono_custom_attrs_from_index (klass->image, idx);
9215 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9218 if (image_is_dynamic (klass->image)) {
9219 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9220 return lookup_custom_attr (klass->image, field);
9222 idx = find_field_index (klass, field);
9223 idx <<= MONO_CUSTOM_ATTR_BITS;
9224 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9225 return mono_custom_attrs_from_index (klass->image, idx);
9229 * mono_custom_attrs_from_param:
9230 * @method: handle to the method that we want to retrieve custom parameter information from
9231 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9233 * The result must be released with mono_custom_attrs_free().
9235 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9238 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9241 guint32 i, idx, method_index;
9242 guint32 param_list, param_last, param_pos, found;
9244 MonoReflectionMethodAux *aux;
9247 * An instantiated method has the same cattrs as the generic method definition.
9249 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9250 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9252 if (method->is_inflated)
9253 method = ((MonoMethodInflated *) method)->declaring;
9255 if (image_is_dynamic (method->klass->image)) {
9256 MonoCustomAttrInfo *res, *ainfo;
9259 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9260 if (!aux || !aux->param_cattr)
9263 /* Need to copy since it will be freed later */
9264 ainfo = aux->param_cattr [param];
9267 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9268 res = g_malloc0 (size);
9269 memcpy (res, ainfo, size);
9273 image = method->klass->image;
9274 method_index = mono_method_get_index (method);
9277 ca = &image->tables [MONO_TABLE_METHOD];
9279 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9280 if (method_index == ca->rows) {
9281 ca = &image->tables [MONO_TABLE_PARAM];
9282 param_last = ca->rows + 1;
9284 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9285 ca = &image->tables [MONO_TABLE_PARAM];
9288 for (i = param_list; i < param_last; ++i) {
9289 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9290 if (param_pos == param) {
9298 idx <<= MONO_CUSTOM_ATTR_BITS;
9299 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9300 return mono_custom_attrs_from_index (image, idx);
9304 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9308 for (i = 0; i < ainfo->num_attrs; ++i) {
9309 klass = ainfo->attrs [i].ctor->klass;
9310 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9317 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9320 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9321 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9326 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9332 mono_error_init (error);
9335 for (i = 0; i < ainfo->num_attrs; ++i) {
9336 klass = ainfo->attrs [i].ctor->klass;
9337 if (mono_class_has_parent (klass, attr_klass)) {
9342 if (attr_index == -1)
9345 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9346 if (!mono_error_ok (error))
9348 return mono_array_get (attrs, MonoObject*, attr_index);
9352 * mono_reflection_get_custom_attrs_info:
9353 * @obj: a reflection object handle
9355 * Return the custom attribute info for attributes defined for the
9356 * reflection handle @obj. The objects.
9358 * FIXME this function leaks like a sieve for SRE objects.
9361 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9364 MonoCustomAttrInfo *cinfo = NULL;
9366 klass = obj->vtable->klass;
9367 if (klass == mono_defaults.monotype_class) {
9368 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9369 klass = mono_class_from_mono_type (type);
9370 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9371 cinfo = mono_custom_attrs_from_class (klass);
9372 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9373 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9374 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9375 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9376 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9377 cinfo = mono_custom_attrs_from_module (module->image);
9378 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9379 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9380 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9381 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9382 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9383 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9384 } else if (strcmp ("MonoField", klass->name) == 0) {
9385 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9386 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9387 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9388 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9389 cinfo = mono_custom_attrs_from_method (rmethod->method);
9390 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9391 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9392 cinfo = mono_custom_attrs_from_method (rmethod->method);
9393 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9394 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9395 MonoClass *member_class = mono_object_class (param->MemberImpl);
9396 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9397 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9398 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9399 } else if (is_sr_mono_property (member_class)) {
9400 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9402 if (!(method = prop->property->get))
9403 method = prop->property->set;
9406 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9408 #ifndef DISABLE_REFLECTION_EMIT
9409 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9410 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9411 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9412 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9413 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9414 MonoMethod *method = NULL;
9415 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9416 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9417 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9418 method = ((MonoReflectionMethod *)c->cb)->method;
9420 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));
9422 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9426 char *type_name = mono_type_get_full_name (member_class);
9427 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9428 MonoException *ex = mono_get_exception_not_supported (msg);
9431 mono_raise_exception (ex);
9433 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9434 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9435 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9436 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9437 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9438 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9439 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9440 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9441 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9442 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9443 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9444 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9445 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9446 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9447 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9448 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9449 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9450 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9451 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9452 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9453 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9454 } else { /* handle other types here... */
9455 g_error ("get custom attrs not yet supported for %s", klass->name);
9462 * mono_reflection_get_custom_attrs_by_type:
9463 * @obj: a reflection object handle
9465 * Return an array with all the custom attributes defined of the
9466 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9467 * of that type are returned. The objects are fully build. Return NULL if a loading error
9471 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9474 MonoCustomAttrInfo *cinfo;
9476 mono_error_init (error);
9478 cinfo = mono_reflection_get_custom_attrs_info (obj);
9480 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9482 mono_custom_attrs_free (cinfo);
9484 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9485 if (mono_loader_get_last_error ())
9487 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9494 * mono_reflection_get_custom_attrs:
9495 * @obj: a reflection object handle
9497 * Return an array with all the custom attributes defined of the
9498 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9502 mono_reflection_get_custom_attrs (MonoObject *obj)
9506 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9510 * mono_reflection_get_custom_attrs_data:
9511 * @obj: a reflection obj handle
9513 * Returns an array of System.Reflection.CustomAttributeData,
9514 * which include information about attributes reflected on
9515 * types loaded using the Reflection Only methods
9518 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9521 MonoCustomAttrInfo *cinfo;
9523 cinfo = mono_reflection_get_custom_attrs_info (obj);
9525 result = mono_custom_attrs_data_construct (cinfo);
9527 mono_custom_attrs_free (cinfo);
9529 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9534 static MonoReflectionType*
9535 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9537 static MonoMethod *method_get_underlying_system_type = NULL;
9538 MonoMethod *usertype_method;
9540 if (!method_get_underlying_system_type)
9541 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9542 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9543 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9548 is_corlib_type (MonoClass *klass)
9550 return klass->image == mono_defaults.corlib;
9553 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9554 static MonoClass *cached_class; \
9556 return cached_class == _class; \
9557 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9558 cached_class = _class; \
9565 #ifndef DISABLE_REFLECTION_EMIT
9567 is_sre_array (MonoClass *klass)
9569 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9573 is_sre_byref (MonoClass *klass)
9575 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9579 is_sre_pointer (MonoClass *klass)
9581 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9585 is_sre_generic_instance (MonoClass *klass)
9587 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9591 is_sre_type_builder (MonoClass *klass)
9593 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9597 is_sre_method_builder (MonoClass *klass)
9599 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9603 is_sre_ctor_builder (MonoClass *klass)
9605 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9609 is_sre_field_builder (MonoClass *klass)
9611 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9615 is_sre_method_on_tb_inst (MonoClass *klass)
9617 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9621 is_sre_ctor_on_tb_inst (MonoClass *klass)
9623 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9627 mono_reflection_type_get_handle (MonoReflectionType* ref)
9635 if (is_usertype (ref)) {
9636 ref = mono_reflection_type_get_underlying_system_type (ref);
9637 if (ref == NULL || is_usertype (ref))
9643 klass = mono_object_class (ref);
9645 if (is_sre_array (klass)) {
9647 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9648 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9650 if (sre_array->rank == 0) //single dimentional array
9651 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9653 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9654 sre_array->type.type = res;
9656 } else if (is_sre_byref (klass)) {
9658 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9659 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9661 res = &mono_class_from_mono_type (base)->this_arg;
9662 sre_byref->type.type = res;
9664 } else if (is_sre_pointer (klass)) {
9666 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9667 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9669 res = &mono_ptr_class_get (base)->byval_arg;
9670 sre_pointer->type.type = res;
9672 } else if (is_sre_generic_instance (klass)) {
9673 MonoType *res, **types;
9674 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9677 count = mono_array_length (gclass->type_arguments);
9678 types = g_new0 (MonoType*, count);
9679 for (i = 0; i < count; ++i) {
9680 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9681 types [i] = mono_reflection_type_get_handle (t);
9688 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9691 gclass->type.type = res;
9695 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9702 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9704 mono_reflection_type_get_handle (type);
9708 mono_reflection_register_with_runtime (MonoReflectionType *type)
9710 MonoType *res = mono_reflection_type_get_handle (type);
9711 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9715 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9717 klass = mono_class_from_mono_type (res);
9719 mono_loader_lock (); /*same locking as mono_type_get_object*/
9720 mono_domain_lock (domain);
9722 if (!image_is_dynamic (klass->image)) {
9723 mono_class_setup_supertypes (klass);
9725 if (!domain->type_hash)
9726 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9727 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9728 mono_g_hash_table_insert (domain->type_hash, res, type);
9730 mono_domain_unlock (domain);
9731 mono_loader_unlock ();
9735 * LOCKING: Assumes the loader lock is held.
9737 static MonoMethodSignature*
9738 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9739 MonoMethodSignature *sig;
9742 count = parameters? mono_array_length (parameters): 0;
9744 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9745 sig->param_count = count;
9746 sig->sentinelpos = -1; /* FIXME */
9747 for (i = 0; i < count; ++i)
9748 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9753 * LOCKING: Assumes the loader lock is held.
9755 static MonoMethodSignature*
9756 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9757 MonoMethodSignature *sig;
9759 sig = parameters_to_signature (image, ctor->parameters);
9760 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9761 sig->ret = &mono_defaults.void_class->byval_arg;
9766 * LOCKING: Assumes the loader lock is held.
9768 static MonoMethodSignature*
9769 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9770 MonoMethodSignature *sig;
9772 sig = parameters_to_signature (image, method->parameters);
9773 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9774 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9775 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9779 static MonoMethodSignature*
9780 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9781 MonoMethodSignature *sig;
9783 sig = parameters_to_signature (NULL, method->parameters);
9784 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9785 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9786 sig->generic_param_count = 0;
9791 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9793 MonoClass *klass = mono_object_class (prop);
9794 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9795 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9796 *name = mono_string_to_utf8 (pb->name);
9797 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9799 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9800 *name = g_strdup (p->property->name);
9801 if (p->property->get)
9802 *type = mono_method_signature (p->property->get)->ret;
9804 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9809 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9811 MonoClass *klass = mono_object_class (field);
9812 if (strcmp (klass->name, "FieldBuilder") == 0) {
9813 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9814 *name = mono_string_to_utf8 (fb->name);
9815 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9817 MonoReflectionField *f = (MonoReflectionField *)field;
9818 *name = g_strdup (mono_field_get_name (f->field));
9819 *type = f->field->type;
9823 #else /* DISABLE_REFLECTION_EMIT */
9826 mono_reflection_register_with_runtime (MonoReflectionType *type)
9832 is_sre_type_builder (MonoClass *klass)
9838 is_sre_generic_instance (MonoClass *klass)
9844 init_type_builder_generics (MonoObject *type)
9848 #endif /* !DISABLE_REFLECTION_EMIT */
9852 is_sr_mono_field (MonoClass *klass)
9854 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9858 is_sr_mono_property (MonoClass *klass)
9860 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9864 is_sr_mono_method (MonoClass *klass)
9866 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9870 is_sr_mono_cmethod (MonoClass *klass)
9872 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9876 is_sr_mono_generic_method (MonoClass *klass)
9878 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9882 is_sr_mono_generic_cmethod (MonoClass *klass)
9884 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9888 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9890 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9894 is_usertype (MonoReflectionType *ref)
9896 MonoClass *klass = mono_object_class (ref);
9897 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9900 static MonoReflectionType*
9901 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9903 if (!type || type->type)
9906 if (is_usertype (type)) {
9907 type = mono_reflection_type_get_underlying_system_type (type);
9908 if (is_usertype (type))
9909 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9915 * Encode a value in a custom attribute stream of bytes.
9916 * The value to encode is either supplied as an object in argument val
9917 * (valuetypes are boxed), or as a pointer to the data in the
9919 * @type represents the type of the value
9920 * @buffer is the start of the buffer
9921 * @p the current position in the buffer
9922 * @buflen contains the size of the buffer and is used to return the new buffer size
9923 * if this needs to be realloced.
9924 * @retbuffer and @retp return the start and the position of the buffer
9927 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9929 MonoTypeEnum simple_type;
9931 if ((p-buffer) + 10 >= *buflen) {
9934 newbuf = g_realloc (buffer, *buflen);
9935 p = newbuf + (p-buffer);
9939 argval = ((char*)arg + sizeof (MonoObject));
9940 simple_type = type->type;
9942 switch (simple_type) {
9943 case MONO_TYPE_BOOLEAN:
9948 case MONO_TYPE_CHAR:
9951 swap_with_size (p, argval, 2, 1);
9957 swap_with_size (p, argval, 4, 1);
9961 swap_with_size (p, argval, 8, 1);
9966 swap_with_size (p, argval, 8, 1);
9969 case MONO_TYPE_VALUETYPE:
9970 if (type->data.klass->enumtype) {
9971 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9974 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9977 case MONO_TYPE_STRING: {
9984 str = mono_string_to_utf8 ((MonoString*)arg);
9985 slen = strlen (str);
9986 if ((p-buffer) + 10 + slen >= *buflen) {
9990 newbuf = g_realloc (buffer, *buflen);
9991 p = newbuf + (p-buffer);
9994 mono_metadata_encode_value (slen, p, &p);
9995 memcpy (p, str, slen);
10000 case MONO_TYPE_CLASS: {
10008 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10009 slen = strlen (str);
10010 if ((p-buffer) + 10 + slen >= *buflen) {
10014 newbuf = g_realloc (buffer, *buflen);
10015 p = newbuf + (p-buffer);
10018 mono_metadata_encode_value (slen, p, &p);
10019 memcpy (p, str, slen);
10024 case MONO_TYPE_SZARRAY: {
10026 MonoClass *eclass, *arg_eclass;
10029 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10032 len = mono_array_length ((MonoArray*)arg);
10034 *p++ = (len >> 8) & 0xff;
10035 *p++ = (len >> 16) & 0xff;
10036 *p++ = (len >> 24) & 0xff;
10038 *retbuffer = buffer;
10039 eclass = type->data.klass;
10040 arg_eclass = mono_object_class (arg)->element_class;
10043 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10044 eclass = mono_defaults.object_class;
10046 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10047 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10048 int elsize = mono_class_array_element_size (arg_eclass);
10049 for (i = 0; i < len; ++i) {
10050 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10053 } else if (eclass->valuetype && arg_eclass->valuetype) {
10054 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10055 int elsize = mono_class_array_element_size (eclass);
10056 for (i = 0; i < len; ++i) {
10057 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10061 for (i = 0; i < len; ++i) {
10062 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10067 case MONO_TYPE_OBJECT: {
10073 * The parameter type is 'object' but the type of the actual
10074 * argument is not. So we have to add type information to the blob
10075 * too. This is completely undocumented in the spec.
10079 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10084 klass = mono_object_class (arg);
10086 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10089 } else if (klass->enumtype) {
10091 } else if (klass == mono_defaults.string_class) {
10092 simple_type = MONO_TYPE_STRING;
10095 } else if (klass->rank == 1) {
10097 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10098 /* See Partition II, Appendix B3 */
10101 *p++ = klass->element_class->byval_arg.type;
10102 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10104 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10105 *p++ = simple_type = klass->byval_arg.type;
10108 g_error ("unhandled type in custom attr");
10110 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10111 slen = strlen (str);
10112 if ((p-buffer) + 10 + slen >= *buflen) {
10116 newbuf = g_realloc (buffer, *buflen);
10117 p = newbuf + (p-buffer);
10120 mono_metadata_encode_value (slen, p, &p);
10121 memcpy (p, str, slen);
10124 simple_type = mono_class_enum_basetype (klass)->type;
10128 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10131 *retbuffer = buffer;
10135 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10137 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10138 char *str = type_get_qualified_name (type, NULL);
10139 int slen = strlen (str);
10143 * This seems to be optional...
10146 mono_metadata_encode_value (slen, p, &p);
10147 memcpy (p, str, slen);
10150 } else if (type->type == MONO_TYPE_OBJECT) {
10152 } else if (type->type == MONO_TYPE_CLASS) {
10153 /* it should be a type: encode_cattr_value () has the check */
10156 mono_metadata_encode_value (type->type, p, &p);
10157 if (type->type == MONO_TYPE_SZARRAY)
10158 /* See the examples in Partition VI, Annex B */
10159 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10165 #ifndef DISABLE_REFLECTION_EMIT
10167 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10170 /* Preallocate a large enough buffer */
10171 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10172 char *str = type_get_qualified_name (type, NULL);
10173 len = strlen (str);
10175 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10176 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10177 len = strlen (str);
10182 len += strlen (name);
10184 if ((p-buffer) + 20 + len >= *buflen) {
10188 newbuf = g_realloc (buffer, *buflen);
10189 p = newbuf + (p-buffer);
10193 encode_field_or_prop_type (type, p, &p);
10195 len = strlen (name);
10196 mono_metadata_encode_value (len, p, &p);
10197 memcpy (p, name, len);
10199 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10201 *retbuffer = buffer;
10205 * mono_reflection_get_custom_attrs_blob:
10206 * @ctor: custom attribute constructor
10207 * @ctorArgs: arguments o the constructor
10213 * Creates the blob of data that needs to be saved in the metadata and that represents
10214 * the custom attributed described by @ctor, @ctorArgs etc.
10215 * Returns: a Byte array representing the blob of data.
10218 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10221 MonoMethodSignature *sig;
10226 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10227 /* sig is freed later so allocate it in the heap */
10228 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10230 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10233 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10235 p = buffer = g_malloc (buflen);
10236 /* write the prolog */
10239 for (i = 0; i < sig->param_count; ++i) {
10240 arg = mono_array_get (ctorArgs, MonoObject*, i);
10241 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10245 i += mono_array_length (properties);
10247 i += mono_array_length (fields);
10249 *p++ = (i >> 8) & 0xff;
10252 for (i = 0; i < mono_array_length (properties); ++i) {
10256 prop = mono_array_get (properties, gpointer, i);
10257 get_prop_name_and_type (prop, &pname, &ptype);
10258 *p++ = 0x54; /* PROPERTY signature */
10259 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10266 for (i = 0; i < mono_array_length (fields); ++i) {
10270 field = mono_array_get (fields, gpointer, i);
10271 get_field_name_and_type (field, &fname, &ftype);
10272 *p++ = 0x53; /* FIELD signature */
10273 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10278 g_assert (p - buffer <= buflen);
10279 buflen = p - buffer;
10280 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10281 p = mono_array_addr (result, char, 0);
10282 memcpy (p, buffer, buflen);
10284 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10290 * mono_reflection_setup_internal_class:
10291 * @tb: a TypeBuilder object
10293 * Creates a MonoClass that represents the TypeBuilder.
10294 * This is a trick that lets us simplify a lot of reflection code
10295 * (and will allow us to support Build and Run assemblies easier).
10298 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10301 MonoClass *klass, *parent;
10303 RESOLVE_TYPE (tb->parent);
10305 mono_loader_lock ();
10308 /* check so we can compile corlib correctly */
10309 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10310 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10311 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10313 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10319 /* the type has already being created: it means we just have to change the parent */
10320 if (tb->type.type) {
10321 klass = mono_class_from_mono_type (tb->type.type);
10322 klass->parent = NULL;
10323 /* fool mono_class_setup_parent */
10324 klass->supertypes = NULL;
10325 mono_class_setup_parent (klass, parent);
10326 mono_class_setup_mono_type (klass);
10327 mono_loader_unlock ();
10331 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10333 klass->image = &tb->module->dynamic_image->image;
10335 klass->inited = 1; /* we lie to the runtime */
10336 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10337 if (!mono_error_ok (&error))
10339 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10340 if (!mono_error_ok (&error))
10342 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10343 klass->flags = tb->attrs;
10345 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10347 klass->element_class = klass;
10349 if (mono_class_get_ref_info (klass) == NULL) {
10351 mono_class_set_ref_info (klass, tb);
10353 /* Put into cache so mono_class_get_checked () will find it.
10354 Skip nested types as those should not be available on the global scope. */
10355 if (!tb->nesting_type)
10356 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10359 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10360 by performing a mono_class_get which does the full resolution.
10362 Working around this semantics would require us to write a lot of code for no clear advantage.
10364 mono_image_append_class_to_reflection_info_set (klass);
10366 g_assert (mono_class_get_ref_info (klass) == tb);
10369 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10371 if (parent != NULL) {
10372 mono_class_setup_parent (klass, parent);
10373 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10374 const char *old_n = klass->name;
10375 /* trick to get relative numbering right when compiling corlib */
10376 klass->name = "BuildingObject";
10377 mono_class_setup_parent (klass, mono_defaults.object_class);
10378 klass->name = old_n;
10381 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10382 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10383 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10384 klass->instance_size = sizeof (MonoObject);
10385 klass->size_inited = 1;
10386 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10389 mono_class_setup_mono_type (klass);
10391 mono_class_setup_supertypes (klass);
10394 * FIXME: handle interfaces.
10397 tb->type.type = &klass->byval_arg;
10399 if (tb->nesting_type) {
10400 g_assert (tb->nesting_type->type);
10401 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10404 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10406 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10408 mono_loader_unlock ();
10412 mono_loader_unlock ();
10413 mono_error_raise_exception (&error);
10417 * mono_reflection_setup_generic_class:
10418 * @tb: a TypeBuilder object
10420 * Setup the generic class before adding the first generic parameter.
10423 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10428 * mono_reflection_create_generic_class:
10429 * @tb: a TypeBuilder object
10431 * Creates the generic class after all generic parameters have been added.
10434 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10439 klass = mono_class_from_mono_type (tb->type.type);
10441 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10443 if (klass->generic_container || (count == 0))
10446 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10448 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10450 klass->generic_container->owner.klass = klass;
10451 klass->generic_container->type_argc = count;
10452 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10454 klass->is_generic = 1;
10456 for (i = 0; i < count; i++) {
10457 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10458 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10459 klass->generic_container->type_params [i] = *param;
10460 /*Make sure we are a diferent type instance */
10461 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10462 klass->generic_container->type_params [i].info.pklass = NULL;
10463 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10465 g_assert (klass->generic_container->type_params [i].param.owner);
10468 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10472 * mono_reflection_create_internal_class:
10473 * @tb: a TypeBuilder object
10475 * Actually create the MonoClass that is associated with the TypeBuilder.
10478 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10482 klass = mono_class_from_mono_type (tb->type.type);
10484 mono_loader_lock ();
10485 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10486 MonoReflectionFieldBuilder *fb;
10488 MonoType *enum_basetype;
10490 g_assert (tb->fields != NULL);
10491 g_assert (mono_array_length (tb->fields) >= 1);
10493 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10495 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10496 mono_loader_unlock ();
10500 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10501 klass->element_class = mono_class_from_mono_type (enum_basetype);
10502 if (!klass->element_class)
10503 klass->element_class = mono_class_from_mono_type (enum_basetype);
10506 * get the element_class from the current corlib.
10508 ec = default_class_from_mono_type (enum_basetype);
10509 klass->instance_size = ec->instance_size;
10510 klass->size_inited = 1;
10512 * this is almost safe to do with enums and it's needed to be able
10513 * to create objects of the enum type (for use in SetConstant).
10515 /* FIXME: Does this mean enums can't have method overrides ? */
10516 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10518 mono_loader_unlock ();
10521 static MonoMarshalSpec*
10522 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10523 MonoReflectionMarshal *minfo)
10525 MonoMarshalSpec *res;
10527 res = image_g_new0 (image, MonoMarshalSpec, 1);
10528 res->native = minfo->type;
10530 switch (minfo->type) {
10531 case MONO_NATIVE_LPARRAY:
10532 res->data.array_data.elem_type = minfo->eltype;
10533 if (minfo->has_size) {
10534 res->data.array_data.param_num = minfo->param_num;
10535 res->data.array_data.num_elem = minfo->count;
10536 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10539 res->data.array_data.param_num = -1;
10540 res->data.array_data.num_elem = -1;
10541 res->data.array_data.elem_mult = -1;
10545 case MONO_NATIVE_BYVALTSTR:
10546 case MONO_NATIVE_BYVALARRAY:
10547 res->data.array_data.num_elem = minfo->count;
10550 case MONO_NATIVE_CUSTOM:
10551 if (minfo->marshaltyperef)
10552 res->data.custom_data.custom_name =
10553 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10554 if (minfo->mcookie)
10555 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10564 #endif /* !DISABLE_REFLECTION_EMIT */
10566 MonoReflectionMarshalAsAttribute*
10567 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10568 MonoMarshalSpec *spec)
10570 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10571 MonoReflectionMarshalAsAttribute *minfo;
10574 if (!System_Reflection_Emit_MarshalAsAttribute) {
10575 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10576 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10577 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10580 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10581 minfo->utype = spec->native;
10583 switch (minfo->utype) {
10584 case MONO_NATIVE_LPARRAY:
10585 minfo->array_subtype = spec->data.array_data.elem_type;
10586 minfo->size_const = spec->data.array_data.num_elem;
10587 if (spec->data.array_data.param_num != -1)
10588 minfo->size_param_index = spec->data.array_data.param_num;
10591 case MONO_NATIVE_BYVALTSTR:
10592 case MONO_NATIVE_BYVALARRAY:
10593 minfo->size_const = spec->data.array_data.num_elem;
10596 case MONO_NATIVE_CUSTOM:
10597 if (spec->data.custom_data.custom_name) {
10598 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10600 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10602 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10604 if (spec->data.custom_data.cookie)
10605 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10615 #ifndef DISABLE_REFLECTION_EMIT
10617 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10618 ReflectionMethodBuilder *rmb,
10619 MonoMethodSignature *sig)
10623 MonoMethodWrapper *wrapperm;
10624 MonoMarshalSpec **specs;
10625 MonoReflectionMethodAux *method_aux;
10630 mono_error_init (&error);
10632 * Methods created using a MethodBuilder should have their memory allocated
10633 * inside the image mempool, while dynamic methods should have their memory
10636 dynamic = rmb->refs != NULL;
10637 image = dynamic ? NULL : klass->image;
10640 g_assert (!klass->generic_class);
10642 mono_loader_lock ();
10644 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10645 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10646 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10648 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10650 wrapperm = (MonoMethodWrapper*)m;
10652 m->dynamic = dynamic;
10654 m->flags = rmb->attrs;
10655 m->iflags = rmb->iattrs;
10656 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10658 m->signature = sig;
10659 m->sre_method = TRUE;
10660 m->skip_visibility = rmb->skip_visibility;
10661 if (rmb->table_idx)
10662 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10664 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10665 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10666 m->string_ctor = 1;
10668 m->signature->pinvoke = 1;
10669 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10670 m->signature->pinvoke = 1;
10672 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10674 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10675 g_assert (mono_error_ok (&error));
10676 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10677 g_assert (mono_error_ok (&error));
10679 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10681 if (image_is_dynamic (klass->image))
10682 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10684 mono_loader_unlock ();
10687 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10688 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10689 MonoMethodHeader *header;
10691 gint32 max_stack, i;
10692 gint32 num_locals = 0;
10693 gint32 num_clauses = 0;
10697 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10698 code_size = rmb->ilgen->code_len;
10699 max_stack = rmb->ilgen->max_stack;
10700 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10701 if (rmb->ilgen->ex_handlers)
10702 num_clauses = method_count_clauses (rmb->ilgen);
10705 code = mono_array_addr (rmb->code, guint8, 0);
10706 code_size = mono_array_length (rmb->code);
10707 /* we probably need to run a verifier on the code... */
10717 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10718 header->code_size = code_size;
10719 header->code = image_g_malloc (image, code_size);
10720 memcpy ((char*)header->code, code, code_size);
10721 header->max_stack = max_stack;
10722 header->init_locals = rmb->init_locals;
10723 header->num_locals = num_locals;
10725 for (i = 0; i < num_locals; ++i) {
10726 MonoReflectionLocalBuilder *lb =
10727 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10729 header->locals [i] = image_g_new0 (image, MonoType, 1);
10730 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10733 header->num_clauses = num_clauses;
10735 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10736 rmb->ilgen, num_clauses);
10739 wrapperm->header = header;
10742 if (rmb->generic_params) {
10743 int count = mono_array_length (rmb->generic_params);
10744 MonoGenericContainer *container = rmb->generic_container;
10746 g_assert (container);
10748 container->type_argc = count;
10749 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10750 container->owner.method = m;
10751 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10753 m->is_generic = TRUE;
10754 mono_method_set_generic_container (m, container);
10756 for (i = 0; i < count; i++) {
10757 MonoReflectionGenericParam *gp =
10758 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10759 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10760 container->type_params [i] = *param;
10764 * The method signature might have pointers to generic parameters that belong to other methods.
10765 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10766 * generic parameters.
10768 for (i = 0; i < m->signature->param_count; ++i) {
10769 MonoType *t = m->signature->params [i];
10770 if (t->type == MONO_TYPE_MVAR) {
10771 MonoGenericParam *gparam = t->data.generic_param;
10772 if (gparam->num < count) {
10773 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10774 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10780 if (klass->generic_container) {
10781 container->parent = klass->generic_container;
10782 container->context.class_inst = klass->generic_container->context.class_inst;
10784 container->context.method_inst = mono_get_shared_generic_inst (container);
10788 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10792 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10794 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10795 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10796 for (i = 0; i < rmb->nrefs; ++i)
10797 data [i + 1] = rmb->refs [i];
10802 /* Parameter info */
10805 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10806 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10807 for (i = 0; i <= m->signature->param_count; ++i) {
10808 MonoReflectionParamBuilder *pb;
10809 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10810 if ((i > 0) && (pb->attrs)) {
10811 /* Make a copy since it might point to a shared type structure */
10812 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10813 m->signature->params [i - 1]->attrs = pb->attrs;
10816 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10817 MonoDynamicImage *assembly;
10818 guint32 idx, def_type, len;
10822 if (!method_aux->param_defaults) {
10823 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10824 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10826 assembly = (MonoDynamicImage*)klass->image;
10827 idx = encode_constant (assembly, pb->def_value, &def_type);
10828 /* Copy the data from the blob since it might get realloc-ed */
10829 p = assembly->blob.data + idx;
10830 len = mono_metadata_decode_blob_size (p, &p2);
10832 method_aux->param_defaults [i] = image_g_malloc (image, len);
10833 method_aux->param_default_types [i] = def_type;
10834 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10838 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10839 g_assert (mono_error_ok (&error));
10842 if (!method_aux->param_cattr)
10843 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10844 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10850 /* Parameter marshalling */
10853 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10854 MonoReflectionParamBuilder *pb;
10855 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10856 if (pb->marshal_info) {
10858 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10859 specs [pb->position] =
10860 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10864 if (specs != NULL) {
10866 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10867 method_aux->param_marshall = specs;
10870 if (image_is_dynamic (klass->image) && method_aux)
10871 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10873 mono_loader_unlock ();
10879 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10881 ReflectionMethodBuilder rmb;
10882 MonoMethodSignature *sig;
10884 mono_loader_lock ();
10885 sig = ctor_builder_to_signature (klass->image, mb);
10886 mono_loader_unlock ();
10888 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10890 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10891 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10893 /* If we are in a generic class, we might be called multiple times from inflate_method */
10894 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10895 /* ilgen is no longer needed */
10899 return mb->mhandle;
10903 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10905 ReflectionMethodBuilder rmb;
10906 MonoMethodSignature *sig;
10908 mono_loader_lock ();
10909 sig = method_builder_to_signature (klass->image, mb);
10910 mono_loader_unlock ();
10912 reflection_methodbuilder_from_method_builder (&rmb, mb);
10914 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10915 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10917 /* If we are in a generic class, we might be called multiple times from inflate_method */
10918 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10919 /* ilgen is no longer needed */
10922 return mb->mhandle;
10925 static MonoClassField*
10926 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10928 MonoClassField *field;
10932 field = g_new0 (MonoClassField, 1);
10934 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10935 g_assert (mono_error_ok (&error));
10936 if (fb->attrs || fb->modreq || fb->modopt) {
10937 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10938 field->type->attrs = fb->attrs;
10940 g_assert (image_is_dynamic (klass->image));
10941 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10942 g_free (field->type);
10943 field->type = mono_metadata_type_dup (klass->image, custom);
10946 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10948 if (fb->offset != -1)
10949 field->offset = fb->offset;
10950 field->parent = klass;
10951 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10953 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10960 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10963 MonoReflectionTypeBuilder *tb = NULL;
10964 gboolean is_dynamic = FALSE;
10965 MonoClass *geninst;
10967 mono_loader_lock ();
10969 if (is_sre_type_builder (mono_object_class (type))) {
10970 tb = (MonoReflectionTypeBuilder *) type;
10973 } else if (is_sre_generic_instance (mono_object_class (type))) {
10974 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10975 MonoReflectionType *gtd = rgi->generic_type;
10977 if (is_sre_type_builder (mono_object_class (gtd))) {
10978 tb = (MonoReflectionTypeBuilder *)gtd;
10983 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10984 if (tb && tb->generic_container)
10985 mono_reflection_create_generic_class (tb);
10987 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10988 if (!klass->generic_container) {
10989 mono_loader_unlock ();
10993 if (klass->wastypebuilder) {
10994 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10999 mono_loader_unlock ();
11001 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11003 return &geninst->byval_arg;
11007 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11009 MonoGenericClass *gclass;
11010 MonoGenericInst *inst;
11012 g_assert (klass->generic_container);
11014 inst = mono_metadata_get_generic_inst (type_argc, types);
11015 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11017 return mono_generic_class_get_class (gclass);
11020 MonoReflectionMethod*
11021 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11025 MonoMethod *method, *inflated;
11026 MonoMethodInflated *imethod;
11027 MonoGenericContext tmp_context;
11028 MonoGenericInst *ginst;
11029 MonoType **type_argv;
11032 /*FIXME but this no longer should happen*/
11033 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11034 #ifndef DISABLE_REFLECTION_EMIT
11035 MonoReflectionMethodBuilder *mb = NULL;
11036 MonoReflectionTypeBuilder *tb;
11039 mb = (MonoReflectionMethodBuilder *) rmethod;
11040 tb = (MonoReflectionTypeBuilder *) mb->type;
11041 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11043 method = methodbuilder_to_mono_method (klass, mb);
11045 g_assert_not_reached ();
11049 method = rmethod->method;
11052 klass = method->klass;
11054 if (method->is_inflated)
11055 method = ((MonoMethodInflated *) method)->declaring;
11057 count = mono_method_signature (method)->generic_param_count;
11058 if (count != mono_array_length (types))
11061 type_argv = g_new0 (MonoType *, count);
11062 for (i = 0; i < count; i++) {
11063 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
11064 type_argv [i] = mono_reflection_type_get_handle (garg);
11066 ginst = mono_metadata_get_generic_inst (count, type_argv);
11067 g_free (type_argv);
11069 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11070 tmp_context.method_inst = ginst;
11072 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11073 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11074 imethod = (MonoMethodInflated *) inflated;
11076 /*FIXME but I think this is no longer necessary*/
11077 if (image_is_dynamic (method->klass->image)) {
11078 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11080 * This table maps metadata structures representing inflated methods/fields
11081 * to the reflection objects representing their generic definitions.
11083 mono_image_lock ((MonoImage*)image);
11084 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11085 mono_image_unlock ((MonoImage*)image);
11088 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11089 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11091 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11094 #ifndef DISABLE_REFLECTION_EMIT
11096 static MonoMethod *
11097 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11099 MonoMethodInflated *imethod;
11100 MonoGenericContext *context;
11104 * With generic code sharing the klass might not be inflated.
11105 * This can happen because classes inflated with their own
11106 * type arguments are "normalized" to the uninflated class.
11108 if (!klass->generic_class)
11111 context = mono_class_get_context (klass);
11113 if (klass->method.count && klass->methods) {
11114 /* Find the already created inflated method */
11115 for (i = 0; i < klass->method.count; ++i) {
11116 g_assert (klass->methods [i]->is_inflated);
11117 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11120 g_assert (i < klass->method.count);
11121 imethod = (MonoMethodInflated*)klass->methods [i];
11124 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11125 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11128 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11129 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11131 mono_image_lock ((MonoImage*)image);
11132 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11133 mono_image_unlock ((MonoImage*)image);
11135 return (MonoMethod *) imethod;
11138 static MonoMethod *
11139 inflate_method (MonoReflectionType *type, MonoObject *obj)
11141 MonoMethod *method;
11144 MonoClass *type_class = mono_object_class (type);
11146 if (is_sre_generic_instance (type_class)) {
11147 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11148 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11149 } else if (is_sre_type_builder (type_class)) {
11150 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11151 } else if (type->type) {
11152 gklass = mono_class_from_mono_type (type->type);
11153 gklass = mono_class_get_generic_type_definition (gklass);
11155 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11158 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11159 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11160 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11162 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11163 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11164 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11165 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11166 method = ((MonoReflectionMethod *) obj)->method;
11168 method = NULL; /* prevent compiler warning */
11169 g_error ("can't handle type %s", obj->vtable->klass->name);
11172 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11175 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11177 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11179 MonoGenericClass *gclass;
11180 MonoDynamicGenericClass *dgclass;
11181 MonoClass *klass, *gklass;
11185 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11186 klass = mono_class_from_mono_type (gtype);
11187 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11188 gclass = gtype->data.generic_class;
11190 if (!gclass->is_dynamic)
11193 dgclass = (MonoDynamicGenericClass *) gclass;
11195 if (dgclass->initialized)
11198 gklass = gclass->container_class;
11199 mono_class_init (gklass);
11201 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11203 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11204 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11205 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11207 for (i = 0; i < dgclass->count_fields; i++) {
11208 MonoObject *obj = mono_array_get (fields, gpointer, i);
11209 MonoClassField *field, *inflated_field = NULL;
11211 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11212 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11213 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11214 field = ((MonoReflectionField *) obj)->field;
11216 field = NULL; /* prevent compiler warning */
11217 g_assert_not_reached ();
11220 dgclass->fields [i] = *field;
11221 dgclass->fields [i].parent = klass;
11222 dgclass->fields [i].type = mono_class_inflate_generic_type (
11223 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11224 dgclass->field_generic_types [i] = field->type;
11225 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11226 dgclass->field_objects [i] = obj;
11228 if (inflated_field) {
11229 g_free (inflated_field);
11231 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11235 dgclass->initialized = TRUE;
11239 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11241 MonoDynamicGenericClass *dgclass;
11244 g_assert (gclass->is_dynamic);
11246 dgclass = (MonoDynamicGenericClass *)gclass;
11248 for (i = 0; i < dgclass->count_fields; ++i) {
11249 MonoClassField *field = dgclass->fields + i;
11250 mono_metadata_free_type (field->type);
11251 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11256 fix_partial_generic_class (MonoClass *klass)
11258 MonoClass *gklass = klass->generic_class->container_class;
11259 MonoDynamicGenericClass *dgclass;
11262 if (klass->wastypebuilder)
11265 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11266 if (klass->parent != gklass->parent) {
11268 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11269 if (mono_error_ok (&error)) {
11270 MonoClass *parent = mono_class_from_mono_type (parent_type);
11271 mono_metadata_free_type (parent_type);
11272 if (parent != klass->parent) {
11273 /*fool mono_class_setup_parent*/
11274 klass->supertypes = NULL;
11275 mono_class_setup_parent (klass, parent);
11278 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11279 mono_error_cleanup (&error);
11280 if (gklass->wastypebuilder)
11281 klass->wastypebuilder = TRUE;
11286 if (!dgclass->initialized)
11289 if (klass->method.count != gklass->method.count) {
11290 klass->method.count = gklass->method.count;
11291 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11293 for (i = 0; i < klass->method.count; i++) {
11295 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11296 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11297 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11301 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11302 klass->interface_count = gklass->interface_count;
11303 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11304 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11306 for (i = 0; i < gklass->interface_count; ++i) {
11307 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11308 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11309 mono_metadata_free_type (iface_type);
11311 ensure_runtime_vtable (klass->interfaces [i]);
11313 klass->interfaces_inited = 1;
11316 if (klass->field.count != gklass->field.count) {
11317 klass->field.count = gklass->field.count;
11318 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11320 for (i = 0; i < klass->field.count; i++) {
11321 klass->fields [i] = gklass->fields [i];
11322 klass->fields [i].parent = klass;
11323 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11327 /*We can only finish with this klass once it's parent has as well*/
11328 if (gklass->wastypebuilder)
11329 klass->wastypebuilder = TRUE;
11334 ensure_generic_class_runtime_vtable (MonoClass *klass)
11336 MonoClass *gklass = klass->generic_class->container_class;
11338 ensure_runtime_vtable (gklass);
11340 fix_partial_generic_class (klass);
11344 ensure_runtime_vtable (MonoClass *klass)
11346 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11349 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11352 ensure_runtime_vtable (klass->parent);
11355 num = tb->ctors? mono_array_length (tb->ctors): 0;
11356 num += tb->num_methods;
11357 klass->method.count = num;
11358 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11359 num = tb->ctors? mono_array_length (tb->ctors): 0;
11360 for (i = 0; i < num; ++i)
11361 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11362 num = tb->num_methods;
11364 for (i = 0; i < num; ++i)
11365 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11367 if (tb->interfaces) {
11368 klass->interface_count = mono_array_length (tb->interfaces);
11369 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11370 for (i = 0; i < klass->interface_count; ++i) {
11371 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11372 klass->interfaces [i] = mono_class_from_mono_type (iface);
11373 ensure_runtime_vtable (klass->interfaces [i]);
11375 klass->interfaces_inited = 1;
11377 } else if (klass->generic_class){
11378 ensure_generic_class_runtime_vtable (klass);
11381 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11383 for (i = 0; i < klass->method.count; ++i) {
11384 MonoMethod *im = klass->methods [i];
11385 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11386 im->slot = slot_num++;
11389 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11390 mono_class_setup_interface_offsets (klass);
11391 mono_class_setup_interface_id (klass);
11395 * The generic vtable is needed even if image->run is not set since some
11396 * runtime code like ves_icall_Type_GetMethodsByName depends on
11397 * method->slot being defined.
11401 * tb->methods could not be freed since it is used for determining
11402 * overrides during dynamic vtable construction.
11407 mono_reflection_method_get_handle (MonoObject *method)
11409 MonoClass *klass = mono_object_class (method);
11410 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11411 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11412 return sr_method->method;
11414 if (is_sre_method_builder (klass)) {
11415 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11416 return mb->mhandle;
11418 if (is_sre_method_on_tb_inst (klass)) {
11419 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11420 MonoMethod *result;
11421 /*FIXME move this to a proper method and unify with resolve_object*/
11422 if (m->method_args) {
11423 result = mono_reflection_method_on_tb_inst_get_handle (m);
11425 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11426 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11427 MonoMethod *mono_method;
11429 if (is_sre_method_builder (mono_object_class (m->mb)))
11430 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11431 else if (is_sr_mono_method (mono_object_class (m->mb)))
11432 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11434 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)));
11436 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11441 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11446 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11448 MonoReflectionTypeBuilder *tb;
11450 MonoReflectionMethod *m;
11453 *num_overrides = 0;
11455 g_assert (image_is_dynamic (klass->image));
11457 if (!mono_class_get_ref_info (klass))
11460 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11462 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11466 for (i = 0; i < tb->num_methods; ++i) {
11467 MonoReflectionMethodBuilder *mb =
11468 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11469 if (mb->override_methods)
11470 onum += mono_array_length (mb->override_methods);
11475 *overrides = g_new0 (MonoMethod*, onum * 2);
11478 for (i = 0; i < tb->num_methods; ++i) {
11479 MonoReflectionMethodBuilder *mb =
11480 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11481 if (mb->override_methods) {
11482 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11483 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11485 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11486 (*overrides) [onum * 2 + 1] = mb->mhandle;
11488 g_assert (mb->mhandle);
11496 *num_overrides = onum;
11500 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11502 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11503 MonoReflectionFieldBuilder *fb;
11504 MonoClassField *field;
11505 MonoImage *image = klass->image;
11506 const char *p, *p2;
11508 guint32 len, idx, real_size = 0;
11510 klass->field.count = tb->num_fields;
11511 klass->field.first = 0;
11513 mono_error_init (error);
11515 if (tb->class_size) {
11516 if ((tb->packing_size & 0xffffff00) != 0) {
11517 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11518 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11521 klass->packing_size = tb->packing_size;
11522 real_size = klass->instance_size + tb->class_size;
11525 if (!klass->field.count) {
11526 klass->instance_size = MAX (klass->instance_size, real_size);
11530 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11531 mono_class_alloc_ext (klass);
11532 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11534 This is, guess what, a hack.
11535 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11536 On the static path no field class is resolved, only types are built. This is the right thing to do
11538 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11540 klass->size_inited = 1;
11542 for (i = 0; i < klass->field.count; ++i) {
11543 MonoArray *rva_data;
11544 fb = mono_array_get (tb->fields, gpointer, i);
11545 field = &klass->fields [i];
11546 field->name = mono_string_to_utf8_image (image, fb->name, error);
11547 if (!mono_error_ok (error))
11550 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11551 field->type->attrs = fb->attrs;
11553 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11556 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11557 char *base = mono_array_addr (rva_data, char, 0);
11558 size_t size = mono_array_length (rva_data);
11559 char *data = mono_image_alloc (klass->image, size);
11560 memcpy (data, base, size);
11561 klass->ext->field_def_values [i].data = data;
11563 if (fb->offset != -1)
11564 field->offset = fb->offset;
11565 field->parent = klass;
11566 fb->handle = field;
11567 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11569 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11570 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11572 if (fb->def_value) {
11573 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11574 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11575 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11576 /* Copy the data from the blob since it might get realloc-ed */
11577 p = assembly->blob.data + idx;
11578 len = mono_metadata_decode_blob_size (p, &p2);
11580 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11581 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11585 klass->instance_size = MAX (klass->instance_size, real_size);
11586 mono_class_layout_fields (klass);
11590 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11592 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11593 MonoReflectionPropertyBuilder *pb;
11594 MonoImage *image = klass->image;
11595 MonoProperty *properties;
11598 mono_error_init (error);
11601 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11603 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11604 klass->ext->property.first = 0;
11606 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11607 klass->ext->properties = properties;
11608 for (i = 0; i < klass->ext->property.count; ++i) {
11609 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11610 properties [i].parent = klass;
11611 properties [i].attrs = pb->attrs;
11612 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11613 if (!mono_error_ok (error))
11615 if (pb->get_method)
11616 properties [i].get = pb->get_method->mhandle;
11617 if (pb->set_method)
11618 properties [i].set = pb->set_method->mhandle;
11620 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11621 if (pb->def_value) {
11623 const char *p, *p2;
11624 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11625 if (!klass->ext->prop_def_values)
11626 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11627 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11628 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11629 /* Copy the data from the blob since it might get realloc-ed */
11630 p = assembly->blob.data + idx;
11631 len = mono_metadata_decode_blob_size (p, &p2);
11633 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11634 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11639 MonoReflectionEvent *
11640 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11642 MonoEvent *event = g_new0 (MonoEvent, 1);
11645 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11647 event->parent = klass;
11648 event->attrs = eb->attrs;
11649 event->name = mono_string_to_utf8 (eb->name);
11650 if (eb->add_method)
11651 event->add = eb->add_method->mhandle;
11652 if (eb->remove_method)
11653 event->remove = eb->remove_method->mhandle;
11654 if (eb->raise_method)
11655 event->raise = eb->raise_method->mhandle;
11657 #ifndef MONO_SMALL_CONFIG
11658 if (eb->other_methods) {
11660 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11661 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11662 MonoReflectionMethodBuilder *mb =
11663 mono_array_get (eb->other_methods,
11664 MonoReflectionMethodBuilder*, j);
11665 event->other [j] = mb->mhandle;
11670 return mono_event_get_object (mono_object_domain (tb), klass, event);
11674 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11676 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11677 MonoReflectionEventBuilder *eb;
11678 MonoImage *image = klass->image;
11682 mono_error_init (error);
11685 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11687 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11688 klass->ext->event.first = 0;
11690 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11691 klass->ext->events = events;
11692 for (i = 0; i < klass->ext->event.count; ++i) {
11693 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11694 events [i].parent = klass;
11695 events [i].attrs = eb->attrs;
11696 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11697 if (!mono_error_ok (error))
11699 if (eb->add_method)
11700 events [i].add = eb->add_method->mhandle;
11701 if (eb->remove_method)
11702 events [i].remove = eb->remove_method->mhandle;
11703 if (eb->raise_method)
11704 events [i].raise = eb->raise_method->mhandle;
11706 #ifndef MONO_SMALL_CONFIG
11707 if (eb->other_methods) {
11709 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11710 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11711 MonoReflectionMethodBuilder *mb =
11712 mono_array_get (eb->other_methods,
11713 MonoReflectionMethodBuilder*, j);
11714 events [i].other [j] = mb->mhandle;
11718 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11723 remove_instantiations_of_and_ensure_contents (gpointer key,
11725 gpointer user_data)
11727 MonoType *type = (MonoType*)key;
11728 MonoClass *klass = (MonoClass*)user_data;
11730 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11731 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11738 check_array_for_usertypes (MonoArray *arr)
11745 for (i = 0; i < mono_array_length (arr); ++i)
11746 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11749 MonoReflectionType*
11750 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11754 MonoDomain* domain;
11755 MonoReflectionType* res;
11758 domain = mono_object_domain (tb);
11759 klass = mono_class_from_mono_type (tb->type.type);
11762 * Check for user defined Type subclasses.
11764 RESOLVE_TYPE (tb->parent);
11765 check_array_for_usertypes (tb->interfaces);
11767 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11768 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11770 RESOLVE_TYPE (fb->type);
11771 check_array_for_usertypes (fb->modreq);
11772 check_array_for_usertypes (fb->modopt);
11773 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11774 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11779 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11780 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11782 RESOLVE_TYPE (mb->rtype);
11783 check_array_for_usertypes (mb->return_modreq);
11784 check_array_for_usertypes (mb->return_modopt);
11785 check_array_for_usertypes (mb->parameters);
11786 if (mb->param_modreq)
11787 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11788 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11789 if (mb->param_modopt)
11790 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11791 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11796 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11797 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11799 check_array_for_usertypes (mb->parameters);
11800 if (mb->param_modreq)
11801 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11802 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11803 if (mb->param_modopt)
11804 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11805 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11810 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11813 * we need to lock the domain because the lock will be taken inside
11814 * So, we need to keep the locking order correct.
11816 mono_loader_lock ();
11817 mono_domain_lock (domain);
11818 if (klass->wastypebuilder) {
11819 mono_domain_unlock (domain);
11820 mono_loader_unlock ();
11821 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11824 * Fields to set in klass:
11825 * the various flags: delegate/unicode/contextbound etc.
11827 klass->flags = tb->attrs;
11828 klass->has_cctor = 1;
11829 klass->has_finalize = 1;
11830 klass->has_finalize_inited = 1;
11832 mono_class_setup_parent (klass, klass->parent);
11833 /* fool mono_class_setup_supertypes */
11834 klass->supertypes = NULL;
11835 mono_class_setup_supertypes (klass);
11836 mono_class_setup_mono_type (klass);
11839 if (!((MonoDynamicImage*)klass->image)->run) {
11840 if (klass->generic_container) {
11841 /* FIXME: The code below can't handle generic classes */
11842 klass->wastypebuilder = TRUE;
11843 mono_loader_unlock ();
11844 mono_domain_unlock (domain);
11845 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11850 /* enums are done right away */
11851 if (!klass->enumtype)
11852 ensure_runtime_vtable (klass);
11854 if (tb->subtypes) {
11855 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11856 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11857 mono_class_alloc_ext (klass);
11858 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)));
11862 klass->nested_classes_inited = TRUE;
11864 /* fields and object layout */
11865 if (klass->parent) {
11866 if (!klass->parent->size_inited)
11867 mono_class_init (klass->parent);
11868 klass->instance_size = klass->parent->instance_size;
11869 klass->sizes.class_size = 0;
11870 klass->min_align = klass->parent->min_align;
11871 /* if the type has no fields we won't call the field_setup
11872 * routine which sets up klass->has_references.
11874 klass->has_references |= klass->parent->has_references;
11876 klass->instance_size = sizeof (MonoObject);
11877 klass->min_align = 1;
11880 /* FIXME: handle packing_size and instance_size */
11881 typebuilder_setup_fields (klass, &error);
11882 if (!mono_error_ok (&error))
11884 typebuilder_setup_properties (klass, &error);
11885 if (!mono_error_ok (&error))
11888 typebuilder_setup_events (klass, &error);
11889 if (!mono_error_ok (&error))
11892 klass->wastypebuilder = TRUE;
11895 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11896 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11897 * we want to return normal System.MonoType objects, so clear these out from the cache.
11899 * Together with this we must ensure the contents of all instances to match the created type.
11901 if (domain->type_hash && klass->generic_container)
11902 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11904 mono_domain_unlock (domain);
11905 mono_loader_unlock ();
11907 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11908 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11909 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11912 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11913 g_assert (res != (MonoReflectionType*)tb);
11918 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11919 klass->wastypebuilder = TRUE;
11920 mono_domain_unlock (domain);
11921 mono_loader_unlock ();
11922 mono_error_raise_exception (&error);
11927 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11929 MonoGenericParamFull *param;
11934 image = &gparam->tbuilder->module->dynamic_image->image;
11936 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11938 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11939 g_assert (mono_error_ok (&error));
11940 param->param.num = gparam->index;
11942 if (gparam->mbuilder) {
11943 if (!gparam->mbuilder->generic_container) {
11944 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11945 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11946 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11947 gparam->mbuilder->generic_container->is_method = TRUE;
11949 * Cannot set owner.method, since the MonoMethod is not created yet.
11950 * Set the image field instead, so type_in_image () works.
11952 gparam->mbuilder->generic_container->is_anonymous = TRUE;
11953 gparam->mbuilder->generic_container->owner.image = klass->image;
11955 param->param.owner = gparam->mbuilder->generic_container;
11956 } else if (gparam->tbuilder) {
11957 if (!gparam->tbuilder->generic_container) {
11958 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11959 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11960 gparam->tbuilder->generic_container->owner.klass = klass;
11962 param->param.owner = gparam->tbuilder->generic_container;
11965 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
11967 gparam->type.type = &pklass->byval_arg;
11969 mono_class_set_ref_info (pklass, gparam);
11970 mono_image_append_class_to_reflection_info_set (pklass);
11974 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11976 MonoReflectionModuleBuilder *module = sig->module;
11977 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11978 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11983 check_array_for_usertypes (sig->arguments);
11985 sigbuffer_init (&buf, 32);
11987 sigbuffer_add_value (&buf, 0x07);
11988 sigbuffer_add_value (&buf, na);
11989 if (assembly != NULL){
11990 for (i = 0; i < na; ++i) {
11991 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11992 encode_reflection_type (assembly, type, &buf);
11996 buflen = buf.p - buf.buf;
11997 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11998 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11999 sigbuffer_free (&buf);
12005 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12007 MonoDynamicImage *assembly = sig->module->dynamic_image;
12008 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12013 check_array_for_usertypes (sig->arguments);
12015 sigbuffer_init (&buf, 32);
12017 sigbuffer_add_value (&buf, 0x06);
12018 for (i = 0; i < na; ++i) {
12019 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12020 encode_reflection_type (assembly, type, &buf);
12023 buflen = buf.p - buf.buf;
12024 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12025 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12026 sigbuffer_free (&buf);
12032 MonoMethod *handle;
12033 MonoDomain *domain;
12034 } DynamicMethodReleaseData;
12037 * The runtime automatically clean up those after finalization.
12039 static MonoReferenceQueue *dynamic_method_queue;
12042 free_dynamic_method (void *dynamic_method)
12044 DynamicMethodReleaseData *data = dynamic_method;
12045 MonoDomain *domain = data->domain;
12046 MonoMethod *method = data->handle;
12049 mono_domain_lock (domain);
12050 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12051 g_hash_table_remove (domain->method_to_dyn_method, method);
12052 mono_domain_unlock (domain);
12053 g_assert (dis_link);
12054 mono_gchandle_free (dis_link);
12056 mono_runtime_free_method (domain, method);
12061 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12063 MonoReferenceQueue *queue;
12064 MonoMethod *handle;
12065 DynamicMethodReleaseData *release_data;
12066 ReflectionMethodBuilder rmb;
12067 MonoMethodSignature *sig;
12069 MonoDomain *domain;
12073 if (mono_runtime_is_shutting_down ())
12074 mono_raise_exception (mono_get_exception_invalid_operation (""));
12076 if (!(queue = dynamic_method_queue)) {
12077 mono_loader_lock ();
12078 if (!(queue = dynamic_method_queue))
12079 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12080 mono_loader_unlock ();
12083 sig = dynamic_method_to_signature (mb);
12085 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12088 * Resolve references.
12091 * Every second entry in the refs array is reserved for storing handle_class,
12092 * which is needed by the ldtoken implementation in the JIT.
12094 rmb.nrefs = mb->nrefs;
12095 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12096 for (i = 0; i < mb->nrefs; i += 2) {
12097 MonoClass *handle_class;
12099 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12101 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12102 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12104 * The referenced DynamicMethod should already be created by the managed
12105 * code, except in the case of circular references. In that case, we store
12106 * method in the refs array, and fix it up later when the referenced
12107 * DynamicMethod is created.
12109 if (method->mhandle) {
12110 ref = method->mhandle;
12112 /* FIXME: GC object stored in unmanaged memory */
12115 /* FIXME: GC object stored in unmanaged memory */
12116 method->referenced_by = g_slist_append (method->referenced_by, mb);
12118 handle_class = mono_defaults.methodhandle_class;
12120 MonoException *ex = NULL;
12121 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12123 ex = mono_get_exception_type_load (NULL, NULL);
12124 else if (mono_security_core_clr_enabled ())
12125 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12129 mono_raise_exception (ex);
12134 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12135 rmb.refs [i + 1] = handle_class;
12138 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12140 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12141 release_data = g_new (DynamicMethodReleaseData, 1);
12142 release_data->handle = handle;
12143 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12144 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12145 g_free (release_data);
12147 /* Fix up refs entries pointing at us */
12148 for (l = mb->referenced_by; l; l = l->next) {
12149 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12150 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12153 g_assert (method->mhandle);
12155 data = (gpointer*)wrapper->method_data;
12156 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12157 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12158 data [i + 1] = mb->mhandle;
12161 g_slist_free (mb->referenced_by);
12165 /* ilgen is no longer needed */
12168 domain = mono_domain_get ();
12169 mono_domain_lock (domain);
12170 if (!domain->method_to_dyn_method)
12171 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12172 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12173 mono_domain_unlock (domain);
12176 #endif /* DISABLE_REFLECTION_EMIT */
12180 * mono_reflection_is_valid_dynamic_token:
12182 * Returns TRUE if token is valid.
12186 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12188 return lookup_dyn_token (image, token) != NULL;
12191 MonoMethodSignature *
12192 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12194 MonoMethodSignature *sig;
12195 g_assert (image_is_dynamic (image));
12197 mono_error_init (error);
12199 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12203 return mono_method_signature_checked (method, error);
12206 #ifndef DISABLE_REFLECTION_EMIT
12209 * mono_reflection_lookup_dynamic_token:
12211 * Finish the Builder object pointed to by TOKEN and return the corresponding
12212 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12213 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12216 * LOCKING: Take the loader lock
12219 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12221 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12225 obj = lookup_dyn_token (assembly, token);
12228 g_error ("Could not find required dynamic token 0x%08x", token);
12234 handle_class = &klass;
12235 return resolve_object (image, obj, handle_class, context);
12239 * ensure_complete_type:
12241 * Ensure that KLASS is completed if it is a dynamic type, or references
12245 ensure_complete_type (MonoClass *klass)
12247 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12248 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12250 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12252 // Asserting here could break a lot of code
12253 //g_assert (klass->wastypebuilder);
12256 if (klass->generic_class) {
12257 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12260 for (i = 0; i < inst->type_argc; ++i) {
12261 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12267 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12269 gpointer result = NULL;
12271 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12272 result = mono_string_intern ((MonoString*)obj);
12273 *handle_class = mono_defaults.string_class;
12275 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12276 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12277 MonoClass *mc = mono_class_from_mono_type (type);
12278 if (!mono_class_init (mc))
12279 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12282 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12283 result = mono_class_from_mono_type (inflated);
12284 mono_metadata_free_type (inflated);
12286 result = mono_class_from_mono_type (type);
12288 *handle_class = mono_defaults.typehandle_class;
12290 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12291 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12292 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12293 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12294 result = ((MonoReflectionMethod*)obj)->method;
12297 result = mono_class_inflate_generic_method_checked (result, context, &error);
12298 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12300 *handle_class = mono_defaults.methodhandle_class;
12302 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12303 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12304 result = mb->mhandle;
12306 /* Type is not yet created */
12307 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12309 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12312 * Hopefully this has been filled in by calling CreateType() on the
12316 * TODO: This won't work if the application finishes another
12317 * TypeBuilder instance instead of this one.
12319 result = mb->mhandle;
12323 result = mono_class_inflate_generic_method_checked (result, context, &error);
12324 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12326 *handle_class = mono_defaults.methodhandle_class;
12327 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12328 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12330 result = cb->mhandle;
12332 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12334 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12335 result = cb->mhandle;
12339 result = mono_class_inflate_generic_method_checked (result, context, &error);
12340 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12342 *handle_class = mono_defaults.methodhandle_class;
12343 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12344 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12346 ensure_complete_type (field->parent);
12348 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12349 MonoClass *klass = mono_class_from_mono_type (inflated);
12350 MonoClassField *inflated_field;
12351 gpointer iter = NULL;
12352 mono_metadata_free_type (inflated);
12353 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12354 if (!strcmp (field->name, inflated_field->name))
12357 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12358 result = inflated_field;
12362 *handle_class = mono_defaults.fieldhandle_class;
12364 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12365 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12366 result = fb->handle;
12369 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12371 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12372 result = fb->handle;
12375 if (fb->handle && fb->handle->parent->generic_container) {
12376 MonoClass *klass = fb->handle->parent;
12377 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12378 MonoClass *inflated = mono_class_from_mono_type (type);
12380 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12382 mono_metadata_free_type (type);
12384 *handle_class = mono_defaults.fieldhandle_class;
12385 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12386 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12387 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12390 klass = type->data.klass;
12391 if (klass->wastypebuilder) {
12392 /* Already created */
12396 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12397 result = type->data.klass;
12400 *handle_class = mono_defaults.typehandle_class;
12401 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12402 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12403 MonoMethodSignature *sig;
12406 if (helper->arguments)
12407 nargs = mono_array_length (helper->arguments);
12411 sig = mono_metadata_signature_alloc (image, nargs);
12412 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12413 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12415 if (helper->unmanaged_call_conv) { /* unmanaged */
12416 sig->call_convention = helper->unmanaged_call_conv - 1;
12417 sig->pinvoke = TRUE;
12418 } else if (helper->call_conv & 0x02) {
12419 sig->call_convention = MONO_CALL_VARARG;
12421 sig->call_convention = MONO_CALL_DEFAULT;
12424 sig->param_count = nargs;
12425 /* TODO: Copy type ? */
12426 sig->ret = helper->return_type->type;
12427 for (i = 0; i < nargs; ++i)
12428 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12431 *handle_class = NULL;
12432 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12433 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12434 /* Already created by the managed code */
12435 g_assert (method->mhandle);
12436 result = method->mhandle;
12437 *handle_class = mono_defaults.methodhandle_class;
12438 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12439 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12440 type = mono_class_inflate_generic_type (type, context);
12441 result = mono_class_from_mono_type (type);
12442 *handle_class = mono_defaults.typehandle_class;
12444 mono_metadata_free_type (type);
12445 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12446 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12447 type = mono_class_inflate_generic_type (type, context);
12448 result = mono_class_from_mono_type (type);
12449 *handle_class = mono_defaults.typehandle_class;
12451 mono_metadata_free_type (type);
12452 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12453 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12454 MonoClass *inflated;
12456 MonoClassField *field;
12458 if (is_sre_field_builder (mono_object_class (f->fb)))
12459 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12460 else if (is_sr_mono_field (mono_object_class (f->fb)))
12461 field = ((MonoReflectionField*)f->fb)->field;
12463 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)));
12465 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12466 inflated = mono_class_from_mono_type (type);
12468 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12469 ensure_complete_type (field->parent);
12471 mono_metadata_free_type (type);
12472 *handle_class = mono_defaults.fieldhandle_class;
12473 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12474 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12475 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12476 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12477 MonoMethod *method;
12479 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12480 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12481 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12482 method = ((MonoReflectionMethod *)c->cb)->method;
12484 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)));
12486 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12487 *handle_class = mono_defaults.methodhandle_class;
12488 mono_metadata_free_type (type);
12489 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12490 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12491 if (m->method_args) {
12492 result = mono_reflection_method_on_tb_inst_get_handle (m);
12495 result = mono_class_inflate_generic_method_checked (result, context, &error);
12496 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12499 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12500 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12501 MonoMethod *method;
12503 if (is_sre_method_builder (mono_object_class (m->mb)))
12504 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12505 else if (is_sr_mono_method (mono_object_class (m->mb)))
12506 method = ((MonoReflectionMethod *)m->mb)->method;
12508 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)));
12510 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12511 mono_metadata_free_type (type);
12513 *handle_class = mono_defaults.methodhandle_class;
12514 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12515 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12518 MonoMethod *method;
12522 mtype = mono_reflection_type_get_handle (m->parent);
12523 klass = mono_class_from_mono_type (mtype);
12525 /* Find the method */
12527 name = mono_string_to_utf8 (m->name);
12529 while ((method = mono_class_get_methods (klass, &iter))) {
12530 if (!strcmp (method->name, name))
12537 // FIXME: Check parameters/return value etc. match
12540 *handle_class = mono_defaults.methodhandle_class;
12541 } else if (is_sre_array (mono_object_get_class(obj)) ||
12542 is_sre_byref (mono_object_get_class(obj)) ||
12543 is_sre_pointer (mono_object_get_class(obj))) {
12544 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12545 MonoType *type = mono_reflection_type_get_handle (ref_type);
12548 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12549 result = mono_class_from_mono_type (inflated);
12550 mono_metadata_free_type (inflated);
12552 result = mono_class_from_mono_type (type);
12554 *handle_class = mono_defaults.typehandle_class;
12556 g_print ("%s\n", obj->vtable->klass->name);
12557 g_assert_not_reached ();
12562 #else /* DISABLE_REFLECTION_EMIT */
12565 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12567 g_assert_not_reached ();
12572 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12574 g_assert_not_reached ();
12578 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12580 g_assert_not_reached ();
12584 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12586 g_assert_not_reached ();
12590 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12592 g_assert_not_reached ();
12596 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12598 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12602 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12604 g_assert_not_reached ();
12608 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12610 g_assert_not_reached ();
12613 MonoReflectionModule *
12614 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12616 g_assert_not_reached ();
12621 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12623 g_assert_not_reached ();
12628 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12630 g_assert_not_reached ();
12635 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12636 gboolean create_open_instance, gboolean register_token)
12638 g_assert_not_reached ();
12643 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12648 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12650 g_assert_not_reached ();
12654 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12657 *num_overrides = 0;
12660 MonoReflectionEvent *
12661 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12663 g_assert_not_reached ();
12667 MonoReflectionType*
12668 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12670 g_assert_not_reached ();
12675 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12677 g_assert_not_reached ();
12681 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12683 g_assert_not_reached ();
12688 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12690 g_assert_not_reached ();
12695 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12700 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12706 mono_reflection_type_get_handle (MonoReflectionType* ref)
12714 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12716 g_assert_not_reached ();
12719 #endif /* DISABLE_REFLECTION_EMIT */
12721 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12722 const static guint32 declsec_flags_map[] = {
12723 0x00000000, /* empty */
12724 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12725 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12726 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12727 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12728 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12729 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12730 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12731 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12732 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12733 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12734 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12735 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12736 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12737 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12738 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12739 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12740 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12741 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12745 * Returns flags that includes all available security action associated to the handle.
12746 * @token: metadata token (either for a class or a method)
12747 * @image: image where resides the metadata.
12750 mono_declsec_get_flags (MonoImage *image, guint32 token)
12752 int index = mono_metadata_declsec_from_index (image, token);
12753 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12754 guint32 result = 0;
12758 /* HasSecurity can be present for other, not specially encoded, attributes,
12759 e.g. SuppressUnmanagedCodeSecurityAttribute */
12763 for (i = index; i < t->rows; i++) {
12764 guint32 cols [MONO_DECL_SECURITY_SIZE];
12766 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12767 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12770 action = cols [MONO_DECL_SECURITY_ACTION];
12771 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12772 result |= declsec_flags_map [action];
12774 g_assert_not_reached ();
12781 * Get the security actions (in the form of flags) associated with the specified method.
12783 * @method: The method for which we want the declarative security flags.
12784 * Return the declarative security flags for the method (only).
12786 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12787 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12790 mono_declsec_flags_from_method (MonoMethod *method)
12792 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12793 /* FIXME: No cache (for the moment) */
12794 guint32 idx = mono_method_get_index (method);
12795 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12796 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12797 return mono_declsec_get_flags (method->klass->image, idx);
12803 * Get the security actions (in the form of flags) associated with the specified class.
12805 * @klass: The class for which we want the declarative security flags.
12806 * Return the declarative security flags for the class.
12808 * Note: We cache the flags inside the MonoClass structure as this will get
12809 * called very often (at least for each method).
12812 mono_declsec_flags_from_class (MonoClass *klass)
12814 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12815 if (!klass->ext || !klass->ext->declsec_flags) {
12818 idx = mono_metadata_token_index (klass->type_token);
12819 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12820 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12821 mono_loader_lock ();
12822 mono_class_alloc_ext (klass);
12823 mono_loader_unlock ();
12824 /* we cache the flags on classes */
12825 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12827 return klass->ext->declsec_flags;
12833 * Get the security actions (in the form of flags) associated with the specified assembly.
12835 * @assembly: The assembly for which we want the declarative security flags.
12836 * Return the declarative security flags for the assembly.
12839 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12841 guint32 idx = 1; /* there is only one assembly */
12842 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12843 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12844 return mono_declsec_get_flags (assembly->image, idx);
12849 * Fill actions for the specific index (which may either be an encoded class token or
12850 * an encoded method token) from the metadata image.
12851 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12854 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12855 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12857 MonoBoolean result = FALSE;
12859 guint32 cols [MONO_DECL_SECURITY_SIZE];
12860 int index = mono_metadata_declsec_from_index (image, token);
12863 t = &image->tables [MONO_TABLE_DECLSECURITY];
12864 for (i = index; i < t->rows; i++) {
12865 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12867 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12870 /* if present only replace (class) permissions with method permissions */
12871 /* if empty accept either class or method permissions */
12872 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12873 if (!actions->demand.blob) {
12874 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12875 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12876 actions->demand.blob = (char*) (blob + 2);
12877 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12880 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12881 if (!actions->noncasdemand.blob) {
12882 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12883 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12884 actions->noncasdemand.blob = (char*) (blob + 2);
12885 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12888 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12889 if (!actions->demandchoice.blob) {
12890 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12891 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12892 actions->demandchoice.blob = (char*) (blob + 2);
12893 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12903 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12904 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12906 guint32 idx = mono_metadata_token_index (klass->type_token);
12907 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12908 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12909 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12913 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12914 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12916 guint32 idx = mono_method_get_index (method);
12917 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12918 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12919 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12923 * Collect all actions (that requires to generate code in mini) assigned for
12924 * the specified method.
12925 * Note: Don't use the content of actions if the function return FALSE.
12928 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12930 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12931 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12932 MonoBoolean result = FALSE;
12935 /* quick exit if no declarative security is present in the metadata */
12936 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12939 /* we want the original as the wrapper is "free" of the security informations */
12940 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12941 method = mono_marshal_method_from_wrapper (method);
12946 /* First we look for method-level attributes */
12947 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12948 mono_class_init (method->klass);
12949 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12951 result = mono_declsec_get_method_demands_params (method, demands,
12952 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12955 /* Here we use (or create) the class declarative cache to look for demands */
12956 flags = mono_declsec_flags_from_class (method->klass);
12957 if (flags & mask) {
12959 mono_class_init (method->klass);
12960 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12962 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12963 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12966 /* The boolean return value is used as a shortcut in case nothing needs to
12967 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12973 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12975 * Note: Don't use the content of actions if the function return FALSE.
12978 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12980 MonoBoolean result = FALSE;
12983 /* quick exit if no declarative security is present in the metadata */
12984 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12987 /* we want the original as the wrapper is "free" of the security informations */
12988 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12989 method = mono_marshal_method_from_wrapper (method);
12994 /* results are independant - zeroize both */
12995 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12996 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12998 /* First we look for method-level attributes */
12999 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13000 mono_class_init (method->klass);
13002 result = mono_declsec_get_method_demands_params (method, cmethod,
13003 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13006 /* Here we use (or create) the class declarative cache to look for demands */
13007 flags = mono_declsec_flags_from_class (method->klass);
13008 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13009 mono_class_init (method->klass);
13011 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13012 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13019 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13021 * @klass The inherited class - this is the class that provides the security check (attributes)
13023 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13025 * Note: Don't use the content of actions if the function return FALSE.
13028 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13030 MonoBoolean result = FALSE;
13033 /* quick exit if no declarative security is present in the metadata */
13034 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13037 /* Here we use (or create) the class declarative cache to look for demands */
13038 flags = mono_declsec_flags_from_class (klass);
13039 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13040 mono_class_init (klass);
13041 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13043 result |= mono_declsec_get_class_demands_params (klass, demands,
13044 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13051 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13053 * Note: Don't use the content of actions if the function return FALSE.
13056 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13058 /* quick exit if no declarative security is present in the metadata */
13059 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13062 /* we want the original as the wrapper is "free" of the security informations */
13063 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13064 method = mono_marshal_method_from_wrapper (method);
13069 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13070 mono_class_init (method->klass);
13071 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13073 return mono_declsec_get_method_demands_params (method, demands,
13074 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13081 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13083 guint32 cols [MONO_DECL_SECURITY_SIZE];
13087 int index = mono_metadata_declsec_from_index (image, token);
13091 t = &image->tables [MONO_TABLE_DECLSECURITY];
13092 for (i = index; i < t->rows; i++) {
13093 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13095 /* shortcut - index are ordered */
13096 if (token != cols [MONO_DECL_SECURITY_PARENT])
13099 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13100 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13101 entry->blob = (char*) (metadata + 2);
13102 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13111 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13113 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13114 guint32 idx = mono_method_get_index (method);
13115 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13116 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13117 return get_declsec_action (method->klass->image, idx, action, entry);
13123 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13126 guint32 flags = mono_declsec_flags_from_class (klass);
13127 if (declsec_flags_map [action] & flags) {
13128 guint32 idx = mono_metadata_token_index (klass->type_token);
13129 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13130 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13131 return get_declsec_action (klass->image, idx, action, entry);
13137 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13139 guint32 idx = 1; /* there is only one assembly */
13140 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13141 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13143 return get_declsec_action (assembly->image, idx, action, entry);
13147 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13149 MonoObject *res, *exc;
13151 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13152 static MonoMethod *method = NULL;
13154 if (!System_Reflection_Emit_TypeBuilder) {
13155 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13156 g_assert (System_Reflection_Emit_TypeBuilder);
13158 if (method == NULL) {
13159 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13164 * The result of mono_type_get_object () might be a System.MonoType but we
13165 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13167 g_assert (mono_class_get_ref_info (klass));
13168 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13170 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13172 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13176 return *(MonoBoolean*)mono_object_unbox (res);
13180 * mono_reflection_type_get_type:
13181 * @reftype: the System.Type object
13183 * Returns the MonoType* associated with the C# System.Type object @reftype.
13186 mono_reflection_type_get_type (MonoReflectionType *reftype)
13188 g_assert (reftype);
13190 return mono_reflection_type_get_handle (reftype);
13194 * mono_reflection_assembly_get_assembly:
13195 * @refassembly: the System.Reflection.Assembly object
13197 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13200 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13202 g_assert (refassembly);
13204 return refassembly->assembly;