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 = (MonoObject *)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_os_mutex_lock (&dynamic_images_mutex);
229 dynamic_images_unlock (void)
231 mono_os_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 = (MonoImage *)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)
264 mono_os_mutex_init (&dynamic_images_mutex);
268 dynamic_image_lock (MonoDynamicImage *image)
270 MONO_PREPARE_BLOCKING;
271 mono_image_lock ((MonoImage*)image);
272 MONO_FINISH_BLOCKING;
276 dynamic_image_unlock (MonoDynamicImage *image)
278 mono_image_unlock ((MonoImage*)image);
282 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
284 MONO_REQ_GC_UNSAFE_MODE;
286 dynamic_image_lock (assembly);
287 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
288 dynamic_image_unlock (assembly);
292 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
294 MONO_REQ_GC_UNSAFE_MODE;
298 dynamic_image_lock (assembly);
299 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
300 dynamic_image_unlock (assembly);
306 sigbuffer_init (SigBuffer *buf, int size)
308 MONO_REQ_GC_NEUTRAL_MODE;
310 buf->buf = (char *)g_malloc (size);
312 buf->end = buf->buf + size;
316 sigbuffer_make_room (SigBuffer *buf, int size)
318 MONO_REQ_GC_NEUTRAL_MODE;
320 if (buf->end - buf->p < size) {
321 int new_size = buf->end - buf->buf + size + 32;
322 char *p = (char *)g_realloc (buf->buf, new_size);
323 size = buf->p - buf->buf;
326 buf->end = buf->buf + new_size;
331 sigbuffer_add_value (SigBuffer *buf, guint32 val)
333 MONO_REQ_GC_NEUTRAL_MODE;
335 sigbuffer_make_room (buf, 6);
336 mono_metadata_encode_value (val, buf->p, &buf->p);
340 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 sigbuffer_make_room (buf, 1);
350 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
352 MONO_REQ_GC_NEUTRAL_MODE;
354 sigbuffer_make_room (buf, size);
355 memcpy (buf->p, p, size);
360 sigbuffer_free (SigBuffer *buf)
362 MONO_REQ_GC_NEUTRAL_MODE;
367 #ifndef DISABLE_REFLECTION_EMIT
371 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
375 image_g_malloc (MonoImage *image, guint size)
377 MONO_REQ_GC_NEUTRAL_MODE;
380 return mono_image_alloc (image, size);
382 return g_malloc (size);
384 #endif /* !DISABLE_REFLECTION_EMIT */
389 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
393 image_g_malloc0 (MonoImage *image, guint size)
395 MONO_REQ_GC_NEUTRAL_MODE;
398 return mono_image_alloc0 (image, size);
400 return g_malloc0 (size);
403 #ifndef DISABLE_REFLECTION_EMIT
405 image_strdup (MonoImage *image, const char *s)
407 MONO_REQ_GC_NEUTRAL_MODE;
410 return mono_image_strdup (image, s);
416 #define image_g_new(image,struct_type, n_structs) \
417 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
419 #define image_g_new0(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
424 alloc_table (MonoDynamicTable *table, guint nrows)
426 MONO_REQ_GC_NEUTRAL_MODE;
429 g_assert (table->columns);
430 if (nrows + 1 >= table->alloc_rows) {
431 while (nrows + 1 >= table->alloc_rows) {
432 if (table->alloc_rows == 0)
433 table->alloc_rows = 16;
435 table->alloc_rows *= 2;
438 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
443 make_room_in_stream (MonoDynamicStream *stream, int size)
445 MONO_REQ_GC_NEUTRAL_MODE;
447 if (size <= stream->alloc_size)
450 while (stream->alloc_size <= size) {
451 if (stream->alloc_size < 4096)
452 stream->alloc_size = 4096;
454 stream->alloc_size *= 2;
457 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
461 string_heap_insert (MonoDynamicStream *sh, const char *str)
463 MONO_REQ_GC_NEUTRAL_MODE;
467 gpointer oldkey, oldval;
469 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
470 return GPOINTER_TO_UINT (oldval);
472 len = strlen (str) + 1;
475 make_room_in_stream (sh, idx + len);
478 * We strdup the string even if we already copy them in sh->data
479 * so that the string pointers in the hash remain valid even if
480 * we need to realloc sh->data. We may want to avoid that later.
482 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
483 memcpy (sh->data + idx, str, len);
489 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
491 MONO_REQ_GC_UNSAFE_MODE;
493 char *name = mono_string_to_utf8 (str);
495 idx = string_heap_insert (sh, name);
500 #ifndef DISABLE_REFLECTION_EMIT
502 string_heap_init (MonoDynamicStream *sh)
504 MONO_REQ_GC_NEUTRAL_MODE;
507 sh->alloc_size = 4096;
508 sh->data = (char *)g_malloc (4096);
509 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
510 string_heap_insert (sh, "");
515 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
517 MONO_REQ_GC_NEUTRAL_MODE;
521 make_room_in_stream (stream, stream->index + len);
522 memcpy (stream->data + stream->index, data, len);
524 stream->index += len;
526 * align index? Not without adding an additional param that controls it since
527 * we may store a blob value in pieces.
533 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
535 MONO_REQ_GC_NEUTRAL_MODE;
539 make_room_in_stream (stream, stream->index + len);
540 memset (stream->data + stream->index, 0, len);
542 stream->index += len;
547 stream_data_align (MonoDynamicStream *stream)
549 MONO_REQ_GC_NEUTRAL_MODE;
552 guint32 count = stream->index % 4;
554 /* we assume the stream data will be aligned */
556 mono_image_add_stream_data (stream, buf, 4 - count);
559 #ifndef DISABLE_REFLECTION_EMIT
561 mono_blob_entry_hash (const char* str)
563 MONO_REQ_GC_NEUTRAL_MODE;
567 len = mono_metadata_decode_blob_size (str, &str);
571 for (str += 1; str < end; str++)
572 h = (h << 5) - h + *str;
580 mono_blob_entry_equal (const char *str1, const char *str2) {
581 MONO_REQ_GC_NEUTRAL_MODE;
586 len = mono_metadata_decode_blob_size (str1, &end1);
587 len2 = mono_metadata_decode_blob_size (str2, &end2);
590 return memcmp (end1, end2, len) == 0;
594 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
596 MONO_REQ_GC_NEUTRAL_MODE;
600 gpointer oldkey, oldval;
602 copy = (char *)g_malloc (s1+s2);
603 memcpy (copy, b1, s1);
604 memcpy (copy + s1, b2, s2);
605 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
607 idx = GPOINTER_TO_UINT (oldval);
609 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
610 mono_image_add_stream_data (&assembly->blob, b2, s2);
611 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
617 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
619 MONO_REQ_GC_NEUTRAL_MODE;
623 guint32 size = buf->p - buf->buf;
625 g_assert (size <= (buf->end - buf->buf));
626 mono_metadata_encode_value (size, b, &b);
627 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
631 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
632 * dest may be misaligned.
635 swap_with_size (char *dest, const char* val, int len, int nelem) {
636 MONO_REQ_GC_NEUTRAL_MODE;
637 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
640 for (elem = 0; elem < nelem; ++elem) {
666 g_assert_not_reached ();
672 memcpy (dest, val, len * nelem);
677 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
679 MONO_REQ_GC_UNSAFE_MODE;
683 guint32 idx = 0, len;
685 len = str->length * 2;
686 mono_metadata_encode_value (len, b, &b);
687 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
689 char *swapped = g_malloc (2 * mono_string_length (str));
690 const char *p = (const char*)mono_string_chars (str);
692 swap_with_size (swapped, p, 2, mono_string_length (str));
693 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
697 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
702 #ifndef DISABLE_REFLECTION_EMIT
704 default_class_from_mono_type (MonoType *type)
706 MONO_REQ_GC_NEUTRAL_MODE;
708 switch (type->type) {
709 case MONO_TYPE_OBJECT:
710 return mono_defaults.object_class;
712 return mono_defaults.void_class;
713 case MONO_TYPE_BOOLEAN:
714 return mono_defaults.boolean_class;
716 return mono_defaults.char_class;
718 return mono_defaults.sbyte_class;
720 return mono_defaults.byte_class;
722 return mono_defaults.int16_class;
724 return mono_defaults.uint16_class;
726 return mono_defaults.int32_class;
728 return mono_defaults.uint32_class;
730 return mono_defaults.int_class;
732 return mono_defaults.uint_class;
734 return mono_defaults.int64_class;
736 return mono_defaults.uint64_class;
738 return mono_defaults.single_class;
740 return mono_defaults.double_class;
741 case MONO_TYPE_STRING:
742 return mono_defaults.string_class;
744 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
745 g_assert_not_reached ();
753 * mono_class_get_ref_info:
755 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
758 mono_class_get_ref_info (MonoClass *klass)
760 MONO_REQ_GC_UNSAFE_MODE;
762 if (klass->ref_info_handle == 0)
765 return mono_gchandle_get_target (klass->ref_info_handle);
769 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
771 MONO_REQ_GC_UNSAFE_MODE;
773 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
774 g_assert (klass->ref_info_handle != 0);
778 mono_class_free_ref_info (MonoClass *klass)
780 MONO_REQ_GC_NEUTRAL_MODE;
782 if (klass->ref_info_handle) {
783 mono_gchandle_free (klass->ref_info_handle);
784 klass->ref_info_handle = 0;
789 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
791 MONO_REQ_GC_NEUTRAL_MODE;
794 MonoGenericInst *class_inst;
799 class_inst = gclass->context.class_inst;
801 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
802 klass = gclass->container_class;
803 sigbuffer_add_value (buf, klass->byval_arg.type);
804 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
806 sigbuffer_add_value (buf, class_inst->type_argc);
807 for (i = 0; i < class_inst->type_argc; ++i)
808 encode_type (assembly, class_inst->type_argv [i], buf);
813 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
815 MONO_REQ_GC_NEUTRAL_MODE;
818 g_assert_not_reached ();
823 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
827 case MONO_TYPE_BOOLEAN:
841 case MONO_TYPE_STRING:
842 case MONO_TYPE_OBJECT:
843 case MONO_TYPE_TYPEDBYREF:
844 sigbuffer_add_value (buf, type->type);
847 sigbuffer_add_value (buf, type->type);
848 encode_type (assembly, type->data.type, buf);
850 case MONO_TYPE_SZARRAY:
851 sigbuffer_add_value (buf, type->type);
852 encode_type (assembly, &type->data.klass->byval_arg, buf);
854 case MONO_TYPE_VALUETYPE:
855 case MONO_TYPE_CLASS: {
856 MonoClass *k = mono_class_from_mono_type (type);
858 if (k->generic_container) {
859 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
860 encode_generic_class (assembly, gclass, buf);
863 * Make sure we use the correct type.
865 sigbuffer_add_value (buf, k->byval_arg.type);
867 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
868 * otherwise two typerefs could point to the same type, leading to
869 * verification errors.
871 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
875 case MONO_TYPE_ARRAY:
876 sigbuffer_add_value (buf, type->type);
877 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
878 sigbuffer_add_value (buf, type->data.array->rank);
879 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
880 sigbuffer_add_value (buf, 0);
882 case MONO_TYPE_GENERICINST:
883 encode_generic_class (assembly, type->data.generic_class, buf);
887 sigbuffer_add_value (buf, type->type);
888 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
891 g_error ("need to encode type %x", type->type);
896 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
898 MONO_REQ_GC_UNSAFE_MODE;
901 sigbuffer_add_value (buf, MONO_TYPE_VOID);
905 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
909 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
911 MONO_REQ_GC_UNSAFE_MODE;
916 for (i = 0; i < mono_array_length (modreq); ++i) {
917 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
918 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
919 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
923 for (i = 0; i < mono_array_length (modopt); ++i) {
924 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
925 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
926 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
931 #ifndef DISABLE_REFLECTION_EMIT
933 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
935 MONO_REQ_GC_UNSAFE_MODE;
939 guint32 nparams = sig->param_count;
945 sigbuffer_init (&buf, 32);
947 * FIXME: vararg, explicit_this, differenc call_conv values...
949 idx = sig->call_convention;
951 idx |= 0x20; /* hasthis */
952 if (sig->generic_param_count)
953 idx |= 0x10; /* generic */
954 sigbuffer_add_byte (&buf, idx);
955 if (sig->generic_param_count)
956 sigbuffer_add_value (&buf, sig->generic_param_count);
957 sigbuffer_add_value (&buf, nparams);
958 encode_type (assembly, sig->ret, &buf);
959 for (i = 0; i < nparams; ++i) {
960 if (i == sig->sentinelpos)
961 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
962 encode_type (assembly, sig->params [i], &buf);
964 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
965 sigbuffer_free (&buf);
971 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
973 MONO_REQ_GC_UNSAFE_MODE;
976 * FIXME: reuse code from method_encode_signature().
980 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
981 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
982 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
985 sigbuffer_init (&buf, 32);
986 /* LAMESPEC: all the call conv spec is foobared */
987 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
988 if (mb->call_conv & 2)
989 idx |= 0x5; /* vararg */
990 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
991 idx |= 0x20; /* hasthis */
993 idx |= 0x10; /* generic */
994 sigbuffer_add_byte (&buf, idx);
996 sigbuffer_add_value (&buf, ngparams);
997 sigbuffer_add_value (&buf, nparams + notypes);
998 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
999 encode_reflection_type (assembly, mb->rtype, &buf);
1000 for (i = 0; i < nparams; ++i) {
1001 MonoArray *modreq = NULL;
1002 MonoArray *modopt = NULL;
1003 MonoReflectionType *pt;
1005 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1006 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1007 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1008 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1009 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1010 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1011 encode_reflection_type (assembly, pt, &buf);
1014 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1015 for (i = 0; i < notypes; ++i) {
1016 MonoReflectionType *pt;
1018 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1019 encode_reflection_type (assembly, pt, &buf);
1022 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1023 sigbuffer_free (&buf);
1028 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1030 MONO_REQ_GC_UNSAFE_MODE;
1032 MonoDynamicTable *table;
1034 guint32 idx, sig_idx;
1035 guint nl = mono_array_length (ilgen->locals);
1039 sigbuffer_init (&buf, 32);
1040 sigbuffer_add_value (&buf, 0x07);
1041 sigbuffer_add_value (&buf, nl);
1042 for (i = 0; i < nl; ++i) {
1043 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1046 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1048 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1050 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1051 sigbuffer_free (&buf);
1053 if (assembly->standalonesig_cache == NULL)
1054 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1055 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1059 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1060 idx = table->next_idx ++;
1062 alloc_table (table, table->rows);
1063 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1065 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1067 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1073 method_count_clauses (MonoReflectionILGen *ilgen)
1075 MONO_REQ_GC_UNSAFE_MODE;
1077 guint32 num_clauses = 0;
1080 MonoILExceptionInfo *ex_info;
1081 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1082 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1083 if (ex_info->handlers)
1084 num_clauses += mono_array_length (ex_info->handlers);
1092 #ifndef DISABLE_REFLECTION_EMIT
1093 static MonoExceptionClause*
1094 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1096 MONO_REQ_GC_UNSAFE_MODE;
1098 MonoExceptionClause *clauses;
1099 MonoExceptionClause *clause;
1100 MonoILExceptionInfo *ex_info;
1101 MonoILExceptionBlock *ex_block;
1102 guint32 finally_start;
1103 int i, j, clause_index;;
1105 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1108 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1109 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1110 finally_start = ex_info->start + ex_info->len;
1111 if (!ex_info->handlers)
1113 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1114 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1115 clause = &(clauses [clause_index]);
1117 clause->flags = ex_block->type;
1118 clause->try_offset = ex_info->start;
1120 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1121 clause->try_len = finally_start - ex_info->start;
1123 clause->try_len = ex_info->len;
1124 clause->handler_offset = ex_block->start;
1125 clause->handler_len = ex_block->len;
1126 if (ex_block->extype) {
1127 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1129 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1130 clause->data.filter_offset = ex_block->filter_offset;
1132 clause->data.filter_offset = 0;
1134 finally_start = ex_block->start + ex_block->len;
1142 #endif /* !DISABLE_REFLECTION_EMIT */
1145 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1147 MONO_REQ_GC_UNSAFE_MODE;
1152 gint32 max_stack, i;
1153 gint32 num_locals = 0;
1154 gint32 num_exception = 0;
1157 char fat_header [12];
1159 guint16 short_value;
1160 guint32 local_sig = 0;
1161 guint32 header_size = 12;
1164 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1165 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1169 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1171 code = mb->ilgen->code;
1172 code_size = mb->ilgen->code_len;
1173 max_stack = mb->ilgen->max_stack;
1174 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1175 if (mb->ilgen->ex_handlers)
1176 num_exception = method_count_clauses (mb->ilgen);
1180 char *name = mono_string_to_utf8 (mb->name);
1181 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1182 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1185 mono_raise_exception (exception);
1188 code_size = mono_array_length (code);
1189 max_stack = 8; /* we probably need to run a verifier on the code... */
1192 stream_data_align (&assembly->code);
1194 /* check for exceptions, maxstack, locals */
1195 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1197 if (code_size < 64 && !(code_size & 1)) {
1198 flags = (code_size << 2) | 0x2;
1199 } else if (code_size < 32 && (code_size & 1)) {
1200 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1204 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1205 /* add to the fixup todo list */
1206 if (mb->ilgen && mb->ilgen->num_token_fixups)
1207 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1208 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1209 return assembly->text_rva + idx;
1213 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1215 * FIXME: need to set also the header size in fat_flags.
1216 * (and more sects and init locals flags)
1220 fat_flags |= METHOD_HEADER_MORE_SECTS;
1221 if (mb->init_locals)
1222 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1223 fat_header [0] = fat_flags;
1224 fat_header [1] = (header_size / 4 ) << 4;
1225 short_value = GUINT16_TO_LE (max_stack);
1226 memcpy (fat_header + 2, &short_value, 2);
1227 int_value = GUINT32_TO_LE (code_size);
1228 memcpy (fat_header + 4, &int_value, 4);
1229 int_value = GUINT32_TO_LE (local_sig);
1230 memcpy (fat_header + 8, &int_value, 4);
1231 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1232 /* add to the fixup todo list */
1233 if (mb->ilgen && mb->ilgen->num_token_fixups)
1234 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1236 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1237 if (num_exception) {
1238 unsigned char sheader [4];
1239 MonoILExceptionInfo * ex_info;
1240 MonoILExceptionBlock * ex_block;
1243 stream_data_align (&assembly->code);
1244 /* always use fat format for now */
1245 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1246 num_exception *= 6 * sizeof (guint32);
1247 num_exception += 4; /* include the size of the header */
1248 sheader [1] = num_exception & 0xff;
1249 sheader [2] = (num_exception >> 8) & 0xff;
1250 sheader [3] = (num_exception >> 16) & 0xff;
1251 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1252 /* fat header, so we are already aligned */
1254 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1255 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1256 if (ex_info->handlers) {
1257 int finally_start = ex_info->start + ex_info->len;
1258 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1260 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1262 val = GUINT32_TO_LE (ex_block->type);
1263 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1265 val = GUINT32_TO_LE (ex_info->start);
1266 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1267 /* need fault, too, probably */
1268 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1269 val = GUINT32_TO_LE (finally_start - ex_info->start);
1271 val = GUINT32_TO_LE (ex_info->len);
1272 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1273 /* handler offset */
1274 val = GUINT32_TO_LE (ex_block->start);
1275 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1277 val = GUINT32_TO_LE (ex_block->len);
1278 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279 finally_start = ex_block->start + ex_block->len;
1280 if (ex_block->extype) {
1281 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1283 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1284 val = ex_block->filter_offset;
1288 val = GUINT32_TO_LE (val);
1289 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1290 /*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",
1291 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);*/
1294 g_error ("No clauses for ex info block %d", i);
1298 return assembly->text_rva + idx;
1302 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1304 MONO_REQ_GC_NEUTRAL_MODE;
1307 MonoDynamicTable *table;
1310 table = &assembly->tables [table_idx];
1312 g_assert (col < table->columns);
1314 values = table->values + table->columns;
1315 for (i = 1; i <= table->rows; ++i) {
1316 if (values [col] == token)
1318 values += table->columns;
1324 * LOCKING: Acquires the loader lock.
1326 static MonoCustomAttrInfo*
1327 lookup_custom_attr (MonoImage *image, gpointer member)
1329 MONO_REQ_GC_NEUTRAL_MODE;
1331 MonoCustomAttrInfo* res;
1333 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1338 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1344 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1346 MONO_REQ_GC_UNSAFE_MODE;
1348 /* FIXME: Need to do more checks */
1349 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1350 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1352 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1359 static MonoCustomAttrInfo*
1360 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1362 MONO_REQ_GC_UNSAFE_MODE;
1364 int i, index, count, not_visible;
1365 MonoCustomAttrInfo *ainfo;
1366 MonoReflectionCustomAttr *cattr;
1370 /* FIXME: check in assembly the Run flag is set */
1372 count = mono_array_length (cattrs);
1374 /* Skip nonpublic attributes since MS.NET seems to do the same */
1375 /* FIXME: This needs to be done more globally */
1377 for (i = 0; i < count; ++i) {
1378 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1379 if (!custom_attr_visible (image, cattr))
1382 count -= not_visible;
1384 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1386 ainfo->image = image;
1387 ainfo->num_attrs = count;
1388 ainfo->cached = alloc_img != NULL;
1390 for (i = 0; i < count; ++i) {
1391 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1392 if (custom_attr_visible (image, cattr)) {
1393 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1394 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1395 ainfo->attrs [index].ctor = cattr->ctor->method;
1396 ainfo->attrs [index].data = saved;
1397 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1405 #ifndef DISABLE_REFLECTION_EMIT
1407 * LOCKING: Acquires the loader lock.
1410 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1412 MONO_REQ_GC_UNSAFE_MODE;
1414 MonoCustomAttrInfo *ainfo, *tmp;
1416 if (!cattrs || !mono_array_length (cattrs))
1419 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1421 mono_loader_lock ();
1422 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1424 mono_custom_attrs_free (tmp);
1425 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1426 mono_loader_unlock ();
1432 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1434 MONO_REQ_GC_NEUTRAL_MODE;
1441 * idx is the table index of the object
1442 * type is one of MONO_CUSTOM_ATTR_*
1445 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1447 MONO_REQ_GC_UNSAFE_MODE;
1449 MonoDynamicTable *table;
1450 MonoReflectionCustomAttr *cattr;
1452 guint32 count, i, token;
1454 char *p = blob_size;
1456 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1459 count = mono_array_length (cattrs);
1460 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1461 table->rows += count;
1462 alloc_table (table, table->rows);
1463 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1464 idx <<= MONO_CUSTOM_ATTR_BITS;
1466 for (i = 0; i < count; ++i) {
1467 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1469 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1470 type = mono_metadata_token_index (token);
1471 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1472 switch (mono_metadata_token_table (token)) {
1473 case MONO_TABLE_METHOD:
1474 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1476 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1477 * method, not the one returned by mono_image_create_token ().
1479 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1481 case MONO_TABLE_MEMBERREF:
1482 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1485 g_warning ("got wrong token in custom attr");
1488 values [MONO_CUSTOM_ATTR_TYPE] = type;
1490 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1491 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1492 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1493 values += MONO_CUSTOM_ATTR_SIZE;
1499 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1501 MONO_REQ_GC_UNSAFE_MODE;
1503 MonoDynamicTable *table;
1505 guint32 count, i, idx;
1506 MonoReflectionPermissionSet *perm;
1511 count = mono_array_length (permissions);
1512 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1513 table->rows += count;
1514 alloc_table (table, table->rows);
1516 for (i = 0; i < mono_array_length (permissions); ++i) {
1517 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1519 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1521 idx = mono_metadata_token_index (parent_token);
1522 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1523 switch (mono_metadata_token_table (parent_token)) {
1524 case MONO_TABLE_TYPEDEF:
1525 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1527 case MONO_TABLE_METHOD:
1528 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1530 case MONO_TABLE_ASSEMBLY:
1531 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1534 g_assert_not_reached ();
1537 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1538 values [MONO_DECL_SECURITY_PARENT] = idx;
1539 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1546 * Fill in the MethodDef and ParamDef tables for a method.
1547 * This is used for both normal methods and constructors.
1550 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1552 MONO_REQ_GC_UNSAFE_MODE;
1554 MonoDynamicTable *table;
1558 /* room in this table is already allocated */
1559 table = &assembly->tables [MONO_TABLE_METHOD];
1560 *mb->table_idx = table->next_idx ++;
1561 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1562 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1563 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1564 values [MONO_METHOD_FLAGS] = mb->attrs;
1565 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1566 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1567 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1569 table = &assembly->tables [MONO_TABLE_PARAM];
1570 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1572 mono_image_add_decl_security (assembly,
1573 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1576 MonoDynamicTable *mtable;
1579 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1580 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1583 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1584 if (mono_array_get (mb->pinfo, gpointer, i))
1587 table->rows += count;
1588 alloc_table (table, table->rows);
1589 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1590 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1591 MonoReflectionParamBuilder *pb;
1592 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1593 values [MONO_PARAM_FLAGS] = pb->attrs;
1594 values [MONO_PARAM_SEQUENCE] = i;
1595 if (pb->name != NULL) {
1596 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1598 values [MONO_PARAM_NAME] = 0;
1600 values += MONO_PARAM_SIZE;
1601 if (pb->marshal_info) {
1603 alloc_table (mtable, mtable->rows);
1604 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1605 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1606 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1608 pb->table_idx = table->next_idx++;
1609 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1610 guint32 field_type = 0;
1611 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1613 alloc_table (mtable, mtable->rows);
1614 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1615 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1616 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1617 mvalues [MONO_CONSTANT_TYPE] = field_type;
1618 mvalues [MONO_CONSTANT_PADDING] = 0;
1625 #ifndef DISABLE_REFLECTION_EMIT
1627 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1629 MONO_REQ_GC_UNSAFE_MODE;
1631 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1633 rmb->ilgen = mb->ilgen;
1634 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1635 rmb->parameters = mb->parameters;
1636 rmb->generic_params = mb->generic_params;
1637 rmb->generic_container = mb->generic_container;
1638 rmb->opt_types = NULL;
1639 rmb->pinfo = mb->pinfo;
1640 rmb->attrs = mb->attrs;
1641 rmb->iattrs = mb->iattrs;
1642 rmb->call_conv = mb->call_conv;
1643 rmb->code = mb->code;
1644 rmb->type = mb->type;
1645 rmb->name = mb->name;
1646 rmb->table_idx = &mb->table_idx;
1647 rmb->init_locals = mb->init_locals;
1648 rmb->skip_visibility = FALSE;
1649 rmb->return_modreq = mb->return_modreq;
1650 rmb->return_modopt = mb->return_modopt;
1651 rmb->param_modreq = mb->param_modreq;
1652 rmb->param_modopt = mb->param_modopt;
1653 rmb->permissions = mb->permissions;
1654 rmb->mhandle = mb->mhandle;
1659 rmb->charset = mb->charset;
1660 rmb->extra_flags = mb->extra_flags;
1661 rmb->native_cc = mb->native_cc;
1662 rmb->dllentry = mb->dllentry;
1668 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1670 MONO_REQ_GC_UNSAFE_MODE;
1672 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1674 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1676 rmb->ilgen = mb->ilgen;
1677 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1678 rmb->parameters = mb->parameters;
1679 rmb->generic_params = NULL;
1680 rmb->generic_container = NULL;
1681 rmb->opt_types = NULL;
1682 rmb->pinfo = mb->pinfo;
1683 rmb->attrs = mb->attrs;
1684 rmb->iattrs = mb->iattrs;
1685 rmb->call_conv = mb->call_conv;
1687 rmb->type = mb->type;
1688 rmb->name = mono_string_new (mono_domain_get (), name);
1689 rmb->table_idx = &mb->table_idx;
1690 rmb->init_locals = mb->init_locals;
1691 rmb->skip_visibility = FALSE;
1692 rmb->return_modreq = NULL;
1693 rmb->return_modopt = NULL;
1694 rmb->param_modreq = mb->param_modreq;
1695 rmb->param_modopt = mb->param_modopt;
1696 rmb->permissions = mb->permissions;
1697 rmb->mhandle = mb->mhandle;
1703 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1705 MONO_REQ_GC_UNSAFE_MODE;
1707 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1709 rmb->ilgen = mb->ilgen;
1710 rmb->rtype = mb->rtype;
1711 rmb->parameters = mb->parameters;
1712 rmb->generic_params = NULL;
1713 rmb->generic_container = NULL;
1714 rmb->opt_types = NULL;
1716 rmb->attrs = mb->attrs;
1718 rmb->call_conv = mb->call_conv;
1720 rmb->type = (MonoObject *) mb->owner;
1721 rmb->name = mb->name;
1722 rmb->table_idx = NULL;
1723 rmb->init_locals = mb->init_locals;
1724 rmb->skip_visibility = mb->skip_visibility;
1725 rmb->return_modreq = NULL;
1726 rmb->return_modopt = NULL;
1727 rmb->param_modreq = NULL;
1728 rmb->param_modopt = NULL;
1729 rmb->permissions = NULL;
1730 rmb->mhandle = mb->mhandle;
1737 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1739 MONO_REQ_GC_UNSAFE_MODE;
1741 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1742 MonoDynamicTable *table;
1745 MonoReflectionMethod *m;
1748 if (!mb->override_methods)
1751 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1752 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1754 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1758 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1759 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1761 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1762 switch (mono_metadata_token_table (tok)) {
1763 case MONO_TABLE_MEMBERREF:
1764 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1766 case MONO_TABLE_METHOD:
1767 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1770 g_assert_not_reached ();
1772 values [MONO_METHODIMPL_DECLARATION] = tok;
1776 #ifndef DISABLE_REFLECTION_EMIT
1778 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1780 MONO_REQ_GC_UNSAFE_MODE;
1782 MonoDynamicTable *table;
1784 ReflectionMethodBuilder rmb;
1787 reflection_methodbuilder_from_method_builder (&rmb, mb);
1789 mono_image_basic_method (&rmb, assembly);
1790 mb->table_idx = *rmb.table_idx;
1792 if (mb->dll) { /* It's a P/Invoke method */
1794 /* map CharSet values to on-disk values */
1795 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1796 int extra_flags = mb->extra_flags;
1797 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1799 alloc_table (table, table->rows);
1800 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1802 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1803 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1805 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1807 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1808 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1809 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1810 table = &assembly->tables [MONO_TABLE_MODULEREF];
1812 alloc_table (table, table->rows);
1813 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1814 values [MONO_IMPLMAP_SCOPE] = table->rows;
1818 if (mb->generic_params) {
1819 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1820 table->rows += mono_array_length (mb->generic_params);
1821 alloc_table (table, table->rows);
1822 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1823 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1825 mono_image_get_generic_param_info (
1826 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1833 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1835 MONO_REQ_GC_UNSAFE_MODE;
1837 ReflectionMethodBuilder rmb;
1839 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1841 mono_image_basic_method (&rmb, assembly);
1842 mb->table_idx = *rmb.table_idx;
1847 type_get_fully_qualified_name (MonoType *type)
1849 MONO_REQ_GC_NEUTRAL_MODE;
1851 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1855 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1857 MONO_REQ_GC_UNSAFE_MODE;
1862 klass = mono_class_from_mono_type (type);
1864 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1865 ta = klass->image->assembly;
1866 if (assembly_is_dynamic (ta) || (ta == ass)) {
1867 if (klass->generic_class || klass->generic_container)
1868 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1869 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1871 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1874 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1877 #ifndef DISABLE_REFLECTION_EMIT
1878 /*field_image is the image to which the eventual custom mods have been encoded against*/
1880 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1882 MONO_REQ_GC_NEUTRAL_MODE;
1885 guint32 idx, i, token;
1887 if (!assembly->save)
1890 sigbuffer_init (&buf, 32);
1892 sigbuffer_add_value (&buf, 0x06);
1893 /* encode custom attributes before the type */
1894 if (type->num_mods) {
1895 for (i = 0; i < type->num_mods; ++i) {
1898 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1899 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1901 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1903 token = type->modifiers [i].token;
1906 if (type->modifiers [i].required)
1907 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1909 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1911 sigbuffer_add_value (&buf, token);
1914 encode_type (assembly, type, &buf);
1915 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1916 sigbuffer_free (&buf);
1922 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1924 MONO_REQ_GC_UNSAFE_MODE;
1928 guint32 typespec = 0;
1932 init_type_builder_generics (fb->type);
1934 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1935 klass = mono_class_from_mono_type (type);
1937 sigbuffer_init (&buf, 32);
1939 sigbuffer_add_value (&buf, 0x06);
1940 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1941 /* encode custom attributes before the type */
1943 if (klass->generic_container)
1944 typespec = create_typespec (assembly, type);
1947 MonoGenericClass *gclass;
1948 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1949 encode_generic_class (assembly, gclass, &buf);
1951 encode_type (assembly, type, &buf);
1953 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1954 sigbuffer_free (&buf);
1959 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1961 MONO_REQ_GC_UNSAFE_MODE;
1963 char blob_size [64];
1964 char *b = blob_size;
1967 guint32 idx = 0, len = 0, dummy = 0;
1969 buf = (char *)g_malloc (64);
1971 *ret_type = MONO_TYPE_CLASS;
1973 box_val = (char*)&dummy;
1975 box_val = ((char*)val) + sizeof (MonoObject);
1976 *ret_type = val->vtable->klass->byval_arg.type;
1979 switch (*ret_type) {
1980 case MONO_TYPE_BOOLEAN:
1985 case MONO_TYPE_CHAR:
2002 case MONO_TYPE_VALUETYPE: {
2003 MonoClass *klass = val->vtable->klass;
2005 if (klass->enumtype) {
2006 *ret_type = mono_class_enum_basetype (klass)->type;
2008 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2011 g_error ("we can't encode valuetypes, we should have never reached this line");
2014 case MONO_TYPE_CLASS:
2016 case MONO_TYPE_STRING: {
2017 MonoString *str = (MonoString*)val;
2018 /* there is no signature */
2019 len = str->length * 2;
2020 mono_metadata_encode_value (len, b, &b);
2021 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2023 char *swapped = g_malloc (2 * mono_string_length (str));
2024 const char *p = (const char*)mono_string_chars (str);
2026 swap_with_size (swapped, p, 2, mono_string_length (str));
2027 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2031 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2037 case MONO_TYPE_GENERICINST:
2038 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2041 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2044 /* there is no signature */
2045 mono_metadata_encode_value (len, b, &b);
2046 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2047 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2048 swap_with_size (blob_size, box_val, len, 1);
2049 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2051 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2059 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2061 MONO_REQ_GC_UNSAFE_MODE;
2067 sigbuffer_init (&buf, 32);
2069 sigbuffer_add_value (&buf, minfo->type);
2071 switch (minfo->type) {
2072 case MONO_NATIVE_BYVALTSTR:
2073 case MONO_NATIVE_BYVALARRAY:
2074 sigbuffer_add_value (&buf, minfo->count);
2076 case MONO_NATIVE_LPARRAY:
2077 if (minfo->eltype || minfo->has_size) {
2078 sigbuffer_add_value (&buf, minfo->eltype);
2079 if (minfo->has_size) {
2080 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2081 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2083 /* LAMESPEC: ElemMult is undocumented */
2084 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2088 case MONO_NATIVE_SAFEARRAY:
2090 sigbuffer_add_value (&buf, minfo->eltype);
2092 case MONO_NATIVE_CUSTOM:
2094 str = mono_string_to_utf8 (minfo->guid);
2096 sigbuffer_add_value (&buf, len);
2097 sigbuffer_add_mem (&buf, str, len);
2100 sigbuffer_add_value (&buf, 0);
2102 /* native type name */
2103 sigbuffer_add_value (&buf, 0);
2104 /* custom marshaler type name */
2105 if (minfo->marshaltype || minfo->marshaltyperef) {
2106 if (minfo->marshaltyperef)
2107 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2109 str = mono_string_to_utf8 (minfo->marshaltype);
2111 sigbuffer_add_value (&buf, len);
2112 sigbuffer_add_mem (&buf, str, len);
2115 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2116 sigbuffer_add_value (&buf, 0);
2118 if (minfo->mcookie) {
2119 str = mono_string_to_utf8 (minfo->mcookie);
2121 sigbuffer_add_value (&buf, len);
2122 sigbuffer_add_mem (&buf, str, len);
2125 sigbuffer_add_value (&buf, 0);
2131 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2132 sigbuffer_free (&buf);
2137 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2139 MONO_REQ_GC_UNSAFE_MODE;
2141 MonoDynamicTable *table;
2144 /* maybe this fixup should be done in the C# code */
2145 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2146 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2147 table = &assembly->tables [MONO_TABLE_FIELD];
2148 fb->table_idx = table->next_idx ++;
2149 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2150 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2151 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2152 values [MONO_FIELD_FLAGS] = fb->attrs;
2153 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2155 if (fb->offset != -1) {
2156 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2158 alloc_table (table, table->rows);
2159 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2160 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2161 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2163 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2164 MonoTypeEnum field_type = (MonoTypeEnum)0;
2165 table = &assembly->tables [MONO_TABLE_CONSTANT];
2167 alloc_table (table, table->rows);
2168 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2169 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2170 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2171 values [MONO_CONSTANT_TYPE] = field_type;
2172 values [MONO_CONSTANT_PADDING] = 0;
2174 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2176 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2178 alloc_table (table, table->rows);
2179 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2180 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2182 * We store it in the code section because it's simpler for now.
2185 if (mono_array_length (fb->rva_data) >= 10)
2186 stream_data_align (&assembly->code);
2187 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2189 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2190 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2192 if (fb->marshal_info) {
2193 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2195 alloc_table (table, table->rows);
2196 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2197 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2198 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2203 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2205 MONO_REQ_GC_UNSAFE_MODE;
2208 guint32 nparams = 0;
2209 MonoReflectionMethodBuilder *mb = fb->get_method;
2210 MonoReflectionMethodBuilder *smb = fb->set_method;
2213 if (mb && mb->parameters)
2214 nparams = mono_array_length (mb->parameters);
2215 if (!mb && smb && smb->parameters)
2216 nparams = mono_array_length (smb->parameters) - 1;
2217 sigbuffer_init (&buf, 32);
2218 if (fb->call_conv & 0x20)
2219 sigbuffer_add_byte (&buf, 0x28);
2221 sigbuffer_add_byte (&buf, 0x08);
2222 sigbuffer_add_value (&buf, nparams);
2224 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2225 for (i = 0; i < nparams; ++i) {
2226 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2227 encode_reflection_type (assembly, pt, &buf);
2229 } else if (smb && smb->parameters) {
2230 /* the property type is the last param */
2231 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2232 for (i = 0; i < nparams; ++i) {
2233 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2234 encode_reflection_type (assembly, pt, &buf);
2237 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2240 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2241 sigbuffer_free (&buf);
2246 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2248 MONO_REQ_GC_UNSAFE_MODE;
2250 MonoDynamicTable *table;
2252 guint num_methods = 0;
2256 * we need to set things in the following tables:
2257 * PROPERTYMAP (info already filled in _get_type_info ())
2258 * PROPERTY (rows already preallocated in _get_type_info ())
2259 * METHOD (method info already done with the generic method code)
2263 table = &assembly->tables [MONO_TABLE_PROPERTY];
2264 pb->table_idx = table->next_idx ++;
2265 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2266 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2267 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2268 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2270 /* FIXME: we still don't handle 'other' methods */
2271 if (pb->get_method) num_methods ++;
2272 if (pb->set_method) num_methods ++;
2274 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2275 table->rows += num_methods;
2276 alloc_table (table, table->rows);
2278 if (pb->get_method) {
2279 semaidx = table->next_idx ++;
2280 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2281 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2282 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2283 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2285 if (pb->set_method) {
2286 semaidx = table->next_idx ++;
2287 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2289 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2290 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2292 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2293 MonoTypeEnum field_type = (MonoTypeEnum)0;
2294 table = &assembly->tables [MONO_TABLE_CONSTANT];
2296 alloc_table (table, table->rows);
2297 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2298 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2299 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2300 values [MONO_CONSTANT_TYPE] = field_type;
2301 values [MONO_CONSTANT_PADDING] = 0;
2306 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2308 MONO_REQ_GC_UNSAFE_MODE;
2310 MonoDynamicTable *table;
2312 guint num_methods = 0;
2316 * we need to set things in the following tables:
2317 * EVENTMAP (info already filled in _get_type_info ())
2318 * EVENT (rows already preallocated in _get_type_info ())
2319 * METHOD (method info already done with the generic method code)
2322 table = &assembly->tables [MONO_TABLE_EVENT];
2323 eb->table_idx = table->next_idx ++;
2324 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2325 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2326 values [MONO_EVENT_FLAGS] = eb->attrs;
2327 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2330 * FIXME: we still don't handle 'other' methods
2332 if (eb->add_method) num_methods ++;
2333 if (eb->remove_method) num_methods ++;
2334 if (eb->raise_method) num_methods ++;
2336 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2337 table->rows += num_methods;
2338 alloc_table (table, table->rows);
2340 if (eb->add_method) {
2341 semaidx = table->next_idx ++;
2342 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2343 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2344 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2345 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2347 if (eb->remove_method) {
2348 semaidx = table->next_idx ++;
2349 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2351 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2352 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2354 if (eb->raise_method) {
2355 semaidx = table->next_idx ++;
2356 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2358 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2359 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2364 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2366 MONO_REQ_GC_UNSAFE_MODE;
2368 MonoDynamicTable *table;
2369 guint32 num_constraints, i;
2373 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2374 num_constraints = gparam->iface_constraints ?
2375 mono_array_length (gparam->iface_constraints) : 0;
2376 table->rows += num_constraints;
2377 if (gparam->base_type)
2379 alloc_table (table, table->rows);
2381 if (gparam->base_type) {
2382 table_idx = table->next_idx ++;
2383 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2385 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2386 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2387 assembly, mono_reflection_type_get_handle (gparam->base_type));
2390 for (i = 0; i < num_constraints; i++) {
2391 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2392 gparam->iface_constraints, gpointer, i);
2394 table_idx = table->next_idx ++;
2395 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2397 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2398 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2399 assembly, mono_reflection_type_get_handle (constraint));
2404 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2406 MONO_REQ_GC_UNSAFE_MODE;
2408 GenericParamTableEntry *entry;
2411 * The GenericParam table must be sorted according to the `owner' field.
2412 * We need to do this sorting prior to writing the GenericParamConstraint
2413 * table, since we have to use the final GenericParam table indices there
2414 * and they must also be sorted.
2417 entry = g_new0 (GenericParamTableEntry, 1);
2418 entry->owner = owner;
2419 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2420 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2421 entry->gparam = gparam;
2423 g_ptr_array_add (assembly->gen_params, entry);
2427 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2429 MONO_REQ_GC_UNSAFE_MODE;
2431 MonoDynamicTable *table;
2432 MonoGenericParam *param;
2436 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2437 table_idx = table->next_idx ++;
2438 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2440 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2442 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2443 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2444 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2445 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2447 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2449 encode_constraints (entry->gparam, table_idx, assembly);
2453 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2455 MONO_REQ_GC_UNSAFE_MODE;
2457 MonoDynamicTable *table;
2460 guint32 cols [MONO_ASSEMBLY_SIZE];
2464 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2467 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2468 table = &assembly->tables [MONO_TABLE_MODULEREF];
2469 token = table->next_idx ++;
2471 alloc_table (table, table->rows);
2472 values = table->values + token * MONO_MODULEREF_SIZE;
2473 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2475 token <<= MONO_RESOLUTION_SCOPE_BITS;
2476 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2477 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2482 if (assembly_is_dynamic (image->assembly))
2484 memset (cols, 0, sizeof (cols));
2486 /* image->assembly->image is the manifest module */
2487 image = image->assembly->image;
2488 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2491 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2492 token = table->next_idx ++;
2494 alloc_table (table, table->rows);
2495 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2496 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2497 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2498 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2499 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2500 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2501 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2502 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2503 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2505 if (strcmp ("", image->assembly->aname.culture)) {
2506 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2507 image->assembly->aname.culture);
2510 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2511 guchar pubtoken [9];
2513 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2514 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2516 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2518 token <<= MONO_RESOLUTION_SCOPE_BITS;
2519 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2520 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2525 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2527 MONO_REQ_GC_NEUTRAL_MODE;
2529 MonoDynamicTable *table;
2534 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2537 sigbuffer_init (&buf, 32);
2538 switch (type->type) {
2539 case MONO_TYPE_FNPTR:
2541 case MONO_TYPE_SZARRAY:
2542 case MONO_TYPE_ARRAY:
2544 case MONO_TYPE_MVAR:
2545 case MONO_TYPE_GENERICINST:
2546 encode_type (assembly, type, &buf);
2548 case MONO_TYPE_CLASS:
2549 case MONO_TYPE_VALUETYPE: {
2550 MonoClass *k = mono_class_from_mono_type (type);
2551 if (!k || !k->generic_container) {
2552 sigbuffer_free (&buf);
2555 encode_type (assembly, type, &buf);
2559 sigbuffer_free (&buf);
2563 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2564 if (assembly->save) {
2565 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2566 alloc_table (table, table->rows + 1);
2567 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2568 values [MONO_TYPESPEC_SIGNATURE] = token;
2570 sigbuffer_free (&buf);
2572 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2573 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2579 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2581 MONO_REQ_GC_UNSAFE_MODE;
2583 MonoDynamicTable *table;
2585 guint32 token, scope, enclosing;
2588 /* if the type requires a typespec, we must try that first*/
2589 if (try_typespec && (token = create_typespec (assembly, type)))
2591 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2594 klass = mono_class_from_mono_type (type);
2596 klass = mono_class_from_mono_type (type);
2599 * If it's in the same module and not a generic type parameter:
2601 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2602 (type->type != MONO_TYPE_MVAR)) {
2603 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2604 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2605 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2609 if (klass->nested_in) {
2610 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2611 /* get the typeref idx of the enclosing type */
2612 enclosing >>= MONO_TYPEDEFORREF_BITS;
2613 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2615 scope = resolution_scope_from_image (assembly, klass->image);
2617 table = &assembly->tables [MONO_TABLE_TYPEREF];
2618 if (assembly->save) {
2619 alloc_table (table, table->rows + 1);
2620 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2621 values [MONO_TYPEREF_SCOPE] = scope;
2622 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2623 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2625 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2626 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2628 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2633 * Despite the name, we handle also TypeSpec (with the above helper).
2636 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2638 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2641 #ifndef DISABLE_REFLECTION_EMIT
2643 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2645 MONO_REQ_GC_NEUTRAL_MODE;
2647 MonoDynamicTable *table;
2649 guint32 token, pclass;
2651 switch (parent & MONO_TYPEDEFORREF_MASK) {
2652 case MONO_TYPEDEFORREF_TYPEREF:
2653 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2655 case MONO_TYPEDEFORREF_TYPESPEC:
2656 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2658 case MONO_TYPEDEFORREF_TYPEDEF:
2659 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2662 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2665 /* extract the index */
2666 parent >>= MONO_TYPEDEFORREF_BITS;
2668 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2670 if (assembly->save) {
2671 alloc_table (table, table->rows + 1);
2672 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2673 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2674 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2675 values [MONO_MEMBERREF_SIGNATURE] = sig;
2678 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2685 * Insert a memberef row into the metadata: the token that point to the memberref
2686 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2687 * mono_image_get_fieldref_token()).
2688 * The sig param is an index to an already built signature.
2691 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2693 MONO_REQ_GC_NEUTRAL_MODE;
2695 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2696 return mono_image_add_memberef_row (assembly, parent, name, sig);
2701 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2703 MONO_REQ_GC_NEUTRAL_MODE;
2706 MonoMethodSignature *sig;
2708 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2710 if (create_typespec) {
2711 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2716 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2717 if (token && !create_typespec)
2720 g_assert (!method->is_inflated);
2723 * A methodref signature can't contain an unmanaged calling convention.
2725 sig = mono_metadata_signature_dup (mono_method_signature (method));
2726 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2727 sig->call_convention = MONO_CALL_DEFAULT;
2728 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2729 method->name, method_encode_signature (assembly, sig));
2731 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2734 if (create_typespec) {
2735 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2736 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2737 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2739 if (assembly->save) {
2742 alloc_table (table, table->rows + 1);
2743 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2744 values [MONO_METHODSPEC_METHOD] = token;
2745 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2748 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2750 /*methodspec and memberef tokens are diferent, */
2751 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2758 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2760 guint32 token, parent, sig;
2761 ReflectionMethodBuilder rmb;
2763 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2765 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2769 name = mono_string_to_utf8 (method->name);
2770 reflection_methodbuilder_from_method_builder (&rmb, method);
2773 * A methodref signature can't contain an unmanaged calling convention.
2774 * Since some flags are encoded as part of call_conv, we need to check against it.
2776 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2777 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2779 sig = method_builder_encode_signature (assembly, &rmb);
2781 if (tb->generic_params)
2782 parent = create_generic_typespec (assembly, tb);
2784 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2786 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2789 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2794 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2795 const gchar *name, guint32 sig)
2797 MonoDynamicTable *table;
2801 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2803 if (assembly->save) {
2804 alloc_table (table, table->rows + 1);
2805 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2806 values [MONO_MEMBERREF_CLASS] = original;
2807 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2808 values [MONO_MEMBERREF_SIGNATURE] = sig;
2811 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2818 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2822 guint32 nparams = mono_array_length (mb->generic_params);
2825 if (!assembly->save)
2828 sigbuffer_init (&buf, 32);
2830 sigbuffer_add_value (&buf, 0xa);
2831 sigbuffer_add_value (&buf, nparams);
2833 for (i = 0; i < nparams; i++) {
2834 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2835 sigbuffer_add_value (&buf, i);
2838 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2839 sigbuffer_free (&buf);
2844 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2846 MonoDynamicTable *table;
2848 guint32 token, mtoken = 0;
2850 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2854 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2856 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2857 switch (mono_metadata_token_table (mtoken)) {
2858 case MONO_TABLE_MEMBERREF:
2859 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2861 case MONO_TABLE_METHOD:
2862 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2865 g_assert_not_reached ();
2868 if (assembly->save) {
2869 alloc_table (table, table->rows + 1);
2870 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2871 values [MONO_METHODSPEC_METHOD] = mtoken;
2872 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2875 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2878 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2883 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2887 if (mb->generic_params && create_methodspec)
2888 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2890 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2894 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2895 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2900 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2902 guint32 token, parent, sig;
2903 ReflectionMethodBuilder rmb;
2905 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2907 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2911 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2913 if (tb->generic_params)
2914 parent = create_generic_typespec (assembly, tb);
2916 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2918 name = mono_string_to_utf8 (rmb.name);
2919 sig = method_builder_encode_signature (assembly, &rmb);
2921 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2924 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2930 is_field_on_inst (MonoClassField *field)
2932 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2936 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2939 get_field_on_inst_generic_type (MonoClassField *field)
2941 MonoClass *klass, *gtd;
2942 MonoDynamicGenericClass *dgclass;
2945 g_assert (is_field_on_inst (field));
2947 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2949 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2950 field_index = field - dgclass->fields;
2951 return dgclass->field_generic_types [field_index];
2954 klass = field->parent;
2955 gtd = klass->generic_class->container_class;
2957 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2958 field_index = field - klass->fields;
2959 return gtd->fields [field_index].type;
2962 g_assert_not_reached ();
2966 #ifndef DISABLE_REFLECTION_EMIT
2968 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2974 g_assert (field->parent);
2976 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2980 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2981 int index = field - field->parent->fields;
2982 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2984 if (is_field_on_inst (field))
2985 type = get_field_on_inst_generic_type (field);
2987 type = mono_field_get_type (field);
2989 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2990 mono_field_get_name (field),
2991 fieldref_encode_signature (assembly, field->parent->image, type));
2992 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2997 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3001 MonoGenericClass *gclass;
3005 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3008 if (is_sre_field_builder (mono_object_class (f->fb))) {
3009 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3010 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3011 klass = mono_class_from_mono_type (type);
3012 gclass = type->data.generic_class;
3013 g_assert (gclass->is_dynamic);
3015 name = mono_string_to_utf8 (fb->name);
3016 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3017 field_encode_signature (assembly, fb));
3019 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3021 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3023 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3024 klass = mono_class_from_mono_type (type);
3026 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3027 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3029 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3030 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3033 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3038 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3042 MonoGenericClass *gclass;
3045 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3047 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3051 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3052 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3053 ReflectionMethodBuilder rmb;
3056 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3057 klass = mono_class_from_mono_type (type);
3059 gclass = type->data.generic_class;
3060 g_assert (gclass->is_dynamic);
3062 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3064 name = mono_string_to_utf8 (rmb.name);
3066 sig = method_builder_encode_signature (assembly, &rmb);
3068 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3070 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3071 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3073 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3074 klass = mono_class_from_mono_type (type);
3076 sig = method_encode_signature (assembly, mono_method_signature (mm));
3077 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3079 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3080 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3084 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3089 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3093 MonoGenericContext tmp_context;
3094 MonoType **type_argv;
3095 MonoGenericInst *ginst;
3096 MonoMethod *method, *inflated;
3099 init_type_builder_generics ((MonoObject*)m->inst);
3101 method = inflate_method (m->inst, (MonoObject*)m->mb);
3103 klass = method->klass;
3105 if (m->method_args == NULL)
3108 if (method->is_inflated)
3109 method = ((MonoMethodInflated *) method)->declaring;
3111 count = mono_array_length (m->method_args);
3113 type_argv = g_new0 (MonoType *, count);
3114 for (i = 0; i < count; i++) {
3115 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3116 type_argv [i] = mono_reflection_type_get_handle (garg);
3118 ginst = mono_metadata_get_generic_inst (count, type_argv);
3121 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3122 tmp_context.method_inst = ginst;
3124 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3125 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3130 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3132 guint32 sig, token = 0;
3136 if (m->method_args) {
3137 MonoMethod *inflated;
3139 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3140 if (create_methodspec)
3141 token = mono_image_get_methodspec_token (assembly, inflated);
3143 token = mono_image_get_inflated_method_token (assembly, inflated);
3147 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3151 if (is_sre_method_builder (mono_object_class (m->mb))) {
3152 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3153 MonoGenericClass *gclass;
3154 ReflectionMethodBuilder rmb;
3157 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3158 klass = mono_class_from_mono_type (type);
3159 gclass = type->data.generic_class;
3160 g_assert (gclass->is_dynamic);
3162 reflection_methodbuilder_from_method_builder (&rmb, mb);
3164 name = mono_string_to_utf8 (rmb.name);
3166 sig = method_builder_encode_signature (assembly, &rmb);
3168 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3170 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3171 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3173 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3174 klass = mono_class_from_mono_type (type);
3176 sig = method_encode_signature (assembly, mono_method_signature (mm));
3177 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3179 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3180 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3183 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3188 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3192 guint32 nparams = context->method_inst->type_argc;
3195 if (!assembly->save)
3198 sigbuffer_init (&buf, 32);
3200 * FIXME: vararg, explicit_this, differenc call_conv values...
3202 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3203 sigbuffer_add_value (&buf, nparams);
3205 for (i = 0; i < nparams; i++)
3206 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3208 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3209 sigbuffer_free (&buf);
3214 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3216 MonoDynamicTable *table;
3218 guint32 token, mtoken = 0, sig;
3219 MonoMethodInflated *imethod;
3220 MonoMethod *declaring;
3222 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3224 g_assert (method->is_inflated);
3225 imethod = (MonoMethodInflated *) method;
3226 declaring = imethod->declaring;
3228 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3229 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3231 if (!mono_method_signature (declaring)->generic_param_count)
3234 switch (mono_metadata_token_table (mtoken)) {
3235 case MONO_TABLE_MEMBERREF:
3236 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3238 case MONO_TABLE_METHOD:
3239 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3242 g_assert_not_reached ();
3245 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3247 if (assembly->save) {
3248 alloc_table (table, table->rows + 1);
3249 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3250 values [MONO_METHODSPEC_METHOD] = mtoken;
3251 values [MONO_METHODSPEC_SIGNATURE] = sig;
3254 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3261 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3263 MonoMethodInflated *imethod;
3266 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3270 g_assert (method->is_inflated);
3271 imethod = (MonoMethodInflated *) method;
3273 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3274 token = method_encode_methodspec (assembly, method);
3276 guint32 sig = method_encode_signature (
3277 assembly, mono_method_signature (imethod->declaring));
3278 token = mono_image_get_memberref_token (
3279 assembly, &method->klass->byval_arg, method->name, sig);
3282 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3287 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3289 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3292 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3293 token = mono_image_get_memberref_token (
3294 assembly, &m->klass->byval_arg, m->name, sig);
3300 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3302 MonoDynamicTable *table;
3311 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3312 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3313 * Because of this, we must not insert it into the `typeref' hash table.
3315 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3316 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3320 sigbuffer_init (&buf, 32);
3322 g_assert (tb->generic_params);
3323 klass = mono_class_from_mono_type (type);
3325 if (tb->generic_container)
3326 mono_reflection_create_generic_class (tb);
3328 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3329 g_assert (klass->generic_container);
3330 sigbuffer_add_value (&buf, klass->byval_arg.type);
3331 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3333 count = mono_array_length (tb->generic_params);
3334 sigbuffer_add_value (&buf, count);
3335 for (i = 0; i < count; i++) {
3336 MonoReflectionGenericParam *gparam;
3338 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3340 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3343 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3345 if (assembly->save) {
3346 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3347 alloc_table (table, table->rows + 1);
3348 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3349 values [MONO_TYPESPEC_SIGNATURE] = token;
3351 sigbuffer_free (&buf);
3353 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3354 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3360 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3363 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3365 int i, count, len, pos;
3370 count += mono_array_length (modreq);
3372 count += mono_array_length (modopt);
3375 return mono_metadata_type_dup (NULL, type);
3377 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3378 t = (MonoType *)g_malloc (len);
3379 memcpy (t, type, MONO_SIZEOF_TYPE);
3381 t->num_mods = count;
3384 for (i = 0; i < mono_array_length (modreq); ++i) {
3385 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3386 t->modifiers [pos].required = 1;
3387 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3392 for (i = 0; i < mono_array_length (modopt); ++i) {
3393 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3394 t->modifiers [pos].required = 0;
3395 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3404 init_type_builder_generics (MonoObject *type)
3406 MonoReflectionTypeBuilder *tb;
3408 if (!is_sre_type_builder(mono_object_class (type)))
3410 tb = (MonoReflectionTypeBuilder *)type;
3412 if (tb && tb->generic_container)
3413 mono_reflection_create_generic_class (tb);
3417 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3419 MonoDynamicTable *table;
3420 MonoType *custom = NULL, *type;
3422 guint32 token, pclass, parent, sig;
3425 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3429 /* FIXME: is this call necessary? */
3430 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3431 name = mono_string_to_utf8 (fb->name);
3433 /*FIXME this is one more layer of ugliness due how types are created.*/
3434 init_type_builder_generics (fb->type);
3436 /* fb->type does not include the custom modifiers */
3437 /* FIXME: We should do this in one place when a fieldbuilder is created */
3438 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3439 if (fb->modreq || fb->modopt)
3440 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3442 sig = fieldref_encode_signature (assembly, NULL, type);
3445 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3446 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3448 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3449 parent >>= MONO_TYPEDEFORREF_BITS;
3451 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3453 if (assembly->save) {
3454 alloc_table (table, table->rows + 1);
3455 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3456 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3457 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3458 values [MONO_MEMBERREF_SIGNATURE] = sig;
3461 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3463 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3469 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3475 if (!assembly->save)
3478 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3479 g_assert (helper->type == 2);
3481 if (helper->arguments)
3482 nargs = mono_array_length (helper->arguments);
3486 sigbuffer_init (&buf, 32);
3488 /* Encode calling convention */
3489 /* Change Any to Standard */
3490 if ((helper->call_conv & 0x03) == 0x03)
3491 helper->call_conv = 0x01;
3492 /* explicit_this implies has_this */
3493 if (helper->call_conv & 0x40)
3494 helper->call_conv &= 0x20;
3496 if (helper->call_conv == 0) { /* Unmanaged */
3497 idx = helper->unmanaged_call_conv - 1;
3500 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3501 if (helper->call_conv & 0x02) /* varargs */
3505 sigbuffer_add_byte (&buf, idx);
3506 sigbuffer_add_value (&buf, nargs);
3507 encode_reflection_type (assembly, helper->return_type, &buf);
3508 for (i = 0; i < nargs; ++i) {
3509 MonoArray *modreqs = NULL;
3510 MonoArray *modopts = NULL;
3511 MonoReflectionType *pt;
3513 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3514 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3515 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3516 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3518 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3519 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3520 encode_reflection_type (assembly, pt, &buf);
3522 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3523 sigbuffer_free (&buf);
3529 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3532 MonoDynamicTable *table;
3535 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3536 idx = table->next_idx ++;
3538 alloc_table (table, table->rows);
3539 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3541 values [MONO_STAND_ALONE_SIGNATURE] =
3542 mono_reflection_encode_sighelper (assembly, helper);
3548 reflection_cc_to_file (int call_conv) {
3549 switch (call_conv & 0x3) {
3551 case 1: return MONO_CALL_DEFAULT;
3552 case 2: return MONO_CALL_VARARG;
3554 g_assert_not_reached ();
3558 #endif /* !DISABLE_REFLECTION_EMIT */
3562 MonoMethodSignature *sig;
3567 #ifndef DISABLE_REFLECTION_EMIT
3569 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3574 MonoMethodSignature *sig;
3578 name = mono_string_to_utf8 (m->name);
3579 nparams = mono_array_length (m->parameters);
3580 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3582 sig->sentinelpos = -1;
3583 sig->call_convention = reflection_cc_to_file (m->call_conv);
3584 sig->param_count = nparams;
3585 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3586 mtype = mono_reflection_type_get_handle (m->parent);
3587 for (i = 0; i < nparams; ++i)
3588 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3590 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3591 am = (ArrayMethod *)tmp->data;
3592 if (strcmp (name, am->name) == 0 &&
3593 mono_metadata_type_equal (am->parent, mtype) &&
3594 mono_metadata_signature_equal (am->sig, sig)) {
3597 m->table_idx = am->token & 0xffffff;
3601 am = g_new0 (ArrayMethod, 1);
3605 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3606 method_encode_signature (assembly, sig));
3607 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3608 m->table_idx = am->token & 0xffffff;
3613 * Insert into the metadata tables all the info about the TypeBuilder tb.
3614 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3617 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3619 MonoDynamicTable *table;
3621 int i, is_object = 0, is_system = 0;
3624 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3625 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3626 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3627 n = mono_string_to_utf8 (tb->name);
3628 if (strcmp (n, "Object") == 0)
3630 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3632 n = mono_string_to_utf8 (tb->nspace);
3633 if (strcmp (n, "System") == 0)
3635 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3637 if (tb->parent && !(is_system && is_object) &&
3638 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3639 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3641 values [MONO_TYPEDEF_EXTENDS] = 0;
3643 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3644 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3647 * if we have explicitlayout or sequentiallayouts, output data in the
3648 * ClassLayout table.
3650 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3651 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3652 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3654 alloc_table (table, table->rows);
3655 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3656 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3657 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3658 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3661 /* handle interfaces */
3662 if (tb->interfaces) {
3663 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3665 table->rows += mono_array_length (tb->interfaces);
3666 alloc_table (table, table->rows);
3667 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3668 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3669 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3670 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3671 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3672 values += MONO_INTERFACEIMPL_SIZE;
3678 table = &assembly->tables [MONO_TABLE_FIELD];
3679 table->rows += tb->num_fields;
3680 alloc_table (table, table->rows);
3681 for (i = 0; i < tb->num_fields; ++i)
3682 mono_image_get_field_info (
3683 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3686 /* handle constructors */
3688 table = &assembly->tables [MONO_TABLE_METHOD];
3689 table->rows += mono_array_length (tb->ctors);
3690 alloc_table (table, table->rows);
3691 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3692 mono_image_get_ctor_info (domain,
3693 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3696 /* handle methods */
3698 table = &assembly->tables [MONO_TABLE_METHOD];
3699 table->rows += tb->num_methods;
3700 alloc_table (table, table->rows);
3701 for (i = 0; i < tb->num_methods; ++i)
3702 mono_image_get_method_info (
3703 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3706 /* Do the same with properties etc.. */
3707 if (tb->events && mono_array_length (tb->events)) {
3708 table = &assembly->tables [MONO_TABLE_EVENT];
3709 table->rows += mono_array_length (tb->events);
3710 alloc_table (table, table->rows);
3711 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3713 alloc_table (table, table->rows);
3714 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3715 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3716 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3717 for (i = 0; i < mono_array_length (tb->events); ++i)
3718 mono_image_get_event_info (
3719 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3721 if (tb->properties && mono_array_length (tb->properties)) {
3722 table = &assembly->tables [MONO_TABLE_PROPERTY];
3723 table->rows += mono_array_length (tb->properties);
3724 alloc_table (table, table->rows);
3725 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3727 alloc_table (table, table->rows);
3728 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3729 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3730 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3731 for (i = 0; i < mono_array_length (tb->properties); ++i)
3732 mono_image_get_property_info (
3733 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3736 /* handle generic parameters */
3737 if (tb->generic_params) {
3738 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3739 table->rows += mono_array_length (tb->generic_params);
3740 alloc_table (table, table->rows);
3741 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3742 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3744 mono_image_get_generic_param_info (
3745 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3749 mono_image_add_decl_security (assembly,
3750 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3753 MonoDynamicTable *ntable;
3755 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3756 ntable->rows += mono_array_length (tb->subtypes);
3757 alloc_table (ntable, ntable->rows);
3758 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3760 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3761 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3763 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3764 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3765 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3766 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3767 mono_string_to_utf8 (tb->name), tb->table_idx,
3768 ntable->next_idx, ntable->rows);*/
3769 values += MONO_NESTED_CLASS_SIZE;
3777 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3781 mono_ptr_array_append (*types, type);
3783 if (!type->subtypes)
3786 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3787 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3788 collect_types (types, subtype);
3793 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3795 if ((*type1)->table_idx < (*type2)->table_idx)
3798 if ((*type1)->table_idx > (*type2)->table_idx)
3805 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3810 for (i = 0; i < mono_array_length (pinfo); ++i) {
3811 MonoReflectionParamBuilder *pb;
3812 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3815 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3820 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3823 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3825 for (i = 0; i < tb->num_fields; ++i) {
3826 MonoReflectionFieldBuilder* fb;
3827 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3828 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3832 for (i = 0; i < mono_array_length (tb->events); ++i) {
3833 MonoReflectionEventBuilder* eb;
3834 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3835 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3838 if (tb->properties) {
3839 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3840 MonoReflectionPropertyBuilder* pb;
3841 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3842 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3846 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3847 MonoReflectionCtorBuilder* cb;
3848 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3849 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3850 params_add_cattrs (assembly, cb->pinfo);
3855 for (i = 0; i < tb->num_methods; ++i) {
3856 MonoReflectionMethodBuilder* mb;
3857 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3858 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3859 params_add_cattrs (assembly, mb->pinfo);
3864 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3865 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3870 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3874 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3876 if (moduleb->global_methods) {
3877 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3878 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3879 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3880 params_add_cattrs (assembly, mb->pinfo);
3884 if (moduleb->global_fields) {
3885 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3886 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3887 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3891 if (moduleb->types) {
3892 for (i = 0; i < moduleb->num_types; ++i)
3893 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3898 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3900 MonoDynamicTable *table;
3904 char *b = blob_size;
3907 table = &assembly->tables [MONO_TABLE_FILE];
3909 alloc_table (table, table->rows);
3910 values = table->values + table->next_idx * MONO_FILE_SIZE;
3911 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3912 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3913 if (image_is_dynamic (module->image)) {
3914 /* This depends on the fact that the main module is emitted last */
3915 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3916 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3919 path = g_strdup (module->image->name);
3921 mono_sha1_get_digest_from_file (path, hash);
3924 mono_metadata_encode_value (20, b, &b);
3925 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3926 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3931 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3933 MonoDynamicTable *table;
3936 table = &assembly->tables [MONO_TABLE_MODULE];
3937 mb->table_idx = table->next_idx ++;
3938 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3939 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3942 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3943 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3944 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3945 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3949 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3950 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3952 MonoDynamicTable *table;
3956 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3957 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3960 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3962 alloc_table (table, table->rows);
3963 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3965 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3966 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3967 if (klass->nested_in)
3968 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3970 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3971 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3972 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3974 res = table->next_idx;
3978 /* Emit nested types */
3979 if (klass->ext && klass->ext->nested_classes) {
3982 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3983 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3990 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3991 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3996 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3998 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4000 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4001 parent_index, assembly);
4005 * We need to do this ourselves since klass->nested_classes is not set up.
4008 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4009 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4014 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4015 guint32 module_index, MonoDynamicImage *assembly)
4017 MonoImage *image = module->image;
4021 t = &image->tables [MONO_TABLE_TYPEDEF];
4023 for (i = 0; i < t->rows; ++i) {
4025 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4026 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4028 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4029 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4034 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4036 MonoDynamicTable *table;
4038 guint32 scope, scope_idx, impl, current_idx;
4039 gboolean forwarder = TRUE;
4040 gpointer iter = NULL;
4043 if (klass->nested_in) {
4044 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4047 scope = resolution_scope_from_image (assembly, klass->image);
4048 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4049 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4050 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4053 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4056 alloc_table (table, table->rows);
4057 current_idx = table->next_idx;
4058 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4060 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4061 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4062 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4063 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4064 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4068 while ((nested = mono_class_get_nested_types (klass, &iter)))
4069 add_exported_type (assemblyb, assembly, nested, current_idx);
4073 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4078 if (!assemblyb->type_forwarders)
4081 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4082 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4087 type = mono_reflection_type_get_handle (t);
4090 klass = mono_class_from_mono_type (type);
4092 add_exported_type (assemblyb, assembly, klass, 0);
4096 #define align_pointer(base,p)\
4098 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4100 (p) += 4 - (__diff & 3);\
4104 compare_constants (const void *a, const void *b)
4106 const guint32 *a_values = (const guint32 *)a;
4107 const guint32 *b_values = (const guint32 *)b;
4108 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4112 compare_semantics (const void *a, const void *b)
4114 const guint32 *a_values = (const guint32 *)a;
4115 const guint32 *b_values = (const guint32 *)b;
4116 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4119 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4123 compare_custom_attrs (const void *a, const void *b)
4125 const guint32 *a_values = (const guint32 *)a;
4126 const guint32 *b_values = (const guint32 *)b;
4128 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4132 compare_field_marshal (const void *a, const void *b)
4134 const guint32 *a_values = (const guint32 *)a;
4135 const guint32 *b_values = (const guint32 *)b;
4137 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4141 compare_nested (const void *a, const void *b)
4143 const guint32 *a_values = (const guint32 *)a;
4144 const guint32 *b_values = (const guint32 *)b;
4146 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4150 compare_genericparam (const void *a, const void *b)
4152 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4153 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4155 if ((*b_entry)->owner == (*a_entry)->owner)
4157 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4158 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4160 return (*a_entry)->owner - (*b_entry)->owner;
4164 compare_declsecurity_attrs (const void *a, const void *b)
4166 const guint32 *a_values = (const guint32 *)a;
4167 const guint32 *b_values = (const guint32 *)b;
4169 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4173 compare_interface_impl (const void *a, const void *b)
4175 const guint32 *a_values = (const guint32 *)a;
4176 const guint32 *b_values = (const guint32 *)b;
4178 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4182 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4186 pad_heap (MonoDynamicStream *sh)
4188 if (sh->index & 3) {
4189 int sz = 4 - (sh->index & 3);
4190 memset (sh->data + sh->index, 0, sz);
4197 MonoDynamicStream *stream;
4201 * build_compressed_metadata() fills in the blob of data that represents the
4202 * raw metadata as it will be saved in the PE file. The five streams are output
4203 * and the metadata tables are comnpressed from the guint32 array representation,
4204 * to the compressed on-disk format.
4207 build_compressed_metadata (MonoDynamicImage *assembly)
4209 MonoDynamicTable *table;
4211 guint64 valid_mask = 0;
4212 guint64 sorted_mask;
4213 guint32 heapt_size = 0;
4214 guint32 meta_size = 256; /* allow for header and other stuff */
4215 guint32 table_offset;
4216 guint32 ntables = 0;
4222 struct StreamDesc stream_desc [5];
4224 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4225 for (i = 0; i < assembly->gen_params->len; i++){
4226 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4227 write_generic_param_entry (assembly, entry);
4230 stream_desc [0].name = "#~";
4231 stream_desc [0].stream = &assembly->tstream;
4232 stream_desc [1].name = "#Strings";
4233 stream_desc [1].stream = &assembly->sheap;
4234 stream_desc [2].name = "#US";
4235 stream_desc [2].stream = &assembly->us;
4236 stream_desc [3].name = "#Blob";
4237 stream_desc [3].stream = &assembly->blob;
4238 stream_desc [4].name = "#GUID";
4239 stream_desc [4].stream = &assembly->guid;
4241 /* tables that are sorted */
4242 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4243 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4244 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4245 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4246 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4247 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4248 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4250 /* Compute table sizes */
4251 /* the MonoImage has already been created in mono_image_basic_init() */
4252 meta = &assembly->image;
4254 /* sizes should be multiple of 4 */
4255 pad_heap (&assembly->blob);
4256 pad_heap (&assembly->guid);
4257 pad_heap (&assembly->sheap);
4258 pad_heap (&assembly->us);
4260 /* Setup the info used by compute_sizes () */
4261 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4262 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4263 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4265 meta_size += assembly->blob.index;
4266 meta_size += assembly->guid.index;
4267 meta_size += assembly->sheap.index;
4268 meta_size += assembly->us.index;
4270 for (i=0; i < MONO_TABLE_NUM; ++i)
4271 meta->tables [i].rows = assembly->tables [i].rows;
4273 for (i = 0; i < MONO_TABLE_NUM; i++){
4274 if (meta->tables [i].rows == 0)
4276 valid_mask |= (guint64)1 << i;
4278 meta->tables [i].row_size = mono_metadata_compute_size (
4279 meta, i, &meta->tables [i].size_bitfield);
4280 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4282 heapt_size += 24; /* #~ header size */
4283 heapt_size += ntables * 4;
4284 /* make multiple of 4 */
4287 meta_size += heapt_size;
4288 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4289 p = (unsigned char*)meta->raw_metadata;
4290 /* the metadata signature */
4291 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4292 /* version numbers and 4 bytes reserved */
4293 int16val = (guint16*)p;
4294 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4295 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4297 /* version string */
4298 int32val = (guint32*)p;
4299 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4301 memcpy (p, meta->version, strlen (meta->version));
4302 p += GUINT32_FROM_LE (*int32val);
4303 align_pointer (meta->raw_metadata, p);
4304 int16val = (guint16*)p;
4305 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4306 *int16val = GUINT16_TO_LE (5); /* number of streams */
4310 * write the stream info.
4312 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4313 table_offset += 3; table_offset &= ~3;
4315 assembly->tstream.index = heapt_size;
4316 for (i = 0; i < 5; ++i) {
4317 int32val = (guint32*)p;
4318 stream_desc [i].stream->offset = table_offset;
4319 *int32val++ = GUINT32_TO_LE (table_offset);
4320 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4321 table_offset += GUINT32_FROM_LE (*int32val);
4322 table_offset += 3; table_offset &= ~3;
4324 strcpy ((char*)p, stream_desc [i].name);
4325 p += strlen (stream_desc [i].name) + 1;
4326 align_pointer (meta->raw_metadata, p);
4329 * now copy the data, the table stream header and contents goes first.
4331 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4332 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4333 int32val = (guint32*)p;
4334 *int32val = GUINT32_TO_LE (0); /* reserved */
4337 *p++ = 2; /* version */
4340 if (meta->idx_string_wide)
4342 if (meta->idx_guid_wide)
4344 if (meta->idx_blob_wide)
4347 *p++ = 1; /* reserved */
4348 int64val = (guint64*)p;
4349 *int64val++ = GUINT64_TO_LE (valid_mask);
4350 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4352 int32val = (guint32*)p;
4353 for (i = 0; i < MONO_TABLE_NUM; i++){
4354 if (meta->tables [i].rows == 0)
4356 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4358 p = (unsigned char*)int32val;
4360 /* sort the tables that still need sorting */
4361 table = &assembly->tables [MONO_TABLE_CONSTANT];
4363 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4364 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4366 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4367 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4369 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4370 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4372 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4373 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4375 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4376 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4377 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4379 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4380 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4382 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4384 /* compress the tables */
4385 for (i = 0; i < MONO_TABLE_NUM; i++){
4388 guint32 bitfield = meta->tables [i].size_bitfield;
4389 if (!meta->tables [i].rows)
4391 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4392 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4393 meta->tables [i].base = (char*)p;
4394 for (row = 1; row <= meta->tables [i].rows; ++row) {
4395 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4396 for (col = 0; col < assembly->tables [i].columns; ++col) {
4397 switch (mono_metadata_table_size (bitfield, col)) {
4399 *p++ = values [col];
4402 *p++ = values [col] & 0xff;
4403 *p++ = (values [col] >> 8) & 0xff;
4406 *p++ = values [col] & 0xff;
4407 *p++ = (values [col] >> 8) & 0xff;
4408 *p++ = (values [col] >> 16) & 0xff;
4409 *p++ = (values [col] >> 24) & 0xff;
4412 g_assert_not_reached ();
4416 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4419 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4420 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4421 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4422 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4423 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4425 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4429 * Some tables in metadata need to be sorted according to some criteria, but
4430 * when methods and fields are first created with reflection, they may be assigned a token
4431 * that doesn't correspond to the final token they will get assigned after the sorting.
4432 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4433 * with the reflection objects that represent them. Once all the tables are set up, the
4434 * reflection objects will contains the correct table index. fixup_method() will fixup the
4435 * tokens for the method with ILGenerator @ilgen.
4438 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4440 guint32 code_idx = GPOINTER_TO_UINT (value);
4441 MonoReflectionILTokenInfo *iltoken;
4442 MonoReflectionFieldBuilder *field;
4443 MonoReflectionCtorBuilder *ctor;
4444 MonoReflectionMethodBuilder *method;
4445 MonoReflectionTypeBuilder *tb;
4446 MonoReflectionArrayMethod *am;
4448 unsigned char *target;
4450 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4451 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4452 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4453 switch (target [3]) {
4454 case MONO_TABLE_FIELD:
4455 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4456 field = (MonoReflectionFieldBuilder *)iltoken->member;
4457 idx = field->table_idx;
4458 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4459 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4460 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4462 g_assert_not_reached ();
4465 case MONO_TABLE_METHOD:
4466 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4467 method = (MonoReflectionMethodBuilder *)iltoken->member;
4468 idx = method->table_idx;
4469 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4470 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4471 idx = ctor->table_idx;
4472 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4473 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4474 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4475 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4477 g_assert_not_reached ();
4480 case MONO_TABLE_TYPEDEF:
4481 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4482 g_assert_not_reached ();
4483 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4484 idx = tb->table_idx;
4486 case MONO_TABLE_MEMBERREF:
4487 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4488 am = (MonoReflectionArrayMethod*)iltoken->member;
4489 idx = am->table_idx;
4490 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4491 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4492 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4493 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4494 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4495 g_assert (m->klass->generic_class || m->klass->generic_container);
4497 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4499 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4500 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4501 g_assert (is_field_on_inst (f));
4503 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4504 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4506 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4508 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4510 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4513 g_assert_not_reached ();
4516 case MONO_TABLE_METHODSPEC:
4517 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4518 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4519 g_assert (mono_method_signature (m)->generic_param_count);
4521 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4523 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4526 g_assert_not_reached ();
4530 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4532 target [0] = idx & 0xff;
4533 target [1] = (idx >> 8) & 0xff;
4534 target [2] = (idx >> 16) & 0xff;
4541 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4542 * value is not known when the table is emitted.
4545 fixup_cattrs (MonoDynamicImage *assembly)
4547 MonoDynamicTable *table;
4549 guint32 type, i, idx, token;
4552 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4554 for (i = 0; i < table->rows; ++i) {
4555 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4557 type = values [MONO_CUSTOM_ATTR_TYPE];
4558 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4559 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4560 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4561 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4564 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4565 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4566 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4567 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4568 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4569 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4570 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4571 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4578 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4580 MonoDynamicTable *table;
4583 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4585 alloc_table (table, table->rows);
4586 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4587 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4588 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4589 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4590 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4595 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4597 MonoDynamicTable *table;
4601 char *b = blob_size;
4603 guint32 idx, offset;
4605 if (rsrc->filename) {
4606 name = mono_string_to_utf8 (rsrc->filename);
4607 sname = g_path_get_basename (name);
4609 table = &assembly->tables [MONO_TABLE_FILE];
4611 alloc_table (table, table->rows);
4612 values = table->values + table->next_idx * MONO_FILE_SIZE;
4613 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4614 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4617 mono_sha1_get_digest_from_file (name, hash);
4618 mono_metadata_encode_value (20, b, &b);
4619 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4620 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4622 idx = table->next_idx++;
4624 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4630 data = mono_array_addr (rsrc->data, char, 0);
4631 len = mono_array_length (rsrc->data);
4637 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4638 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4639 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4640 mono_image_add_stream_data (&assembly->resources, data, len);
4644 * The entry should be emitted into the MANIFESTRESOURCE table of
4645 * the main module, but that needs to reference the FILE table
4646 * which isn't emitted yet.
4653 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4657 set_version_from_string (MonoString *version, guint32 *values)
4659 gchar *ver, *p, *str;
4662 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4663 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4664 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4665 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4668 ver = str = mono_string_to_utf8 (version);
4669 for (i = 0; i < 4; ++i) {
4670 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4676 /* handle Revision and Build */
4686 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4690 char *b = blob_size;
4695 len = mono_array_length (pkey);
4696 mono_metadata_encode_value (len, b, &b);
4697 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4698 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4700 assembly->public_key = (guint8 *)g_malloc (len);
4701 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4702 assembly->public_key_len = len;
4704 /* Special case: check for ECMA key (16 bytes) */
4705 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4706 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4707 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4708 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4709 /* minimum key size (in 2.0) is 384 bits */
4710 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4712 /* FIXME - verifier */
4713 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4714 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4716 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4722 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4724 MonoDynamicTable *table;
4725 MonoDynamicImage *assembly;
4726 MonoReflectionAssemblyBuilder *assemblyb;
4730 guint32 module_index;
4732 assemblyb = moduleb->assemblyb;
4733 assembly = moduleb->dynamic_image;
4734 domain = mono_object_domain (assemblyb);
4736 /* Emit ASSEMBLY table */
4737 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4738 alloc_table (table, 1);
4739 values = table->values + MONO_ASSEMBLY_SIZE;
4740 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4741 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4742 if (assemblyb->culture) {
4743 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4745 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4747 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4748 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4749 set_version_from_string (assemblyb->version, values);
4751 /* Emit FILE + EXPORTED_TYPE table */
4753 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4755 MonoReflectionModuleBuilder *file_module =
4756 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4757 if (file_module != moduleb) {
4758 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4760 if (file_module->types) {
4761 for (j = 0; j < file_module->num_types; ++j) {
4762 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4763 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4768 if (assemblyb->loaded_modules) {
4769 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4770 MonoReflectionModule *file_module =
4771 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4772 mono_image_fill_file_table (domain, file_module, assembly);
4774 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4777 if (assemblyb->type_forwarders)
4778 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4780 /* Emit MANIFESTRESOURCE table */
4782 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4784 MonoReflectionModuleBuilder *file_module =
4785 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4786 /* The table for the main module is emitted later */
4787 if (file_module != moduleb) {
4789 if (file_module->resources) {
4790 int len = mono_array_length (file_module->resources);
4791 for (j = 0; j < len; ++j) {
4792 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4793 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4800 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4803 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4804 * for the modulebuilder @moduleb.
4805 * At the end of the process, method and field tokens are fixed up and the
4806 * on-disk compressed metadata representation is created.
4809 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4811 MonoDynamicTable *table;
4812 MonoDynamicImage *assembly;
4813 MonoReflectionAssemblyBuilder *assemblyb;
4819 assemblyb = moduleb->assemblyb;
4820 assembly = moduleb->dynamic_image;
4821 domain = mono_object_domain (assemblyb);
4823 if (assembly->text_rva)
4826 assembly->text_rva = START_TEXT_RVA;
4828 if (moduleb->is_main) {
4829 mono_image_emit_manifest (moduleb);
4832 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4833 table->rows = 1; /* .<Module> */
4835 alloc_table (table, table->rows);
4837 * Set the first entry.
4839 values = table->values + table->columns;
4840 values [MONO_TYPEDEF_FLAGS] = 0;
4841 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4842 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4843 values [MONO_TYPEDEF_EXTENDS] = 0;
4844 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4845 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4848 * handle global methods
4849 * FIXME: test what to do when global methods are defined in multiple modules.
4851 if (moduleb->global_methods) {
4852 table = &assembly->tables [MONO_TABLE_METHOD];
4853 table->rows += mono_array_length (moduleb->global_methods);
4854 alloc_table (table, table->rows);
4855 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4856 mono_image_get_method_info (
4857 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4859 if (moduleb->global_fields) {
4860 table = &assembly->tables [MONO_TABLE_FIELD];
4861 table->rows += mono_array_length (moduleb->global_fields);
4862 alloc_table (table, table->rows);
4863 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4864 mono_image_get_field_info (
4865 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4868 table = &assembly->tables [MONO_TABLE_MODULE];
4869 alloc_table (table, 1);
4870 mono_image_fill_module_table (domain, moduleb, assembly);
4872 /* Collect all types into a list sorted by their table_idx */
4873 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4876 for (i = 0; i < moduleb->num_types; ++i) {
4877 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4878 collect_types (&types, type);
4881 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4882 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4883 table->rows += mono_ptr_array_size (types);
4884 alloc_table (table, table->rows);
4887 * Emit type names + namespaces at one place inside the string heap,
4888 * so load_class_names () needs to touch fewer pages.
4890 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4891 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4892 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4894 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4895 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4896 string_heap_insert_mstring (&assembly->sheap, tb->name);
4899 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4900 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4901 mono_image_get_type_info (domain, type, assembly);
4905 * table->rows is already set above and in mono_image_fill_module_table.
4907 /* add all the custom attributes at the end, once all the indexes are stable */
4908 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4910 /* CAS assembly permissions */
4911 if (assemblyb->permissions_minimum)
4912 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4913 if (assemblyb->permissions_optional)
4914 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4915 if (assemblyb->permissions_refused)
4916 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4918 module_add_cattrs (assembly, moduleb);
4921 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4923 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4924 * the final tokens and don't need another fixup pass. */
4926 if (moduleb->global_methods) {
4927 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4928 MonoReflectionMethodBuilder *mb = mono_array_get (
4929 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4930 mono_image_add_methodimpl (assembly, mb);
4934 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4935 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4936 if (type->methods) {
4937 for (j = 0; j < type->num_methods; ++j) {
4938 MonoReflectionMethodBuilder *mb = mono_array_get (
4939 type->methods, MonoReflectionMethodBuilder*, j);
4941 mono_image_add_methodimpl (assembly, mb);
4946 mono_ptr_array_destroy (types);
4948 fixup_cattrs (assembly);
4951 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4954 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4956 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4959 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4963 guint32 import_lookup_table;
4967 guint32 import_address_table_rva;
4975 #ifndef DISABLE_REFLECTION_EMIT
4978 * mono_image_insert_string:
4979 * @module: module builder object
4982 * Insert @str into the user string stream of @module.
4985 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4987 MonoDynamicImage *assembly;
4992 if (!module->dynamic_image)
4993 mono_image_module_basic_init (module);
4995 assembly = module->dynamic_image;
4997 if (assembly->save) {
4998 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4999 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5000 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5002 char *swapped = g_malloc (2 * mono_string_length (str));
5003 const char *p = (const char*)mono_string_chars (str);
5005 swap_with_size (swapped, p, 2, mono_string_length (str));
5006 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5010 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5012 mono_image_add_stream_data (&assembly->us, "", 1);
5014 idx = assembly->us.index ++;
5017 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5019 return MONO_TOKEN_STRING | idx;
5023 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5027 MonoMethodSignature *sig;
5029 klass = obj->vtable->klass;
5030 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5031 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5032 MonoMethodSignature *old;
5033 guint32 sig_token, parent;
5036 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5038 nargs = mono_array_length (opt_param_types);
5039 old = mono_method_signature (method);
5040 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5042 sig->hasthis = old->hasthis;
5043 sig->explicit_this = old->explicit_this;
5044 sig->call_convention = old->call_convention;
5045 sig->generic_param_count = old->generic_param_count;
5046 sig->param_count = old->param_count + nargs;
5047 sig->sentinelpos = old->param_count;
5048 sig->ret = old->ret;
5050 for (i = 0; i < old->param_count; i++)
5051 sig->params [i] = old->params [i];
5053 for (i = 0; i < nargs; i++) {
5054 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5055 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5058 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5059 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5060 parent >>= MONO_TYPEDEFORREF_BITS;
5062 parent <<= MONO_MEMBERREF_PARENT_BITS;
5063 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5065 sig_token = method_encode_signature (assembly, sig);
5066 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5067 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5068 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5069 ReflectionMethodBuilder rmb;
5070 guint32 parent, sig_token;
5071 int nopt_args, nparams, ngparams, i;
5074 reflection_methodbuilder_from_method_builder (&rmb, mb);
5075 rmb.opt_types = opt_param_types;
5076 nopt_args = mono_array_length (opt_param_types);
5078 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5079 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5080 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5082 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5083 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5084 sig->call_convention = rmb.call_conv;
5085 sig->generic_param_count = ngparams;
5086 sig->param_count = nparams + nopt_args;
5087 sig->sentinelpos = nparams;
5088 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5090 for (i = 0; i < nparams; i++) {
5091 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5092 sig->params [i] = mono_reflection_type_get_handle (rt);
5095 for (i = 0; i < nopt_args; i++) {
5096 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5097 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5100 sig_token = method_builder_encode_signature (assembly, &rmb);
5102 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5103 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5105 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5106 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5108 name = mono_string_to_utf8 (rmb.name);
5109 token = mono_image_get_varargs_method_token (
5110 assembly, parent, name, sig_token);
5113 g_error ("requested method token for %s\n", klass->name);
5116 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5117 register_dyn_token (assembly, token, obj);
5122 * mono_image_create_token:
5123 * @assembly: a dynamic assembly
5125 * @register_token: Whenever to register the token in the assembly->tokens hash.
5127 * Get a token to insert in the IL code stream for the given MemberInfo.
5128 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5129 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5133 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5134 gboolean create_open_instance, gboolean register_token)
5139 klass = obj->vtable->klass;
5141 /* Check for user defined reflection objects */
5142 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5143 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5144 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5146 if (strcmp (klass->name, "MethodBuilder") == 0) {
5147 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5148 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5150 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5151 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5153 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5154 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5155 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5156 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5157 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5159 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5160 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5162 token = mono_image_get_ctorbuilder_token (assembly, mb);
5163 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5164 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5165 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5166 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5167 if (tb->generic_params) {
5168 token = mono_image_get_generic_field_token (assembly, fb);
5170 if (tb->module->dynamic_image == assembly) {
5171 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5173 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5176 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5177 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5178 if (create_open_instance && tb->generic_params) {
5180 init_type_builder_generics (obj);
5181 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5182 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5183 token = mono_metadata_token_from_dor (token);
5184 } else if (tb->module->dynamic_image == assembly) {
5185 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5188 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5191 } else if (strcmp (klass->name, "MonoType") == 0) {
5192 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5193 MonoClass *mc = mono_class_from_mono_type (type);
5194 token = mono_metadata_token_from_dor (
5195 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5196 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5197 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5198 token = mono_metadata_token_from_dor (
5199 mono_image_typedef_or_ref (assembly, type));
5200 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5201 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5202 token = mono_metadata_token_from_dor (
5203 mono_image_typedef_or_ref (assembly, type));
5204 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5205 strcmp (klass->name, "MonoMethod") == 0 ||
5206 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5207 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5208 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5209 if (m->method->is_inflated) {
5210 if (create_open_instance)
5211 token = mono_image_get_methodspec_token (assembly, m->method);
5213 token = mono_image_get_inflated_method_token (assembly, m->method);
5214 } else if ((m->method->klass->image == &assembly->image) &&
5215 !m->method->klass->generic_class) {
5216 static guint32 method_table_idx = 0xffffff;
5217 if (m->method->klass->wastypebuilder) {
5218 /* we use the same token as the one that was assigned
5219 * to the Methodbuilder.
5220 * FIXME: do the equivalent for Fields.
5222 token = m->method->token;
5225 * Each token should have a unique index, but the indexes are
5226 * assigned by managed code, so we don't know about them. An
5227 * easy solution is to count backwards...
5229 method_table_idx --;
5230 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5233 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5235 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5236 } else if (strcmp (klass->name, "MonoField") == 0) {
5237 MonoReflectionField *f = (MonoReflectionField *)obj;
5238 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5239 static guint32 field_table_idx = 0xffffff;
5241 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5243 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5245 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5246 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5247 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5248 token = mono_image_get_array_token (assembly, m);
5249 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5250 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5251 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5252 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5253 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5254 token = mono_metadata_token_from_dor (
5255 mono_image_typedef_or_ref (assembly, type));
5256 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5257 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5258 token = mono_image_get_field_on_inst_token (assembly, f);
5259 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5260 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5261 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5262 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5263 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5264 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5265 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5266 MonoReflectionType *type = (MonoReflectionType *)obj;
5267 token = mono_metadata_token_from_dor (
5268 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5270 g_error ("requested token for %s\n", klass->name);
5274 mono_image_register_token (assembly, token, obj);
5280 * mono_image_register_token:
5282 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5283 * the Module.ResolveXXXToken () methods to work.
5286 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5290 dynamic_image_lock (assembly);
5291 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5293 /* There could be multiple MethodInfo objects with the same token */
5294 //g_assert (prev == obj);
5296 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5298 dynamic_image_unlock (assembly);
5301 static MonoDynamicImage*
5302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5304 static const guchar entrycode [16] = {0xff, 0x25, 0};
5305 MonoDynamicImage *image;
5308 const char *version;
5310 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5311 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5313 version = mono_get_runtime_info ()->runtime_version;
5316 /* The MonoGHashTable's need GC tracking */
5317 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5319 image = g_new0 (MonoDynamicImage, 1);
5322 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5324 /*g_print ("created image %p\n", image);*/
5325 /* keep in sync with image.c */
5326 image->image.name = assembly_name;
5327 image->image.assembly_name = image->image.name; /* they may be different */
5328 image->image.module_name = module_name;
5329 image->image.version = g_strdup (version);
5330 image->image.md_version_major = 1;
5331 image->image.md_version_minor = 1;
5332 image->image.dynamic = TRUE;
5334 image->image.references = g_new0 (MonoAssembly*, 1);
5335 image->image.references [0] = NULL;
5337 mono_image_init (&image->image);
5339 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");
5340 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5341 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5342 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5343 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5344 image->handleref = g_hash_table_new (NULL, NULL);
5345 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");
5346 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5347 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");
5348 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");
5349 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5350 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5351 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5352 image->gen_params = g_ptr_array_new ();
5353 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5355 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5356 string_heap_init (&image->sheap);
5357 mono_image_add_stream_data (&image->us, "", 1);
5358 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5359 /* import tables... */
5360 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5361 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5362 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5363 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5364 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5365 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5366 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5367 stream_data_align (&image->code);
5369 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5371 for (i=0; i < MONO_TABLE_NUM; ++i) {
5372 image->tables [i].next_idx = 1;
5373 image->tables [i].columns = table_sizes [i];
5376 image->image.assembly = (MonoAssembly*)assembly;
5377 image->run = assembly->run;
5378 image->save = assembly->save;
5379 image->pe_kind = 0x1; /* ILOnly */
5380 image->machine = 0x14c; /* I386 */
5382 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5384 dynamic_images_lock ();
5386 if (!dynamic_images)
5387 dynamic_images = g_ptr_array_new ();
5389 g_ptr_array_add (dynamic_images, image);
5391 dynamic_images_unlock ();
5398 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5404 release_hashtable (MonoGHashTable **hash)
5407 mono_g_hash_table_destroy (*hash);
5413 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5415 release_hashtable (&image->token_fixups);
5416 release_hashtable (&image->handleref_managed);
5417 release_hashtable (&image->tokens);
5418 release_hashtable (&image->remapped_tokens);
5419 release_hashtable (&image->generic_def_objects);
5420 release_hashtable (&image->methodspec);
5423 // Free dynamic image pass one: Free resources but not image itself
5425 mono_dynamic_image_free (MonoDynamicImage *image)
5427 MonoDynamicImage *di = image;
5432 mono_g_hash_table_destroy (di->methodspec);
5434 g_hash_table_destroy (di->typespec);
5436 g_hash_table_destroy (di->typeref);
5438 g_hash_table_destroy (di->handleref);
5439 if (di->handleref_managed)
5440 mono_g_hash_table_destroy (di->handleref_managed);
5442 mono_g_hash_table_destroy (di->tokens);
5443 if (di->remapped_tokens)
5444 mono_g_hash_table_destroy (di->remapped_tokens);
5445 if (di->generic_def_objects)
5446 mono_g_hash_table_destroy (di->generic_def_objects);
5447 if (di->blob_cache) {
5448 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5449 g_hash_table_destroy (di->blob_cache);
5451 if (di->standalonesig_cache)
5452 g_hash_table_destroy (di->standalonesig_cache);
5453 for (list = di->array_methods; list; list = list->next) {
5454 ArrayMethod *am = (ArrayMethod *)list->data;
5459 g_list_free (di->array_methods);
5460 if (di->gen_params) {
5461 for (i = 0; i < di->gen_params->len; i++) {
5462 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5463 mono_gc_deregister_root ((char*) &entry->gparam);
5466 g_ptr_array_free (di->gen_params, TRUE);
5468 if (di->token_fixups)
5469 mono_g_hash_table_destroy (di->token_fixups);
5470 if (di->method_to_table_idx)
5471 g_hash_table_destroy (di->method_to_table_idx);
5472 if (di->field_to_table_idx)
5473 g_hash_table_destroy (di->field_to_table_idx);
5474 if (di->method_aux_hash)
5475 g_hash_table_destroy (di->method_aux_hash);
5476 if (di->vararg_aux_hash)
5477 g_hash_table_destroy (di->vararg_aux_hash);
5478 g_free (di->strong_name);
5479 g_free (di->win32_res);
5481 g_free (di->public_key);
5483 /*g_print ("string heap destroy for image %p\n", di);*/
5484 mono_dynamic_stream_reset (&di->sheap);
5485 mono_dynamic_stream_reset (&di->code);
5486 mono_dynamic_stream_reset (&di->resources);
5487 mono_dynamic_stream_reset (&di->us);
5488 mono_dynamic_stream_reset (&di->blob);
5489 mono_dynamic_stream_reset (&di->tstream);
5490 mono_dynamic_stream_reset (&di->guid);
5491 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5492 g_free (di->tables [i].values);
5495 dynamic_images_lock ();
5498 g_ptr_array_remove (dynamic_images, di);
5500 dynamic_images_unlock ();
5503 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5505 mono_dynamic_image_free_image (MonoDynamicImage *image)
5507 /* See create_dynamic_mono_image () */
5509 /* Allocated using GC_MALLOC */
5515 #ifndef DISABLE_REFLECTION_EMIT
5518 * mono_image_basic_init:
5519 * @assembly: an assembly builder object
5521 * Create the MonoImage that represents the assembly builder and setup some
5522 * of the helper hash table and the basic metadata streams.
5525 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5527 MonoDynamicAssembly *assembly;
5528 MonoDynamicImage *image;
5529 MonoDomain *domain = mono_object_domain (assemblyb);
5531 if (assemblyb->dynamic_assembly)
5535 /* assembly->assembly.image might be GC allocated */
5536 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5538 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5541 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5543 assembly->assembly.ref_count = 1;
5544 assembly->assembly.dynamic = TRUE;
5545 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5546 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5547 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5548 if (assemblyb->culture)
5549 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5551 assembly->assembly.aname.culture = g_strdup ("");
5553 if (assemblyb->version) {
5554 char *vstr = mono_string_to_utf8 (assemblyb->version);
5555 char **version = g_strsplit (vstr, ".", 4);
5556 char **parts = version;
5557 assembly->assembly.aname.major = atoi (*parts++);
5558 assembly->assembly.aname.minor = atoi (*parts++);
5559 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5560 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5562 g_strfreev (version);
5565 assembly->assembly.aname.major = 0;
5566 assembly->assembly.aname.minor = 0;
5567 assembly->assembly.aname.build = 0;
5568 assembly->assembly.aname.revision = 0;
5571 assembly->run = assemblyb->access != 2;
5572 assembly->save = assemblyb->access != 1;
5573 assembly->domain = domain;
5575 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5576 image->initial_image = TRUE;
5577 assembly->assembly.aname.name = image->image.name;
5578 assembly->assembly.image = &image->image;
5579 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5580 /* -1 to correct for the trailing NULL byte */
5581 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5582 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5584 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5587 mono_domain_assemblies_lock (domain);
5588 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5589 mono_domain_assemblies_unlock (domain);
5591 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5593 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5595 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5598 #endif /* !DISABLE_REFLECTION_EMIT */
5600 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5603 calc_section_size (MonoDynamicImage *assembly)
5607 /* alignment constraints */
5608 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5609 g_assert ((assembly->code.index % 4) == 0);
5610 assembly->meta_size += 3;
5611 assembly->meta_size &= ~3;
5612 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5613 g_assert ((assembly->resources.index % 4) == 0);
5615 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5616 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5619 if (assembly->win32_res) {
5620 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5622 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5623 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5627 assembly->sections [MONO_SECTION_RELOC].size = 12;
5628 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5638 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5642 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5644 ResTreeNode *t1 = (ResTreeNode*)a;
5645 ResTreeNode *t2 = (ResTreeNode*)b;
5647 return t1->id - t2->id;
5651 * resource_tree_create:
5653 * Organize the resources into a resource tree.
5655 static ResTreeNode *
5656 resource_tree_create (MonoArray *win32_resources)
5658 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5662 tree = g_new0 (ResTreeNode, 1);
5664 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5665 MonoReflectionWin32Resource *win32_res =
5666 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5670 /* FIXME: BUG: this stores managed references in unmanaged memory */
5671 lang_node = g_new0 (ResTreeNode, 1);
5672 lang_node->id = win32_res->lang_id;
5673 lang_node->win32_res = win32_res;
5675 /* Create type node if neccesary */
5677 for (l = tree->children; l; l = l->next)
5678 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5679 type_node = (ResTreeNode*)l->data;
5684 type_node = g_new0 (ResTreeNode, 1);
5685 type_node->id = win32_res->res_type;
5688 * The resource types have to be sorted otherwise
5689 * Windows Explorer can't display the version information.
5691 tree->children = g_slist_insert_sorted (tree->children,
5692 type_node, resource_tree_compare_by_id);
5695 /* Create res node if neccesary */
5697 for (l = type_node->children; l; l = l->next)
5698 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5699 res_node = (ResTreeNode*)l->data;
5704 res_node = g_new0 (ResTreeNode, 1);
5705 res_node->id = win32_res->res_id;
5706 type_node->children = g_slist_append (type_node->children, res_node);
5709 res_node->children = g_slist_append (res_node->children, lang_node);
5716 * resource_tree_encode:
5718 * Encode the resource tree into the format used in the PE file.
5721 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5724 MonoPEResourceDir dir;
5725 MonoPEResourceDirEntry dir_entry;
5726 MonoPEResourceDataEntry data_entry;
5728 guint32 res_id_entries;
5731 * For the format of the resource directory, see the article
5732 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5736 memset (&dir, 0, sizeof (dir));
5737 memset (&dir_entry, 0, sizeof (dir_entry));
5738 memset (&data_entry, 0, sizeof (data_entry));
5740 g_assert (sizeof (dir) == 16);
5741 g_assert (sizeof (dir_entry) == 8);
5742 g_assert (sizeof (data_entry) == 16);
5744 node->offset = p - begin;
5746 /* IMAGE_RESOURCE_DIRECTORY */
5747 res_id_entries = g_slist_length (node->children);
5748 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5750 memcpy (p, &dir, sizeof (dir));
5753 /* Reserve space for entries */
5755 p += sizeof (dir_entry) * res_id_entries;
5757 /* Write children */
5758 for (l = node->children; l; l = l->next) {
5759 ResTreeNode *child = (ResTreeNode*)l->data;
5761 if (child->win32_res) {
5764 child->offset = p - begin;
5766 /* IMAGE_RESOURCE_DATA_ENTRY */
5767 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5768 size = mono_array_length (child->win32_res->res_data);
5769 data_entry.rde_size = GUINT32_TO_LE (size);
5771 memcpy (p, &data_entry, sizeof (data_entry));
5772 p += sizeof (data_entry);
5774 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5777 resource_tree_encode (child, begin, p, &p);
5781 /* IMAGE_RESOURCE_ENTRY */
5782 for (l = node->children; l; l = l->next) {
5783 ResTreeNode *child = (ResTreeNode*)l->data;
5785 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5786 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5788 memcpy (entries, &dir_entry, sizeof (dir_entry));
5789 entries += sizeof (dir_entry);
5796 resource_tree_free (ResTreeNode * node)
5799 for (list = node->children; list; list = list->next)
5800 resource_tree_free ((ResTreeNode*)list->data);
5801 g_slist_free(node->children);
5806 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5811 MonoReflectionWin32Resource *win32_res;
5814 if (!assemblyb->win32_resources)
5818 * Resources are stored in a three level tree inside the PE file.
5819 * - level one contains a node for each type of resource
5820 * - level two contains a node for each resource
5821 * - level three contains a node for each instance of a resource for a
5822 * specific language.
5825 tree = resource_tree_create (assemblyb->win32_resources);
5827 /* Estimate the size of the encoded tree */
5829 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5830 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5831 size += mono_array_length (win32_res->res_data);
5833 /* Directory structure */
5834 size += mono_array_length (assemblyb->win32_resources) * 256;
5835 p = buf = (char *)g_malloc (size);
5837 resource_tree_encode (tree, p, p, &p);
5839 g_assert (p - buf <= size);
5841 assembly->win32_res = (char *)g_malloc (p - buf);
5842 assembly->win32_res_size = p - buf;
5843 memcpy (assembly->win32_res, buf, p - buf);
5846 resource_tree_free (tree);
5850 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5852 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5855 p += sizeof (MonoPEResourceDir);
5856 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5857 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5858 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5859 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5860 fixup_resource_directory (res_section, child, rva);
5862 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5863 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5866 p += sizeof (MonoPEResourceDirEntry);
5871 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5874 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5875 g_error ("WriteFile returned %d\n", GetLastError ());
5879 * mono_image_create_pefile:
5880 * @mb: a module builder object
5882 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5883 * assembly->pefile where it can be easily retrieved later in chunks.
5886 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5888 MonoMSDOSHeader *msdos;
5889 MonoDotNetHeader *header;
5890 MonoSectionTable *section;
5891 MonoCLIHeader *cli_header;
5892 guint32 size, image_size, virtual_base, text_offset;
5893 guint32 header_start, section_start, file_offset, virtual_offset;
5894 MonoDynamicImage *assembly;
5895 MonoReflectionAssemblyBuilder *assemblyb;
5896 MonoDynamicStream pefile_stream = {0};
5897 MonoDynamicStream *pefile = &pefile_stream;
5899 guint32 *rva, value;
5901 static const unsigned char msheader[] = {
5902 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5903 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5906 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5907 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5908 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5909 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5912 assemblyb = mb->assemblyb;
5914 mono_image_basic_init (assemblyb);
5915 assembly = mb->dynamic_image;
5917 assembly->pe_kind = assemblyb->pe_kind;
5918 assembly->machine = assemblyb->machine;
5919 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5920 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5922 mono_image_build_metadata (mb);
5924 if (mb->is_main && assemblyb->resources) {
5925 int len = mono_array_length (assemblyb->resources);
5926 for (i = 0; i < len; ++i)
5927 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5930 if (mb->resources) {
5931 int len = mono_array_length (mb->resources);
5932 for (i = 0; i < len; ++i)
5933 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5936 build_compressed_metadata (assembly);
5939 assembly_add_win32_resources (assembly, assemblyb);
5941 nsections = calc_section_size (assembly);
5943 /* The DOS header and stub */
5944 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5945 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5947 /* the dotnet header */
5948 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5950 /* the section tables */
5951 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5953 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5954 virtual_offset = VIRT_ALIGN;
5957 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5958 if (!assembly->sections [i].size)
5961 file_offset += FILE_ALIGN - 1;
5962 file_offset &= ~(FILE_ALIGN - 1);
5963 virtual_offset += VIRT_ALIGN - 1;
5964 virtual_offset &= ~(VIRT_ALIGN - 1);
5966 assembly->sections [i].offset = file_offset;
5967 assembly->sections [i].rva = virtual_offset;
5969 file_offset += assembly->sections [i].size;
5970 virtual_offset += assembly->sections [i].size;
5971 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5974 file_offset += FILE_ALIGN - 1;
5975 file_offset &= ~(FILE_ALIGN - 1);
5977 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5979 /* back-patch info */
5980 msdos = (MonoMSDOSHeader*)pefile->data;
5981 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5983 header = (MonoDotNetHeader*)(pefile->data + header_start);
5984 header->pesig [0] = 'P';
5985 header->pesig [1] = 'E';
5987 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5988 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5989 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5990 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5991 if (assemblyb->pekind == 1) {
5993 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5996 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5999 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6001 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6002 header->pe.pe_major = 6;
6003 header->pe.pe_minor = 0;
6004 size = assembly->sections [MONO_SECTION_TEXT].size;
6005 size += FILE_ALIGN - 1;
6006 size &= ~(FILE_ALIGN - 1);
6007 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6008 size = assembly->sections [MONO_SECTION_RSRC].size;
6009 size += FILE_ALIGN - 1;
6010 size &= ~(FILE_ALIGN - 1);
6011 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6012 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6013 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6014 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6015 /* pe_rva_entry_point always at the beginning of the text section */
6016 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6018 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6019 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6020 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6021 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6022 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6023 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6024 size = section_start;
6025 size += FILE_ALIGN - 1;
6026 size &= ~(FILE_ALIGN - 1);
6027 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6029 size += VIRT_ALIGN - 1;
6030 size &= ~(VIRT_ALIGN - 1);
6031 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6034 // Translate the PEFileKind value to the value expected by the Windows loader
6040 // PEFileKinds.Dll == 1
6041 // PEFileKinds.ConsoleApplication == 2
6042 // PEFileKinds.WindowApplication == 3
6045 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6046 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6048 if (assemblyb->pekind == 3)
6053 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6055 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6056 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6057 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6058 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6059 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6060 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6062 /* fill data directory entries */
6064 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6065 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6067 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6068 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6070 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6071 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6072 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6073 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6074 /* patch entrypoint name */
6075 if (assemblyb->pekind == 1)
6076 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6078 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6079 /* patch imported function RVA name */
6080 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6081 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6083 /* the import table */
6084 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6085 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6086 /* patch imported dll RVA name and other entries in the dir */
6087 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6088 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6089 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6090 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6091 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6092 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6094 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6095 value = (assembly->text_rva + assembly->imp_names_offset);
6096 *p++ = (value) & 0xff;
6097 *p++ = (value >> 8) & (0xff);
6098 *p++ = (value >> 16) & (0xff);
6099 *p++ = (value >> 24) & (0xff);
6101 /* the CLI header info */
6102 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6103 cli_header->ch_size = GUINT32_FROM_LE (72);
6104 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6105 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6106 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6107 if (assemblyb->entry_point) {
6108 guint32 table_idx = 0;
6109 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6110 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6111 table_idx = methodb->table_idx;
6113 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6115 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6117 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6119 /* The embedded managed resources */
6120 text_offset = assembly->text_rva + assembly->code.index;
6121 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6122 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6123 text_offset += assembly->resources.index;
6124 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6125 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6126 text_offset += assembly->meta_size;
6127 if (assembly->strong_name_size) {
6128 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6129 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6130 text_offset += assembly->strong_name_size;
6133 /* write the section tables and section content */
6134 section = (MonoSectionTable*)(pefile->data + section_start);
6135 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6136 static const char section_names [][7] = {
6137 ".text", ".rsrc", ".reloc"
6139 if (!assembly->sections [i].size)
6141 strcpy (section->st_name, section_names [i]);
6142 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6143 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6144 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6145 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6146 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6147 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6148 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6152 checked_write_file (file, pefile->data, pefile->index);
6154 mono_dynamic_stream_reset (pefile);
6156 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6157 if (!assembly->sections [i].size)
6160 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6161 g_error ("SetFilePointer returned %d\n", GetLastError ());
6164 case MONO_SECTION_TEXT:
6165 /* patch entry point */
6166 p = (guchar*)(assembly->code.data + 2);
6167 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6168 *p++ = (value) & 0xff;
6169 *p++ = (value >> 8) & 0xff;
6170 *p++ = (value >> 16) & 0xff;
6171 *p++ = (value >> 24) & 0xff;
6173 checked_write_file (file, assembly->code.data, assembly->code.index);
6174 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6175 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6176 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6179 g_free (assembly->image.raw_metadata);
6181 case MONO_SECTION_RELOC: {
6185 guint16 type_and_offset;
6189 g_assert (sizeof (reloc) == 12);
6191 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6192 reloc.block_size = GUINT32_FROM_LE (12);
6195 * the entrypoint is always at the start of the text section
6196 * 3 is IMAGE_REL_BASED_HIGHLOW
6197 * 2 is patch_size_rva - text_rva
6199 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6202 checked_write_file (file, &reloc, sizeof (reloc));
6206 case MONO_SECTION_RSRC:
6207 if (assembly->win32_res) {
6209 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6210 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6211 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6215 g_assert_not_reached ();
6219 /* check that the file is properly padded */
6220 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6221 g_error ("SetFilePointer returned %d\n", GetLastError ());
6222 if (! SetEndOfFile (file))
6223 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6225 mono_dynamic_stream_reset (&assembly->code);
6226 mono_dynamic_stream_reset (&assembly->us);
6227 mono_dynamic_stream_reset (&assembly->blob);
6228 mono_dynamic_stream_reset (&assembly->guid);
6229 mono_dynamic_stream_reset (&assembly->sheap);
6231 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6232 g_hash_table_destroy (assembly->blob_cache);
6233 assembly->blob_cache = NULL;
6236 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6239 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6241 g_assert_not_reached ();
6244 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6246 #ifndef DISABLE_REFLECTION_EMIT
6248 MonoReflectionModule *
6249 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6253 MonoImageOpenStatus status;
6254 MonoDynamicAssembly *assembly;
6255 guint32 module_count;
6256 MonoImage **new_modules;
6257 gboolean *new_modules_loaded;
6259 name = mono_string_to_utf8 (fileName);
6261 image = mono_image_open (name, &status);
6264 if (status == MONO_IMAGE_ERROR_ERRNO)
6265 exc = mono_get_exception_file_not_found (fileName);
6267 exc = mono_get_exception_bad_image_format (name);
6269 mono_raise_exception (exc);
6274 assembly = ab->dynamic_assembly;
6275 image->assembly = (MonoAssembly*)assembly;
6277 module_count = image->assembly->image->module_count;
6278 new_modules = g_new0 (MonoImage *, module_count + 1);
6279 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6281 if (image->assembly->image->modules)
6282 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6283 if (image->assembly->image->modules_loaded)
6284 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6285 new_modules [module_count] = image;
6286 new_modules_loaded [module_count] = TRUE;
6287 mono_image_addref (image);
6289 g_free (image->assembly->image->modules);
6290 image->assembly->image->modules = new_modules;
6291 image->assembly->image->modules_loaded = new_modules_loaded;
6292 image->assembly->image->module_count ++;
6294 mono_assembly_load_references (image, &status);
6296 mono_image_close (image);
6297 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6300 return mono_module_get_object (mono_domain_get (), image);
6303 #endif /* DISABLE_REFLECTION_EMIT */
6306 * We need to return always the same object for MethodInfo, FieldInfo etc..
6307 * but we need to consider the reflected type.
6308 * type uses a different hash, since it uses custom hash/equal functions.
6313 MonoClass *refclass;
6317 reflected_equal (gconstpointer a, gconstpointer b) {
6318 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6319 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6321 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6325 reflected_hash (gconstpointer a) {
6326 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6327 return mono_aligned_addr_hash (ea->item);
6330 #define CHECK_OBJECT(t,p,k) \
6336 mono_domain_lock (domain); \
6337 if (!domain->refobject_hash) \
6338 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"); \
6339 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6340 mono_domain_unlock (domain); \
6343 mono_domain_unlock (domain); \
6346 #ifdef HAVE_BOEHM_GC
6347 /* ReflectedEntry doesn't need to be GC tracked */
6348 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6349 #define FREE_REFENTRY(entry) g_free ((entry))
6350 #define REFENTRY_REQUIRES_CLEANUP
6352 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6354 #define FREE_REFENTRY(entry)
6357 #define CACHE_OBJECT(t,p,o,k) \
6360 ReflectedEntry pe; \
6362 pe.refclass = (k); \
6363 mono_domain_lock (domain); \
6364 if (!domain->refobject_hash) \
6365 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"); \
6366 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6368 ReflectedEntry *e = ALLOC_REFENTRY; \
6370 e->refclass = (k); \
6371 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6374 mono_domain_unlock (domain); \
6379 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6381 mono_domain_lock (domain);
6382 if (domain->refobject_hash) {
6384 gpointer orig_pe, orig_value;
6387 pe.refclass = klass;
6388 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6389 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6390 FREE_REFENTRY (orig_pe);
6393 mono_domain_unlock (domain);
6396 #ifdef REFENTRY_REQUIRES_CLEANUP
6398 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6400 FREE_REFENTRY (key);
6405 mono_reflection_cleanup_domain (MonoDomain *domain)
6407 if (domain->refobject_hash) {
6408 /*let's avoid scanning the whole hashtable if not needed*/
6409 #ifdef REFENTRY_REQUIRES_CLEANUP
6410 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6412 mono_g_hash_table_destroy (domain->refobject_hash);
6413 domain->refobject_hash = NULL;
6417 #ifndef DISABLE_REFLECTION_EMIT
6419 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6421 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6425 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6427 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6431 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6433 MonoDynamicImage *image = moduleb->dynamic_image;
6434 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6438 MonoImage **new_modules;
6440 char *name, *fqname;
6442 * FIXME: we already created an image in mono_image_basic_init (), but
6443 * we don't know which module it belongs to, since that is only
6444 * determined at assembly save time.
6446 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6447 name = mono_string_to_utf8 (ab->name);
6448 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6449 if (!mono_error_ok (&error)) {
6451 mono_error_raise_exception (&error);
6453 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6455 moduleb->module.image = &image->image;
6456 moduleb->dynamic_image = image;
6457 register_module (mono_object_domain (moduleb), moduleb, image);
6459 /* register the module with the assembly */
6460 ass = ab->dynamic_assembly->assembly.image;
6461 module_count = ass->module_count;
6462 new_modules = g_new0 (MonoImage *, module_count + 1);
6465 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6466 new_modules [module_count] = &image->image;
6467 mono_image_addref (&image->image);
6469 g_free (ass->modules);
6470 ass->modules = new_modules;
6471 ass->module_count ++;
6476 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6478 MonoDynamicImage *image = moduleb->dynamic_image;
6480 g_assert (type->type);
6481 image->wrappers_type = mono_class_from_mono_type (type->type);
6487 * mono_assembly_get_object:
6488 * @domain: an app domain
6489 * @assembly: an assembly
6491 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6493 MonoReflectionAssembly*
6494 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6496 static MonoClass *assembly_type;
6497 MonoReflectionAssembly *res;
6499 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6500 if (!assembly_type) {
6501 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6503 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6505 assembly_type = klass;
6507 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6508 res->assembly = assembly;
6510 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6515 MonoReflectionModule*
6516 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6518 static MonoClass *module_type;
6519 MonoReflectionModule *res;
6522 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6524 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6526 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6528 module_type = klass;
6530 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6533 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6535 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6536 basename = g_path_get_basename (image->name);
6537 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6538 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6542 if (image->assembly->image == image) {
6543 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6547 if (image->assembly->image->modules) {
6548 for (i = 0; i < image->assembly->image->module_count; i++) {
6549 if (image->assembly->image->modules [i] == image)
6550 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6552 g_assert (res->token);
6556 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6559 MonoReflectionModule*
6560 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6562 static MonoClass *module_type;
6563 MonoReflectionModule *res;
6564 MonoTableInfo *table;
6565 guint32 cols [MONO_FILE_SIZE];
6567 guint32 i, name_idx;
6571 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6573 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6575 module_type = klass;
6577 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6579 table = &image->tables [MONO_TABLE_FILE];
6580 g_assert (table_index < table->rows);
6581 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6584 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6585 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6587 /* Check whenever the row has a corresponding row in the moduleref table */
6588 table = &image->tables [MONO_TABLE_MODULEREF];
6589 for (i = 0; i < table->rows; ++i) {
6590 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6591 val = mono_metadata_string_heap (image, name_idx);
6592 if (strcmp (val, name) == 0)
6593 res->image = image->modules [i];
6596 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6597 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6598 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6599 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6600 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6606 verify_safe_for_managed_space (MonoType *type)
6608 switch (type->type) {
6610 case MONO_TYPE_ARRAY:
6611 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6613 return verify_safe_for_managed_space (type->data.type);
6614 case MONO_TYPE_SZARRAY:
6615 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6616 case MONO_TYPE_GENERICINST: {
6617 MonoGenericInst *inst = type->data.generic_class->inst;
6621 for (i = 0; i < inst->type_argc; ++i)
6622 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6628 case MONO_TYPE_MVAR:
6636 mono_type_normalize (MonoType *type)
6639 MonoGenericClass *gclass;
6640 MonoGenericInst *ginst;
6642 MonoGenericContainer *gcontainer;
6643 MonoType **argv = NULL;
6644 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6646 if (type->type != MONO_TYPE_GENERICINST)
6649 gclass = type->data.generic_class;
6650 ginst = gclass->context.class_inst;
6651 if (!ginst->is_open)
6654 gtd = gclass->container_class;
6655 gcontainer = gtd->generic_container;
6656 argv = g_newa (MonoType*, ginst->type_argc);
6658 for (i = 0; i < ginst->type_argc; ++i) {
6659 MonoType *t = ginst->type_argv [i], *norm;
6660 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6661 is_denorm_gtd = FALSE;
6662 norm = mono_type_normalize (t);
6665 requires_rebind = TRUE;
6669 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6671 if (requires_rebind) {
6672 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6673 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6679 * mono_type_get_object:
6680 * @domain: an app domain
6683 * Return an System.MonoType object representing the type @type.
6686 mono_type_get_object (MonoDomain *domain, MonoType *type)
6689 MonoType *norm_type;
6690 MonoReflectionType *res;
6691 MonoClass *klass = mono_class_from_mono_type (type);
6693 /*we must avoid using @type as it might have come
6694 * from a mono_metadata_type_dup and the caller
6695 * expects that is can be freed.
6696 * Using the right type from
6698 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6700 /* void is very common */
6701 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6702 return (MonoReflectionType*)domain->typeof_void;
6705 * If the vtable of the given class was already created, we can use
6706 * the MonoType from there and avoid all locking and hash table lookups.
6708 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6709 * that the resulting object is different.
6711 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6712 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6713 if (vtable && vtable->type)
6714 return (MonoReflectionType *)vtable->type;
6717 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6718 mono_domain_lock (domain);
6719 if (!domain->type_hash)
6720 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6721 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6722 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6723 mono_domain_unlock (domain);
6724 mono_loader_unlock ();
6728 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6729 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6730 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6731 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6732 * artifact of how generics are encoded and should be transparent to managed code so we
6733 * need to weed out this diference when retrieving managed System.Type objects.
6735 norm_type = mono_type_normalize (type);
6736 if (norm_type != type) {
6737 res = mono_type_get_object (domain, norm_type);
6738 mono_g_hash_table_insert (domain->type_hash, type, res);
6739 mono_domain_unlock (domain);
6740 mono_loader_unlock ();
6744 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6745 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6748 if (!verify_safe_for_managed_space (type)) {
6749 mono_domain_unlock (domain);
6750 mono_loader_unlock ();
6751 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6754 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6755 gboolean is_type_done = TRUE;
6756 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6757 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6758 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6760 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6761 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6763 if (gparam->owner && gparam->owner->is_method) {
6764 MonoMethod *method = gparam->owner->owner.method;
6765 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6766 is_type_done = FALSE;
6767 } else if (gparam->owner && !gparam->owner->is_method) {
6768 MonoClass *klass = gparam->owner->owner.klass;
6769 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6770 is_type_done = FALSE;
6774 /* g_assert_not_reached (); */
6775 /* should this be considered an error condition? */
6776 if (is_type_done && !type->byref) {
6777 mono_domain_unlock (domain);
6778 mono_loader_unlock ();
6779 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6782 /* This is stored in vtables/JITted code so it has to be pinned */
6783 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, &error);
6784 mono_error_raise_exception (&error);
6786 mono_g_hash_table_insert (domain->type_hash, type, res);
6788 if (type->type == MONO_TYPE_VOID)
6789 domain->typeof_void = (MonoObject*)res;
6791 mono_domain_unlock (domain);
6792 mono_loader_unlock ();
6797 * mono_method_get_object:
6798 * @domain: an app domain
6800 * @refclass: the reflected type (can be NULL)
6802 * Return an System.Reflection.MonoMethod object representing the method @method.
6804 MonoReflectionMethod*
6805 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6808 * We use the same C representation for methods and constructors, but the type
6809 * name in C# is different.
6811 static MonoClass *System_Reflection_MonoMethod = NULL;
6812 static MonoClass *System_Reflection_MonoCMethod = NULL;
6813 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6814 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6816 MonoReflectionMethod *ret;
6818 if (method->is_inflated) {
6819 MonoReflectionGenericMethod *gret;
6822 refclass = method->klass;
6823 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6824 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6825 if (!System_Reflection_MonoGenericCMethod)
6826 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6827 klass = System_Reflection_MonoGenericCMethod;
6829 if (!System_Reflection_MonoGenericMethod)
6830 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6831 klass = System_Reflection_MonoGenericMethod;
6833 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6834 gret->method.method = method;
6835 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6836 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6837 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6841 refclass = method->klass;
6843 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6844 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6845 if (!System_Reflection_MonoCMethod)
6846 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6847 klass = System_Reflection_MonoCMethod;
6850 if (!System_Reflection_MonoMethod)
6851 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6852 klass = System_Reflection_MonoMethod;
6854 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6855 ret->method = method;
6856 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6857 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6861 * mono_method_clear_object:
6863 * Clear the cached reflection objects for the dynamic method METHOD.
6866 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6869 g_assert (method_is_dynamic (method));
6871 klass = method->klass;
6873 clear_cached_object (domain, method, klass);
6874 klass = klass->parent;
6876 /* Added by mono_param_get_objects () */
6877 clear_cached_object (domain, &(method->signature), NULL);
6878 klass = method->klass;
6880 clear_cached_object (domain, &(method->signature), klass);
6881 klass = klass->parent;
6886 * mono_field_get_object:
6887 * @domain: an app domain
6891 * Return an System.Reflection.MonoField object representing the field @field
6894 MonoReflectionField*
6895 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6897 MonoReflectionField *res;
6898 static MonoClass *monofield_klass;
6900 CHECK_OBJECT (MonoReflectionField *, field, klass);
6901 if (!monofield_klass)
6902 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6903 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6906 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6908 if (is_field_on_inst (field)) {
6909 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6910 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6913 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6914 res->attrs = mono_field_get_flags (field);
6916 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6920 * mono_property_get_object:
6921 * @domain: an app domain
6923 * @property: a property
6925 * Return an System.Reflection.MonoProperty object representing the property @property
6928 MonoReflectionProperty*
6929 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6931 MonoReflectionProperty *res;
6932 static MonoClass *monoproperty_klass;
6934 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6935 if (!monoproperty_klass)
6936 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6937 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6939 res->property = property;
6940 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6944 * mono_event_get_object:
6945 * @domain: an app domain
6949 * Return an System.Reflection.MonoEvent object representing the event @event
6952 MonoReflectionEvent*
6953 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6955 MonoReflectionEvent *res;
6956 MonoReflectionMonoEvent *mono_event;
6957 static MonoClass *monoevent_klass;
6959 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6960 if (!monoevent_klass)
6961 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6962 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6963 mono_event->klass = klass;
6964 mono_event->event = event;
6965 res = (MonoReflectionEvent*)mono_event;
6966 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6970 * mono_get_reflection_missing_object:
6971 * @domain: Domain where the object lives
6973 * Returns the System.Reflection.Missing.Value singleton object
6974 * (of type System.Reflection.Missing).
6976 * Used as the value for ParameterInfo.DefaultValue when Optional
6980 mono_get_reflection_missing_object (MonoDomain *domain)
6983 static MonoClassField *missing_value_field = NULL;
6985 if (!missing_value_field) {
6986 MonoClass *missing_klass;
6987 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6988 mono_class_init (missing_klass);
6989 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6990 g_assert (missing_value_field);
6992 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6998 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7001 *dbnull = mono_get_dbnull_object (domain);
7006 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7008 if (!*reflection_missing)
7009 *reflection_missing = mono_get_reflection_missing_object (domain);
7010 return *reflection_missing;
7014 * mono_param_get_objects:
7015 * @domain: an app domain
7018 * Return an System.Reflection.ParameterInfo array object representing the parameters
7019 * in the method @method.
7022 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7024 static MonoClass *System_Reflection_ParameterInfo;
7025 static MonoClass *System_Reflection_ParameterInfo_array;
7027 MonoArray *res = NULL;
7028 MonoReflectionMethod *member = NULL;
7029 MonoReflectionParameter *param = NULL;
7030 char **names, **blobs = NULL;
7031 guint32 *types = NULL;
7032 MonoType *type = NULL;
7033 MonoObject *dbnull = NULL;
7034 MonoObject *missing = NULL;
7035 MonoMarshalSpec **mspecs;
7036 MonoMethodSignature *sig;
7037 MonoVTable *pinfo_vtable;
7040 if (!System_Reflection_ParameterInfo_array) {
7043 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7045 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7047 mono_memory_barrier ();
7048 System_Reflection_ParameterInfo = klass;
7051 klass = mono_array_class_get (klass, 1);
7052 mono_memory_barrier ();
7053 System_Reflection_ParameterInfo_array = klass;
7056 sig = mono_method_signature_checked (method, &error);
7057 if (!mono_error_ok (&error))
7058 mono_error_raise_exception (&error);
7060 if (!sig->param_count) {
7061 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7062 mono_error_raise_exception (&error); /* FIXME don't raise here */
7067 /* Note: the cache is based on the address of the signature into the method
7068 * since we already cache MethodInfos with the method as keys.
7070 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7072 member = mono_method_get_object (domain, method, refclass);
7073 names = g_new (char *, sig->param_count);
7074 mono_method_get_param_names (method, (const char **) names);
7076 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7077 mono_method_get_marshal_info (method, mspecs);
7079 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7080 mono_error_raise_exception (&error); /* FIXME don't raise here */
7082 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7083 for (i = 0; i < sig->param_count; ++i) {
7084 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7085 mono_error_raise_exception (&error); /* FIXME don't raise here */
7086 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7087 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7088 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7089 param->PositionImpl = i;
7090 param->AttrsImpl = sig->params [i]->attrs;
7092 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7093 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7094 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7096 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7100 blobs = g_new0 (char *, sig->param_count);
7101 types = g_new0 (guint32, sig->param_count);
7102 get_default_param_value_blobs (method, blobs, types);
7105 /* Build MonoType for the type from the Constant Table */
7107 type = g_new0 (MonoType, 1);
7108 type->type = (MonoTypeEnum)types [i];
7109 type->data.klass = NULL;
7110 if (types [i] == MONO_TYPE_CLASS)
7111 type->data.klass = mono_defaults.object_class;
7112 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7113 /* For enums, types [i] contains the base type */
7115 type->type = MONO_TYPE_VALUETYPE;
7116 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7118 type->data.klass = mono_class_from_mono_type (type);
7120 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7122 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7123 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7124 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7125 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7127 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7133 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7135 mono_array_setref (res, i, param);
7142 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7144 mono_metadata_free_marshal_spec (mspecs [i]);
7147 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7151 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7153 return mono_param_get_objects_internal (domain, method, NULL);
7157 * mono_method_body_get_object:
7158 * @domain: an app domain
7161 * Return an System.Reflection.MethodBody object representing the method @method.
7163 MonoReflectionMethodBody*
7164 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7166 static MonoClass *System_Reflection_MethodBody = NULL;
7167 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7168 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7169 MonoReflectionMethodBody *ret;
7170 MonoMethodHeader *header;
7172 guint32 method_rva, local_var_sig_token;
7174 unsigned char format, flags;
7177 /* for compatibility with .net */
7178 if (method_is_dynamic (method))
7179 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7181 if (!System_Reflection_MethodBody)
7182 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7183 if (!System_Reflection_LocalVariableInfo)
7184 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7185 if (!System_Reflection_ExceptionHandlingClause)
7186 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7188 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7190 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7191 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7192 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7193 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7194 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7197 image = method->klass->image;
7198 header = mono_method_get_header (method);
7200 if (!image_is_dynamic (image)) {
7201 /* Obtain local vars signature token */
7202 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7203 ptr = mono_image_rva_map (image, method_rva);
7204 flags = *(const unsigned char *) ptr;
7205 format = flags & METHOD_HEADER_FORMAT_MASK;
7207 case METHOD_HEADER_TINY_FORMAT:
7208 local_var_sig_token = 0;
7210 case METHOD_HEADER_FAT_FORMAT:
7214 local_var_sig_token = read32 (ptr);
7217 g_assert_not_reached ();
7220 local_var_sig_token = 0; //FIXME
7222 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7224 ret->init_locals = header->init_locals;
7225 ret->max_stack = header->max_stack;
7226 ret->local_var_sig_token = local_var_sig_token;
7227 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7228 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7231 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7232 for (i = 0; i < header->num_locals; ++i) {
7233 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7234 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7235 info->is_pinned = header->locals [i]->pinned;
7236 info->local_index = i;
7237 mono_array_setref (ret->locals, i, info);
7241 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7242 for (i = 0; i < header->num_clauses; ++i) {
7243 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7244 MonoExceptionClause *clause = &header->clauses [i];
7246 info->flags = clause->flags;
7247 info->try_offset = clause->try_offset;
7248 info->try_length = clause->try_len;
7249 info->handler_offset = clause->handler_offset;
7250 info->handler_length = clause->handler_len;
7251 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7252 info->filter_offset = clause->data.filter_offset;
7253 else if (clause->data.catch_class)
7254 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7256 mono_array_setref (ret->clauses, i, info);
7259 mono_metadata_free_mh (header);
7260 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7265 * mono_get_dbnull_object:
7266 * @domain: Domain where the object lives
7268 * Returns the System.DBNull.Value singleton object
7270 * Used as the value for ParameterInfo.DefaultValue
7273 mono_get_dbnull_object (MonoDomain *domain)
7276 static MonoClassField *dbnull_value_field = NULL;
7278 if (!dbnull_value_field) {
7279 MonoClass *dbnull_klass;
7280 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7281 mono_class_init (dbnull_klass);
7282 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7283 g_assert (dbnull_value_field);
7285 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7291 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7293 guint32 param_index, i, lastp, crow = 0;
7294 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7297 MonoClass *klass = method->klass;
7298 MonoImage *image = klass->image;
7299 MonoMethodSignature *methodsig = mono_method_signature (method);
7301 MonoTableInfo *constt;
7302 MonoTableInfo *methodt;
7303 MonoTableInfo *paramt;
7305 if (!methodsig->param_count)
7308 mono_class_init (klass);
7310 if (image_is_dynamic (klass->image)) {
7311 MonoReflectionMethodAux *aux;
7312 if (method->is_inflated)
7313 method = ((MonoMethodInflated*)method)->declaring;
7314 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7315 if (aux && aux->param_defaults) {
7316 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7317 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7322 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7323 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7324 constt = &image->tables [MONO_TABLE_CONSTANT];
7326 idx = mono_method_get_index (method) - 1;
7327 g_assert (idx != -1);
7329 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7330 if (idx + 1 < methodt->rows)
7331 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7333 lastp = paramt->rows + 1;
7335 for (i = param_index; i < lastp; ++i) {
7338 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7339 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7341 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7344 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7349 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7350 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7351 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7358 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7363 MonoType *basetype = type;
7368 klass = mono_class_from_mono_type (type);
7369 if (klass->valuetype) {
7370 object = mono_object_new (domain, klass);
7371 retval = ((gchar *) object + sizeof (MonoObject));
7372 if (klass->enumtype)
7373 basetype = mono_class_enum_basetype (klass);
7378 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7385 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7388 gboolean quoted = FALSE;
7390 memset (assembly, 0, sizeof (MonoAssemblyName));
7391 assembly->culture = "";
7392 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7399 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7410 /* Remove trailing whitespace */
7412 while (*s && g_ascii_isspace (*s))
7415 while (g_ascii_isspace (*p))
7418 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7420 assembly->major = strtoul (p, &s, 10);
7421 if (s == p || *s != '.')
7424 assembly->minor = strtoul (p, &s, 10);
7425 if (s == p || *s != '.')
7428 assembly->build = strtoul (p, &s, 10);
7429 if (s == p || *s != '.')
7432 assembly->revision = strtoul (p, &s, 10);
7436 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7438 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7439 assembly->culture = "";
7442 assembly->culture = p;
7443 while (*p && *p != ',') {
7447 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7449 if (strncmp (p, "null", 4) == 0) {
7454 while (*p && *p != ',') {
7457 len = (p - start + 1);
7458 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7459 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7460 g_strlcpy ((char*)assembly->public_key_token, start, len);
7463 while (*p && *p != ',')
7467 while (g_ascii_isspace (*p) || *p == ',') {
7481 * mono_reflection_parse_type:
7484 * Parse a type name as accepted by the GetType () method and output the info
7485 * extracted in the info structure.
7486 * the name param will be mangled, so, make a copy before passing it to this function.
7487 * The fields in info will be valid until the memory pointed to by name is valid.
7489 * See also mono_type_get_name () below.
7491 * Returns: 0 on parse error.
7494 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7495 MonoTypeNameParse *info)
7497 char *start, *p, *w, *last_point, *startn;
7498 int in_modifiers = 0;
7499 int isbyref = 0, rank = 0, isptr = 0;
7501 start = p = w = name;
7503 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7504 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7505 info->name = info->name_space = NULL;
7506 info->nested = NULL;
7507 info->modifiers = NULL;
7508 info->type_arguments = NULL;
7510 /* last_point separates the namespace from the name */
7513 while (*p == ' ') p++, start++, w++, name++;
7518 *p = 0; /* NULL terminate the name */
7520 info->nested = g_list_append (info->nested, startn);
7521 /* we have parsed the nesting namespace + name */
7525 info->name_space = start;
7527 info->name = last_point + 1;
7529 info->name_space = (char *)"";
7557 info->name_space = start;
7559 info->name = last_point + 1;
7561 info->name_space = (char *)"";
7568 if (isbyref) /* only one level allowed by the spec */
7572 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7576 if (isbyref) /* pointer to ref not okay */
7578 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7583 if (isbyref) /* array of ref and generic ref are not okay */
7585 //Decide if it's an array of a generic argument list
7590 if (*p == ',' || *p == '*' || *p == ']') { //array
7598 else if (*p == '*') /* '*' means unknown lower bound */
7599 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7606 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7608 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7611 info->type_arguments = g_ptr_array_new ();
7613 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7614 gboolean fqname = FALSE;
7616 g_ptr_array_add (info->type_arguments, subinfo);
7618 while (*p == ' ') p++;
7624 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7627 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7628 if (fqname && (*p != ']')) {
7636 while (*p && (*p != ']'))
7644 if (g_ascii_isspace (*aname)) {
7651 !assembly_name_to_aname (&subinfo->assembly, aname))
7653 } else if (fqname && (*p == ']')) {
7675 if (g_ascii_isspace (*p)) {
7682 return 0; /* missing assembly name */
7683 if (!assembly_name_to_aname (&info->assembly, p))
7689 if (info->assembly.name)
7692 // *w = 0; /* terminate class name */
7694 if (!info->name || !*info->name)
7698 /* add other consistency checks */
7704 * mono_identifier_unescape_type_name_chars:
7705 * @identifier: the display name of a mono type
7708 * The name in internal form, that is without escaping backslashes.
7710 * The string is modified in place!
7713 mono_identifier_unescape_type_name_chars(char* identifier)
7718 for (w = r = identifier; *r != 0; r++)
7736 mono_identifier_unescape_info (MonoTypeNameParse* info);
7739 unescape_each_type_argument(void* data, void* user_data)
7741 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7742 mono_identifier_unescape_info (info);
7746 unescape_each_nested_name (void* data, void* user_data)
7748 char* nested_name = (char*) data;
7749 mono_identifier_unescape_type_name_chars(nested_name);
7753 * mono_identifier_unescape_info:
7755 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7759 * Destructively updates the info by unescaping the identifiers that
7760 * comprise the type namespace, name, nested types (if any) and
7761 * generic type arguments (if any).
7763 * The resulting info has the names in internal form.
7767 mono_identifier_unescape_info (MonoTypeNameParse *info)
7771 mono_identifier_unescape_type_name_chars(info->name_space);
7772 mono_identifier_unescape_type_name_chars(info->name);
7773 // but don't escape info->assembly
7774 if (info->type_arguments)
7775 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7777 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7781 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7783 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7785 mono_identifier_unescape_info (info);
7791 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7793 gboolean type_resolve = FALSE;
7795 MonoImage *rootimage = image;
7797 if (info->assembly.name) {
7798 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7799 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7801 * This could happen in the AOT compiler case when the search hook is not
7804 assembly = image->assembly;
7806 /* then we must load the assembly ourselve - see #60439 */
7807 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7811 image = assembly->image;
7812 } else if (!image) {
7813 image = mono_defaults.corlib;
7816 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7817 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7818 image = mono_defaults.corlib;
7819 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7826 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7831 gboolean bounded = FALSE;
7834 image = mono_defaults.corlib;
7837 rootimage = mono_defaults.corlib;
7841 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7842 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7844 klass = mono_class_from_name (image, info->name_space, info->name);
7848 for (mod = info->nested; mod; mod = mod->next) {
7849 gpointer iter = NULL;
7853 mono_class_init (parent);
7855 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7857 char *nested_name, *nested_nspace;
7858 gboolean match = TRUE;
7860 lastp = strrchr ((const char *)mod->data, '.');
7862 /* Nested classes can have namespaces */
7865 nested_name = g_strdup (lastp + 1);
7866 nspace_len = lastp - (char*)mod->data;
7867 nested_nspace = (char *)g_malloc (nspace_len + 1);
7868 memcpy (nested_nspace, mod->data, nspace_len);
7869 nested_nspace [nspace_len] = '\0';
7872 nested_name = (char *)mod->data;
7873 nested_nspace = NULL;
7876 if (nested_nspace) {
7878 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7881 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7887 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7890 if (strcmp (klass->name, nested_name) != 0)
7895 g_free (nested_name);
7896 g_free (nested_nspace);
7908 if (info->type_arguments) {
7909 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7910 MonoReflectionType *the_type;
7914 for (i = 0; i < info->type_arguments->len; i++) {
7915 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
7917 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7918 if (!type_args [i]) {
7924 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7926 instance = mono_reflection_bind_generic_parameters (
7927 the_type, info->type_arguments->len, type_args);
7933 klass = mono_class_from_mono_type (instance);
7936 for (mod = info->modifiers; mod; mod = mod->next) {
7937 modval = GPOINTER_TO_UINT (mod->data);
7938 if (!modval) { /* byref: must be last modifier */
7939 return &klass->this_arg;
7940 } else if (modval == -1) {
7941 klass = mono_ptr_class_get (&klass->byval_arg);
7942 } else if (modval == -2) {
7944 } else { /* array rank */
7945 klass = mono_bounded_array_class_get (klass, modval, bounded);
7949 return &klass->byval_arg;
7953 * mono_reflection_get_type:
7954 * @image: a metadata context
7955 * @info: type description structure
7956 * @ignorecase: flag for case-insensitive string compares
7957 * @type_resolve: whenever type resolve was already tried
7959 * Build a MonoType from the type description in @info.
7964 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7965 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7969 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7971 MonoReflectionAssemblyBuilder *abuilder;
7975 g_assert (assembly_is_dynamic (assembly));
7976 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7978 /* Enumerate all modules */
7981 if (abuilder->modules) {
7982 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7983 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7984 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7990 if (!type && abuilder->loaded_modules) {
7991 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7992 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7993 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8003 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8006 MonoReflectionAssembly *assembly;
8010 if (image && image_is_dynamic (image))
8011 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8013 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8016 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8023 *type_resolve = TRUE;
8026 /* Reconstruct the type name */
8027 fullName = g_string_new ("");
8028 if (info->name_space && (info->name_space [0] != '\0'))
8029 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8031 g_string_printf (fullName, "%s", info->name);
8032 for (mod = info->nested; mod; mod = mod->next)
8033 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8035 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8037 if (assembly_is_dynamic (assembly->assembly))
8038 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8040 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8043 g_string_free (fullName, TRUE);
8048 mono_reflection_free_type_info (MonoTypeNameParse *info)
8050 g_list_free (info->modifiers);
8051 g_list_free (info->nested);
8053 if (info->type_arguments) {
8056 for (i = 0; i < info->type_arguments->len; i++) {
8057 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8059 mono_reflection_free_type_info (subinfo);
8060 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8064 g_ptr_array_free (info->type_arguments, TRUE);
8069 * mono_reflection_type_from_name:
8071 * @image: a metadata context (can be NULL).
8073 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8074 * it defaults to get the type from @image or, if @image is NULL or loading
8075 * from it fails, uses corlib.
8079 mono_reflection_type_from_name (char *name, MonoImage *image)
8081 MonoType *type = NULL;
8082 MonoTypeNameParse info;
8085 /* Make a copy since parse_type modifies its argument */
8086 tmp = g_strdup (name);
8088 /*g_print ("requested type %s\n", str);*/
8089 if (mono_reflection_parse_type (tmp, &info)) {
8090 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8094 mono_reflection_free_type_info (&info);
8099 * mono_reflection_get_token:
8101 * Return the metadata token of OBJ which should be an object
8102 * representing a metadata element.
8105 mono_reflection_get_token (MonoObject *obj)
8110 klass = obj->vtable->klass;
8112 if (strcmp (klass->name, "MethodBuilder") == 0) {
8113 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8115 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8116 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8117 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8119 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8120 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8121 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8123 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8124 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8125 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8126 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8127 } else if (strcmp (klass->name, "MonoType") == 0) {
8128 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8129 MonoClass *mc = mono_class_from_mono_type (type);
8130 if (!mono_class_init (mc))
8131 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8133 token = mc->type_token;
8134 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8135 strcmp (klass->name, "MonoMethod") == 0 ||
8136 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8137 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8138 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8139 if (m->method->is_inflated) {
8140 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8141 return inflated->declaring->token;
8143 token = m->method->token;
8145 } else if (strcmp (klass->name, "MonoField") == 0) {
8146 MonoReflectionField *f = (MonoReflectionField*)obj;
8148 if (is_field_on_inst (f->field)) {
8149 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8151 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8152 int field_index = f->field - dgclass->fields;
8155 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8156 obj = dgclass->field_objects [field_index];
8157 return mono_reflection_get_token (obj);
8160 token = mono_class_get_field_token (f->field);
8161 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8162 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8164 token = mono_class_get_property_token (p->property);
8165 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8166 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8168 token = mono_class_get_event_token (p->event);
8169 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8170 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8171 MonoClass *member_class = mono_object_class (p->MemberImpl);
8172 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8174 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8175 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8176 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8179 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8180 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8182 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8183 MonoException *ex = mono_get_exception_not_implemented (msg);
8185 mono_raise_exception (ex);
8192 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8196 int slen = mono_metadata_decode_value (p, &p);
8198 mono_error_init (error);
8200 n = (char *)g_memdup (p, slen + 1);
8202 t = mono_reflection_type_from_name (n, image);
8204 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8205 /* We don't free n, it's consumed by mono_error */
8206 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8212 return mono_class_from_mono_type (t);
8216 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8218 int slen, type = t->type;
8219 MonoClass *tklass = t->data.klass;
8221 mono_error_init (error);
8227 case MONO_TYPE_BOOLEAN: {
8228 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8233 case MONO_TYPE_CHAR:
8235 case MONO_TYPE_I2: {
8236 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8241 #if SIZEOF_VOID_P == 4
8247 case MONO_TYPE_I4: {
8248 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8253 #if SIZEOF_VOID_P == 8
8254 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8258 case MONO_TYPE_I8: {
8259 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8264 case MONO_TYPE_R8: {
8265 double *val = (double *)g_malloc (sizeof (double));
8270 case MONO_TYPE_VALUETYPE:
8271 if (t->data.klass->enumtype) {
8272 type = mono_class_enum_basetype (t->data.klass)->type;
8275 MonoClass *k = t->data.klass;
8277 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8278 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8284 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8287 case MONO_TYPE_STRING:
8288 if (*p == (char)0xFF) {
8292 slen = mono_metadata_decode_value (p, &p);
8294 return mono_string_new_len (mono_domain_get (), p, slen);
8295 case MONO_TYPE_CLASS: {
8298 if (*p == (char)0xFF) {
8303 slen = mono_metadata_decode_value (p, &p);
8304 n = (char *)g_memdup (p, slen + 1);
8306 t = mono_reflection_type_from_name (n, image);
8308 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8309 /* We don't free n, it's consumed by mono_error */
8310 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8315 return mono_type_get_object (mono_domain_get (), t);
8317 case MONO_TYPE_OBJECT: {
8320 MonoClass *subc = NULL;
8325 } else if (subt == 0x0E) {
8326 type = MONO_TYPE_STRING;
8328 } else if (subt == 0x1D) {
8329 MonoType simple_type = {{0}};
8333 type = MONO_TYPE_SZARRAY;
8334 if (etype == 0x50) {
8335 tklass = mono_defaults.systemtype_class;
8336 } else if (etype == 0x55) {
8337 tklass = load_cattr_enum_type (image, p, &p, error);
8338 if (!mono_error_ok (error))
8342 /* See Partition II, Appendix B3 */
8343 etype = MONO_TYPE_OBJECT;
8344 simple_type.type = (MonoTypeEnum)etype;
8345 tklass = mono_class_from_mono_type (&simple_type);
8348 } else if (subt == 0x55) {
8351 slen = mono_metadata_decode_value (p, &p);
8352 n = (char *)g_memdup (p, slen + 1);
8354 t = mono_reflection_type_from_name (n, image);
8356 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8357 /* We don't free n, it's consumed by mono_error */
8358 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8363 subc = mono_class_from_mono_type (t);
8364 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8365 MonoType simple_type = {{0}};
8366 simple_type.type = (MonoTypeEnum)subt;
8367 subc = mono_class_from_mono_type (&simple_type);
8369 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8371 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8373 if (mono_error_ok (error)) {
8374 obj = mono_object_new (mono_domain_get (), subc);
8375 g_assert (!subc->has_references);
8376 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8382 case MONO_TYPE_SZARRAY: {
8384 guint32 i, alen, basetype;
8387 if (alen == 0xffffffff) {
8391 arr = mono_array_new (mono_domain_get(), tklass, alen);
8392 basetype = tklass->byval_arg.type;
8393 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8394 basetype = mono_class_enum_basetype (tklass)->type;
8399 case MONO_TYPE_BOOLEAN:
8400 for (i = 0; i < alen; i++) {
8401 MonoBoolean val = *p++;
8402 mono_array_set (arr, MonoBoolean, i, val);
8405 case MONO_TYPE_CHAR:
8408 for (i = 0; i < alen; i++) {
8409 guint16 val = read16 (p);
8410 mono_array_set (arr, guint16, i, val);
8417 for (i = 0; i < alen; i++) {
8418 guint32 val = read32 (p);
8419 mono_array_set (arr, guint32, i, val);
8424 for (i = 0; i < alen; i++) {
8427 mono_array_set (arr, double, i, val);
8433 for (i = 0; i < alen; i++) {
8434 guint64 val = read64 (p);
8435 mono_array_set (arr, guint64, i, val);
8439 case MONO_TYPE_CLASS:
8440 case MONO_TYPE_OBJECT:
8441 case MONO_TYPE_STRING:
8442 case MONO_TYPE_SZARRAY:
8443 for (i = 0; i < alen; i++) {
8444 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8445 if (!mono_error_ok (error))
8447 mono_array_setref (arr, i, item);
8451 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8457 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8463 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8465 static MonoClass *klass;
8466 static MonoMethod *ctor;
8468 void *params [2], *unboxed;
8471 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8473 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8475 params [0] = mono_type_get_object (mono_domain_get (), t);
8477 retval = mono_object_new (mono_domain_get (), klass);
8478 unboxed = mono_object_unbox (retval);
8479 mono_runtime_invoke (ctor, unboxed, params, NULL);
8485 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8487 static MonoClass *klass;
8488 static MonoMethod *ctor;
8490 void *unboxed, *params [2];
8493 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8495 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8498 params [1] = typedarg;
8499 retval = mono_object_new (mono_domain_get (), klass);
8500 unboxed = mono_object_unbox (retval);
8501 mono_runtime_invoke (ctor, unboxed, params, NULL);
8507 type_is_reference (MonoType *type)
8509 switch (type->type) {
8510 case MONO_TYPE_BOOLEAN:
8511 case MONO_TYPE_CHAR:
8524 case MONO_TYPE_VALUETYPE:
8532 free_param_data (MonoMethodSignature *sig, void **params) {
8534 for (i = 0; i < sig->param_count; ++i) {
8535 if (!type_is_reference (sig->params [i]))
8536 g_free (params [i]);
8541 * Find the field index in the metadata FieldDef table.
8544 find_field_index (MonoClass *klass, MonoClassField *field) {
8547 for (i = 0; i < klass->field.count; ++i) {
8548 if (field == &klass->fields [i])
8549 return klass->field.first + 1 + i;
8555 * Find the property index in the metadata Property table.
8558 find_property_index (MonoClass *klass, MonoProperty *property) {
8561 for (i = 0; i < klass->ext->property.count; ++i) {
8562 if (property == &klass->ext->properties [i])
8563 return klass->ext->property.first + 1 + i;
8569 * Find the event index in the metadata Event table.
8572 find_event_index (MonoClass *klass, MonoEvent *event) {
8575 for (i = 0; i < klass->ext->event.count; ++i) {
8576 if (event == &klass->ext->events [i])
8577 return klass->ext->event.first + 1 + i;
8583 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8585 const char *p = (const char*)data;
8587 guint32 i, j, num_named;
8589 void *params_buf [32];
8590 void **params = NULL;
8591 MonoMethodSignature *sig;
8592 MonoObject *exc = NULL;
8594 mono_error_init (error);
8596 mono_class_init (method->klass);
8598 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8599 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8604 attr = mono_object_new (mono_domain_get (), method->klass);
8605 mono_runtime_invoke (method, attr, NULL, NULL);
8609 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8612 /*g_print ("got attr %s\n", method->klass->name);*/
8614 sig = mono_method_signature (method);
8615 if (sig->param_count < 32) {
8616 params = params_buf;
8617 memset (params, 0, sizeof (void*) * sig->param_count);
8619 /* Allocate using GC so it gets GC tracking */
8620 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8625 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8626 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8627 if (!mono_error_ok (error))
8632 attr = mono_object_new (mono_domain_get (), method->klass);
8634 mono_runtime_invoke (method, attr, params, &exc);
8637 num_named = read16 (named);
8639 for (j = 0; j < num_named; j++) {
8641 char *name, named_type, data_type;
8642 named_type = *named++;
8643 data_type = *named++; /* type of data */
8644 if (data_type == MONO_TYPE_SZARRAY)
8645 data_type = *named++;
8646 if (data_type == MONO_TYPE_ENUM) {
8649 type_len = mono_metadata_decode_blob_size (named, &named);
8650 type_name = (char *)g_malloc (type_len + 1);
8651 memcpy (type_name, named, type_len);
8652 type_name [type_len] = 0;
8654 /* FIXME: lookup the type and check type consistency */
8657 name_len = mono_metadata_decode_blob_size (named, &named);
8658 name = (char *)g_malloc (name_len + 1);
8659 memcpy (name, named, name_len);
8660 name [name_len] = 0;
8662 if (named_type == 0x53) {
8663 MonoClassField *field;
8666 /* how this fail is a blackbox */
8667 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8669 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8674 val = load_cattr_value (image, field->type, named, &named, error);
8675 if (!mono_error_ok (error)) {
8677 if (!type_is_reference (field->type))
8682 mono_field_set_value (attr, field, val);
8683 if (!type_is_reference (field->type))
8685 } else if (named_type == 0x54) {
8688 MonoType *prop_type;
8690 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8693 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8699 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8704 /* can we have more that 1 arg in a custom attr named property? */
8705 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8706 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8708 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8709 if (!mono_error_ok (error)) {
8711 if (!type_is_reference (prop_type))
8712 g_free (pparams [0]);
8717 mono_property_set_value (prop, attr, pparams, NULL);
8718 if (!type_is_reference (prop_type))
8719 g_free (pparams [0]);
8724 free_param_data (method->signature, params);
8725 if (params != params_buf)
8726 mono_gc_free_fixed (params);
8731 free_param_data (method->signature, params);
8732 if (params != params_buf)
8733 mono_gc_free_fixed (params);
8735 mono_raise_exception ((MonoException*)exc);
8740 * mono_reflection_create_custom_attr_data_args:
8742 * Create an array of typed and named arguments from the cattr blob given by DATA.
8743 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8744 * NAMED_ARG_INFO will contain information about the named arguments.
8747 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)
8749 MonoArray *typedargs, *namedargs;
8750 MonoClass *attrklass;
8752 const char *p = (const char*)data;
8754 guint32 i, j, num_named;
8755 CattrNamedArg *arginfo = NULL;
8759 *named_arg_info = NULL;
8761 mono_error_init (error);
8763 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8764 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8768 mono_class_init (method->klass);
8770 domain = mono_domain_get ();
8772 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8775 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8779 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8783 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8784 if (!mono_error_ok (error)) {
8785 if (!type_is_reference (mono_method_signature (method)->params [i]))
8790 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8791 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8792 mono_array_setref (typedargs, i, obj);
8794 if (!type_is_reference (mono_method_signature (method)->params [i]))
8799 num_named = read16 (named);
8800 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8802 attrklass = method->klass;
8804 arginfo = g_new0 (CattrNamedArg, num_named);
8805 *named_arg_info = arginfo;
8807 for (j = 0; j < num_named; j++) {
8809 char *name, named_type, data_type;
8810 named_type = *named++;
8811 data_type = *named++; /* type of data */
8812 if (data_type == MONO_TYPE_SZARRAY)
8813 data_type = *named++;
8814 if (data_type == MONO_TYPE_ENUM) {
8817 type_len = mono_metadata_decode_blob_size (named, &named);
8818 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8821 type_name = (char *)g_malloc (type_len + 1);
8822 memcpy (type_name, named, type_len);
8823 type_name [type_len] = 0;
8825 /* FIXME: lookup the type and check type consistency */
8828 name_len = mono_metadata_decode_blob_size (named, &named);
8829 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8831 name = (char *)g_malloc (name_len + 1);
8832 memcpy (name, named, name_len);
8833 name [name_len] = 0;
8835 if (named_type == 0x53) {
8837 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8845 arginfo [j].type = field->type;
8846 arginfo [j].field = field;
8848 val = load_cattr_value (image, field->type, named, &named, error);
8849 if (!mono_error_ok (error)) {
8850 if (!type_is_reference (field->type))
8856 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8857 mono_array_setref (namedargs, j, obj);
8858 if (!type_is_reference (field->type))
8860 } else if (named_type == 0x54) {
8862 MonoType *prop_type;
8863 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8866 if (!prop || !prop->set) {
8871 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8872 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8874 arginfo [j].type = prop_type;
8875 arginfo [j].prop = prop;
8877 val = load_cattr_value (image, prop_type, named, &named, error);
8878 if (!mono_error_ok (error)) {
8879 if (!type_is_reference (prop_type))
8885 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8886 mono_array_setref (namedargs, j, obj);
8887 if (!type_is_reference (prop_type))
8893 *typed_args = typedargs;
8894 *named_args = namedargs;
8897 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8899 *named_arg_info = NULL;
8903 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8906 MonoArray *typedargs, *namedargs;
8909 CattrNamedArg *arginfo = NULL;
8919 image = assembly->assembly->image;
8920 method = ref_method->method;
8921 domain = mono_object_domain (ref_method);
8923 if (!mono_class_init (method->klass))
8924 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8926 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
8927 if (!mono_error_ok (&error))
8928 mono_error_raise_exception (&error);
8929 if (mono_loader_get_last_error ())
8930 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8932 if (!typedargs || !namedargs) {
8937 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8938 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8939 MonoObject *typedarg;
8941 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8942 mono_array_setref (typedargs, i, typedarg);
8945 for (i = 0; i < mono_array_length (namedargs); ++i) {
8946 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8947 MonoObject *typedarg, *namedarg, *minfo;
8949 if (arginfo [i].prop)
8950 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8952 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8954 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8955 namedarg = create_cattr_named_arg (minfo, typedarg);
8957 mono_array_setref (namedargs, i, namedarg);
8960 *ctor_args = typedargs;
8961 *named_args = namedargs;
8966 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8968 static MonoMethod *ctor;
8973 g_assert (image->assembly);
8976 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8978 domain = mono_domain_get ();
8979 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8980 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8981 params [1] = mono_assembly_get_object (domain, image->assembly);
8982 params [2] = (gpointer)&cattr->data;
8983 params [3] = &cattr->data_size;
8984 mono_runtime_invoke (ctor, attr, params, NULL);
8989 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8995 mono_error_init (error);
8998 for (i = 0; i < cinfo->num_attrs; ++i) {
8999 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9003 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9005 for (i = 0; i < cinfo->num_attrs; ++i) {
9006 if (!cinfo->attrs [i].ctor)
9007 /* The cattr type is not finished yet */
9008 /* We should include the type name but cinfo doesn't contain it */
9009 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9010 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9011 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9012 if (!mono_error_ok (error))
9014 mono_array_setref (result, n, attr);
9022 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9025 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9026 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9032 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9038 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9039 for (i = 0; i < cinfo->num_attrs; ++i) {
9040 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9041 mono_array_setref (result, i, attr);
9047 * mono_custom_attrs_from_index:
9049 * Returns: NULL if no attributes are found or if a loading error occurs.
9052 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9054 guint32 mtoken, i, len;
9055 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9057 MonoCustomAttrInfo *ainfo;
9058 GList *tmp, *list = NULL;
9060 MonoCustomAttrEntry* attr;
9062 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9064 i = mono_metadata_custom_attrs_from_index (image, idx);
9068 while (i < ca->rows) {
9069 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9071 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9074 len = g_list_length (list);
9077 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9078 ainfo->num_attrs = len;
9079 ainfo->image = image;
9080 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9081 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9082 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9083 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9084 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9085 mtoken |= MONO_TOKEN_METHOD_DEF;
9087 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9088 mtoken |= MONO_TOKEN_MEMBER_REF;
9091 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9094 attr = &ainfo->attrs [i - 1];
9095 attr->ctor = mono_get_method (image, mtoken, NULL);
9097 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9103 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9104 /*FIXME raising an exception here doesn't make any sense*/
9105 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9110 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9111 attr->data_size = mono_metadata_decode_value (data, &data);
9112 attr->data = (guchar*)data;
9120 mono_custom_attrs_from_method (MonoMethod *method)
9125 * An instantiated method has the same cattrs as the generic method definition.
9127 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9128 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9130 if (method->is_inflated)
9131 method = ((MonoMethodInflated *) method)->declaring;
9133 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9134 return lookup_custom_attr (method->klass->image, method);
9137 /* Synthetic methods */
9140 idx = mono_method_get_index (method);
9141 idx <<= MONO_CUSTOM_ATTR_BITS;
9142 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9143 return mono_custom_attrs_from_index (method->klass->image, idx);
9147 mono_custom_attrs_from_class (MonoClass *klass)
9151 if (klass->generic_class)
9152 klass = klass->generic_class->container_class;
9154 if (image_is_dynamic (klass->image))
9155 return lookup_custom_attr (klass->image, klass);
9157 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9158 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9159 idx <<= MONO_CUSTOM_ATTR_BITS;
9160 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9162 idx = mono_metadata_token_index (klass->type_token);
9163 idx <<= MONO_CUSTOM_ATTR_BITS;
9164 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9166 return mono_custom_attrs_from_index (klass->image, idx);
9170 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9174 if (image_is_dynamic (assembly->image))
9175 return lookup_custom_attr (assembly->image, assembly);
9176 idx = 1; /* there is only one assembly */
9177 idx <<= MONO_CUSTOM_ATTR_BITS;
9178 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9179 return mono_custom_attrs_from_index (assembly->image, idx);
9182 static MonoCustomAttrInfo*
9183 mono_custom_attrs_from_module (MonoImage *image)
9187 if (image_is_dynamic (image))
9188 return lookup_custom_attr (image, image);
9189 idx = 1; /* there is only one module */
9190 idx <<= MONO_CUSTOM_ATTR_BITS;
9191 idx |= MONO_CUSTOM_ATTR_MODULE;
9192 return mono_custom_attrs_from_index (image, idx);
9196 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9200 if (image_is_dynamic (klass->image)) {
9201 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9202 return lookup_custom_attr (klass->image, property);
9204 idx = find_property_index (klass, property);
9205 idx <<= MONO_CUSTOM_ATTR_BITS;
9206 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9207 return mono_custom_attrs_from_index (klass->image, idx);
9211 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9215 if (image_is_dynamic (klass->image)) {
9216 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9217 return lookup_custom_attr (klass->image, event);
9219 idx = find_event_index (klass, event);
9220 idx <<= MONO_CUSTOM_ATTR_BITS;
9221 idx |= MONO_CUSTOM_ATTR_EVENT;
9222 return mono_custom_attrs_from_index (klass->image, idx);
9226 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9229 if (image_is_dynamic (klass->image)) {
9230 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9231 return lookup_custom_attr (klass->image, field);
9233 idx = find_field_index (klass, field);
9234 idx <<= MONO_CUSTOM_ATTR_BITS;
9235 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9236 return mono_custom_attrs_from_index (klass->image, idx);
9240 * mono_custom_attrs_from_param:
9241 * @method: handle to the method that we want to retrieve custom parameter information from
9242 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9244 * The result must be released with mono_custom_attrs_free().
9246 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9249 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9252 guint32 i, idx, method_index;
9253 guint32 param_list, param_last, param_pos, found;
9255 MonoReflectionMethodAux *aux;
9258 * An instantiated method has the same cattrs as the generic method definition.
9260 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9261 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9263 if (method->is_inflated)
9264 method = ((MonoMethodInflated *) method)->declaring;
9266 if (image_is_dynamic (method->klass->image)) {
9267 MonoCustomAttrInfo *res, *ainfo;
9270 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9271 if (!aux || !aux->param_cattr)
9274 /* Need to copy since it will be freed later */
9275 ainfo = aux->param_cattr [param];
9278 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9279 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9280 memcpy (res, ainfo, size);
9284 image = method->klass->image;
9285 method_index = mono_method_get_index (method);
9288 ca = &image->tables [MONO_TABLE_METHOD];
9290 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9291 if (method_index == ca->rows) {
9292 ca = &image->tables [MONO_TABLE_PARAM];
9293 param_last = ca->rows + 1;
9295 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9296 ca = &image->tables [MONO_TABLE_PARAM];
9299 for (i = param_list; i < param_last; ++i) {
9300 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9301 if (param_pos == param) {
9309 idx <<= MONO_CUSTOM_ATTR_BITS;
9310 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9311 return mono_custom_attrs_from_index (image, idx);
9315 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9319 for (i = 0; i < ainfo->num_attrs; ++i) {
9320 klass = ainfo->attrs [i].ctor->klass;
9321 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9328 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9331 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9332 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9337 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9343 mono_error_init (error);
9346 for (i = 0; i < ainfo->num_attrs; ++i) {
9347 klass = ainfo->attrs [i].ctor->klass;
9348 if (mono_class_has_parent (klass, attr_klass)) {
9353 if (attr_index == -1)
9356 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9357 if (!mono_error_ok (error))
9359 return mono_array_get (attrs, MonoObject*, attr_index);
9363 * mono_reflection_get_custom_attrs_info:
9364 * @obj: a reflection object handle
9366 * Return the custom attribute info for attributes defined for the
9367 * reflection handle @obj. The objects.
9369 * FIXME this function leaks like a sieve for SRE objects.
9372 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9375 MonoCustomAttrInfo *cinfo = NULL;
9377 klass = obj->vtable->klass;
9378 if (klass == mono_defaults.monotype_class) {
9379 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9380 klass = mono_class_from_mono_type (type);
9381 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9382 cinfo = mono_custom_attrs_from_class (klass);
9383 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9384 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9385 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9386 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9387 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9388 cinfo = mono_custom_attrs_from_module (module->image);
9389 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9390 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9391 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9392 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9393 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9394 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9395 } else if (strcmp ("MonoField", klass->name) == 0) {
9396 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9397 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9398 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9399 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9400 cinfo = mono_custom_attrs_from_method (rmethod->method);
9401 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9402 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9403 cinfo = mono_custom_attrs_from_method (rmethod->method);
9404 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9405 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9406 MonoClass *member_class = mono_object_class (param->MemberImpl);
9407 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9408 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9409 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9410 } else if (is_sr_mono_property (member_class)) {
9411 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9413 if (!(method = prop->property->get))
9414 method = prop->property->set;
9417 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9419 #ifndef DISABLE_REFLECTION_EMIT
9420 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9421 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9422 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9423 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9424 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9425 MonoMethod *method = NULL;
9426 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9427 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9428 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9429 method = ((MonoReflectionMethod *)c->cb)->method;
9431 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));
9433 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9437 char *type_name = mono_type_get_full_name (member_class);
9438 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9439 MonoException *ex = mono_get_exception_not_supported (msg);
9442 mono_raise_exception (ex);
9444 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9445 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9446 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9447 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9448 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9449 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9450 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9451 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9452 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9453 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9454 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9455 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9456 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9457 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9458 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9459 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9460 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9461 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9462 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9463 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9464 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9465 } else { /* handle other types here... */
9466 g_error ("get custom attrs not yet supported for %s", klass->name);
9473 * mono_reflection_get_custom_attrs_by_type:
9474 * @obj: a reflection object handle
9476 * Return an array with all the custom attributes defined of the
9477 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9478 * of that type are returned. The objects are fully build. Return NULL if a loading error
9482 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9485 MonoCustomAttrInfo *cinfo;
9487 mono_error_init (error);
9489 cinfo = mono_reflection_get_custom_attrs_info (obj);
9491 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9493 mono_custom_attrs_free (cinfo);
9495 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9496 if (mono_loader_get_last_error ())
9498 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9505 * mono_reflection_get_custom_attrs:
9506 * @obj: a reflection object handle
9508 * Return an array with all the custom attributes defined of the
9509 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9513 mono_reflection_get_custom_attrs (MonoObject *obj)
9517 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9521 * mono_reflection_get_custom_attrs_data:
9522 * @obj: a reflection obj handle
9524 * Returns an array of System.Reflection.CustomAttributeData,
9525 * which include information about attributes reflected on
9526 * types loaded using the Reflection Only methods
9529 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9532 MonoCustomAttrInfo *cinfo;
9534 cinfo = mono_reflection_get_custom_attrs_info (obj);
9536 result = mono_custom_attrs_data_construct (cinfo);
9538 mono_custom_attrs_free (cinfo);
9540 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9545 static MonoReflectionType*
9546 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9548 static MonoMethod *method_get_underlying_system_type = NULL;
9549 MonoMethod *usertype_method;
9551 if (!method_get_underlying_system_type)
9552 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9553 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9554 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9559 is_corlib_type (MonoClass *klass)
9561 return klass->image == mono_defaults.corlib;
9564 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9565 static MonoClass *cached_class; \
9567 return cached_class == _class; \
9568 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9569 cached_class = _class; \
9576 #ifndef DISABLE_REFLECTION_EMIT
9578 is_sre_array (MonoClass *klass)
9580 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9584 is_sre_byref (MonoClass *klass)
9586 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9590 is_sre_pointer (MonoClass *klass)
9592 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9596 is_sre_generic_instance (MonoClass *klass)
9598 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9602 is_sre_type_builder (MonoClass *klass)
9604 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9608 is_sre_method_builder (MonoClass *klass)
9610 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9614 is_sre_ctor_builder (MonoClass *klass)
9616 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9620 is_sre_field_builder (MonoClass *klass)
9622 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9626 is_sre_method_on_tb_inst (MonoClass *klass)
9628 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9632 is_sre_ctor_on_tb_inst (MonoClass *klass)
9634 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9638 mono_reflection_type_get_handle (MonoReflectionType* ref)
9646 if (is_usertype (ref)) {
9647 ref = mono_reflection_type_get_underlying_system_type (ref);
9648 if (ref == NULL || is_usertype (ref))
9654 klass = mono_object_class (ref);
9656 if (is_sre_array (klass)) {
9658 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9659 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9661 if (sre_array->rank == 0) //single dimentional array
9662 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9664 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9665 sre_array->type.type = res;
9667 } else if (is_sre_byref (klass)) {
9669 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9670 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9672 res = &mono_class_from_mono_type (base)->this_arg;
9673 sre_byref->type.type = res;
9675 } else if (is_sre_pointer (klass)) {
9677 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9678 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9680 res = &mono_ptr_class_get (base)->byval_arg;
9681 sre_pointer->type.type = res;
9683 } else if (is_sre_generic_instance (klass)) {
9684 MonoType *res, **types;
9685 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9688 count = mono_array_length (gclass->type_arguments);
9689 types = g_new0 (MonoType*, count);
9690 for (i = 0; i < count; ++i) {
9691 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9692 types [i] = mono_reflection_type_get_handle (t);
9699 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9702 gclass->type.type = res;
9706 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9713 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9715 mono_reflection_type_get_handle (type);
9719 mono_reflection_register_with_runtime (MonoReflectionType *type)
9721 MonoType *res = mono_reflection_type_get_handle (type);
9722 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9726 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9728 klass = mono_class_from_mono_type (res);
9730 mono_loader_lock (); /*same locking as mono_type_get_object*/
9731 mono_domain_lock (domain);
9733 if (!image_is_dynamic (klass->image)) {
9734 mono_class_setup_supertypes (klass);
9736 if (!domain->type_hash)
9737 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9738 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9739 mono_g_hash_table_insert (domain->type_hash, res, type);
9741 mono_domain_unlock (domain);
9742 mono_loader_unlock ();
9746 * LOCKING: Assumes the loader lock is held.
9748 static MonoMethodSignature*
9749 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9750 MonoMethodSignature *sig;
9753 count = parameters? mono_array_length (parameters): 0;
9755 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9756 sig->param_count = count;
9757 sig->sentinelpos = -1; /* FIXME */
9758 for (i = 0; i < count; ++i)
9759 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9764 * LOCKING: Assumes the loader lock is held.
9766 static MonoMethodSignature*
9767 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9768 MonoMethodSignature *sig;
9770 sig = parameters_to_signature (image, ctor->parameters);
9771 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9772 sig->ret = &mono_defaults.void_class->byval_arg;
9777 * LOCKING: Assumes the loader lock is held.
9779 static MonoMethodSignature*
9780 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9781 MonoMethodSignature *sig;
9783 sig = parameters_to_signature (image, method->parameters);
9784 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9785 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9786 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9790 static MonoMethodSignature*
9791 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9792 MonoMethodSignature *sig;
9794 sig = parameters_to_signature (NULL, method->parameters);
9795 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9796 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9797 sig->generic_param_count = 0;
9802 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9804 MonoClass *klass = mono_object_class (prop);
9805 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9806 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9807 *name = mono_string_to_utf8 (pb->name);
9808 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9810 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9811 *name = g_strdup (p->property->name);
9812 if (p->property->get)
9813 *type = mono_method_signature (p->property->get)->ret;
9815 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9820 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9822 MonoClass *klass = mono_object_class (field);
9823 if (strcmp (klass->name, "FieldBuilder") == 0) {
9824 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9825 *name = mono_string_to_utf8 (fb->name);
9826 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9828 MonoReflectionField *f = (MonoReflectionField *)field;
9829 *name = g_strdup (mono_field_get_name (f->field));
9830 *type = f->field->type;
9834 #else /* DISABLE_REFLECTION_EMIT */
9837 mono_reflection_register_with_runtime (MonoReflectionType *type)
9843 is_sre_type_builder (MonoClass *klass)
9849 is_sre_generic_instance (MonoClass *klass)
9855 init_type_builder_generics (MonoObject *type)
9859 #endif /* !DISABLE_REFLECTION_EMIT */
9863 is_sr_mono_field (MonoClass *klass)
9865 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9869 is_sr_mono_property (MonoClass *klass)
9871 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9875 is_sr_mono_method (MonoClass *klass)
9877 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9881 is_sr_mono_cmethod (MonoClass *klass)
9883 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9887 is_sr_mono_generic_method (MonoClass *klass)
9889 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9893 is_sr_mono_generic_cmethod (MonoClass *klass)
9895 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9899 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9901 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9905 is_usertype (MonoReflectionType *ref)
9907 MonoClass *klass = mono_object_class (ref);
9908 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9911 static MonoReflectionType*
9912 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9914 if (!type || type->type)
9917 if (is_usertype (type)) {
9918 type = mono_reflection_type_get_underlying_system_type (type);
9919 if (is_usertype (type))
9920 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9926 * Encode a value in a custom attribute stream of bytes.
9927 * The value to encode is either supplied as an object in argument val
9928 * (valuetypes are boxed), or as a pointer to the data in the
9930 * @type represents the type of the value
9931 * @buffer is the start of the buffer
9932 * @p the current position in the buffer
9933 * @buflen contains the size of the buffer and is used to return the new buffer size
9934 * if this needs to be realloced.
9935 * @retbuffer and @retp return the start and the position of the buffer
9938 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9940 MonoTypeEnum simple_type;
9942 if ((p-buffer) + 10 >= *buflen) {
9945 newbuf = (char *)g_realloc (buffer, *buflen);
9946 p = newbuf + (p-buffer);
9950 argval = ((char*)arg + sizeof (MonoObject));
9951 simple_type = type->type;
9953 switch (simple_type) {
9954 case MONO_TYPE_BOOLEAN:
9959 case MONO_TYPE_CHAR:
9962 swap_with_size (p, argval, 2, 1);
9968 swap_with_size (p, argval, 4, 1);
9972 swap_with_size (p, argval, 8, 1);
9977 swap_with_size (p, argval, 8, 1);
9980 case MONO_TYPE_VALUETYPE:
9981 if (type->data.klass->enumtype) {
9982 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9985 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9988 case MONO_TYPE_STRING: {
9995 str = mono_string_to_utf8 ((MonoString*)arg);
9996 slen = strlen (str);
9997 if ((p-buffer) + 10 + slen >= *buflen) {
10001 newbuf = (char *)g_realloc (buffer, *buflen);
10002 p = newbuf + (p-buffer);
10005 mono_metadata_encode_value (slen, p, &p);
10006 memcpy (p, str, slen);
10011 case MONO_TYPE_CLASS: {
10019 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10020 slen = strlen (str);
10021 if ((p-buffer) + 10 + slen >= *buflen) {
10025 newbuf = (char *)g_realloc (buffer, *buflen);
10026 p = newbuf + (p-buffer);
10029 mono_metadata_encode_value (slen, p, &p);
10030 memcpy (p, str, slen);
10035 case MONO_TYPE_SZARRAY: {
10037 MonoClass *eclass, *arg_eclass;
10040 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10043 len = mono_array_length ((MonoArray*)arg);
10045 *p++ = (len >> 8) & 0xff;
10046 *p++ = (len >> 16) & 0xff;
10047 *p++ = (len >> 24) & 0xff;
10049 *retbuffer = buffer;
10050 eclass = type->data.klass;
10051 arg_eclass = mono_object_class (arg)->element_class;
10054 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10055 eclass = mono_defaults.object_class;
10057 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10058 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10059 int elsize = mono_class_array_element_size (arg_eclass);
10060 for (i = 0; i < len; ++i) {
10061 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10064 } else if (eclass->valuetype && arg_eclass->valuetype) {
10065 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10066 int elsize = mono_class_array_element_size (eclass);
10067 for (i = 0; i < len; ++i) {
10068 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10072 for (i = 0; i < len; ++i) {
10073 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10078 case MONO_TYPE_OBJECT: {
10084 * The parameter type is 'object' but the type of the actual
10085 * argument is not. So we have to add type information to the blob
10086 * too. This is completely undocumented in the spec.
10090 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10095 klass = mono_object_class (arg);
10097 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10100 } else if (klass->enumtype) {
10102 } else if (klass == mono_defaults.string_class) {
10103 simple_type = MONO_TYPE_STRING;
10106 } else if (klass->rank == 1) {
10108 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10109 /* See Partition II, Appendix B3 */
10112 *p++ = klass->element_class->byval_arg.type;
10113 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10115 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10116 *p++ = simple_type = klass->byval_arg.type;
10119 g_error ("unhandled type in custom attr");
10121 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10122 slen = strlen (str);
10123 if ((p-buffer) + 10 + slen >= *buflen) {
10127 newbuf = (char *)g_realloc (buffer, *buflen);
10128 p = newbuf + (p-buffer);
10131 mono_metadata_encode_value (slen, p, &p);
10132 memcpy (p, str, slen);
10135 simple_type = mono_class_enum_basetype (klass)->type;
10139 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10142 *retbuffer = buffer;
10146 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10148 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10149 char *str = type_get_qualified_name (type, NULL);
10150 int slen = strlen (str);
10154 * This seems to be optional...
10157 mono_metadata_encode_value (slen, p, &p);
10158 memcpy (p, str, slen);
10161 } else if (type->type == MONO_TYPE_OBJECT) {
10163 } else if (type->type == MONO_TYPE_CLASS) {
10164 /* it should be a type: encode_cattr_value () has the check */
10167 mono_metadata_encode_value (type->type, p, &p);
10168 if (type->type == MONO_TYPE_SZARRAY)
10169 /* See the examples in Partition VI, Annex B */
10170 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10176 #ifndef DISABLE_REFLECTION_EMIT
10178 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10181 /* Preallocate a large enough buffer */
10182 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10183 char *str = type_get_qualified_name (type, NULL);
10184 len = strlen (str);
10186 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10187 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10188 len = strlen (str);
10193 len += strlen (name);
10195 if ((p-buffer) + 20 + len >= *buflen) {
10199 newbuf = (char *)g_realloc (buffer, *buflen);
10200 p = newbuf + (p-buffer);
10204 encode_field_or_prop_type (type, p, &p);
10206 len = strlen (name);
10207 mono_metadata_encode_value (len, p, &p);
10208 memcpy (p, name, len);
10210 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10212 *retbuffer = buffer;
10216 * mono_reflection_get_custom_attrs_blob:
10217 * @ctor: custom attribute constructor
10218 * @ctorArgs: arguments o the constructor
10224 * Creates the blob of data that needs to be saved in the metadata and that represents
10225 * the custom attributed described by @ctor, @ctorArgs etc.
10226 * Returns: a Byte array representing the blob of data.
10229 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10232 MonoMethodSignature *sig;
10237 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10238 /* sig is freed later so allocate it in the heap */
10239 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10241 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10244 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10246 p = buffer = (char *)g_malloc (buflen);
10247 /* write the prolog */
10250 for (i = 0; i < sig->param_count; ++i) {
10251 arg = mono_array_get (ctorArgs, MonoObject*, i);
10252 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10256 i += mono_array_length (properties);
10258 i += mono_array_length (fields);
10260 *p++ = (i >> 8) & 0xff;
10263 for (i = 0; i < mono_array_length (properties); ++i) {
10267 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10268 get_prop_name_and_type (prop, &pname, &ptype);
10269 *p++ = 0x54; /* PROPERTY signature */
10270 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10277 for (i = 0; i < mono_array_length (fields); ++i) {
10281 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10282 get_field_name_and_type (field, &fname, &ftype);
10283 *p++ = 0x53; /* FIELD signature */
10284 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10289 g_assert (p - buffer <= buflen);
10290 buflen = p - buffer;
10291 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10292 p = mono_array_addr (result, char, 0);
10293 memcpy (p, buffer, buflen);
10295 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10301 * mono_reflection_setup_internal_class:
10302 * @tb: a TypeBuilder object
10304 * Creates a MonoClass that represents the TypeBuilder.
10305 * This is a trick that lets us simplify a lot of reflection code
10306 * (and will allow us to support Build and Run assemblies easier).
10309 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10312 MonoClass *klass, *parent;
10314 RESOLVE_TYPE (tb->parent);
10316 mono_loader_lock ();
10319 /* check so we can compile corlib correctly */
10320 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10321 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10322 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10324 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10330 /* the type has already being created: it means we just have to change the parent */
10331 if (tb->type.type) {
10332 klass = mono_class_from_mono_type (tb->type.type);
10333 klass->parent = NULL;
10334 /* fool mono_class_setup_parent */
10335 klass->supertypes = NULL;
10336 mono_class_setup_parent (klass, parent);
10337 mono_class_setup_mono_type (klass);
10338 mono_loader_unlock ();
10342 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10344 klass->image = &tb->module->dynamic_image->image;
10346 klass->inited = 1; /* we lie to the runtime */
10347 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10348 if (!mono_error_ok (&error))
10350 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10351 if (!mono_error_ok (&error))
10353 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10354 klass->flags = tb->attrs;
10356 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10358 klass->element_class = klass;
10360 if (mono_class_get_ref_info (klass) == NULL) {
10362 mono_class_set_ref_info (klass, tb);
10364 /* Put into cache so mono_class_get_checked () will find it.
10365 Skip nested types as those should not be available on the global scope. */
10366 if (!tb->nesting_type)
10367 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10370 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10371 by performing a mono_class_get which does the full resolution.
10373 Working around this semantics would require us to write a lot of code for no clear advantage.
10375 mono_image_append_class_to_reflection_info_set (klass);
10377 g_assert (mono_class_get_ref_info (klass) == tb);
10380 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10382 if (parent != NULL) {
10383 mono_class_setup_parent (klass, parent);
10384 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10385 const char *old_n = klass->name;
10386 /* trick to get relative numbering right when compiling corlib */
10387 klass->name = "BuildingObject";
10388 mono_class_setup_parent (klass, mono_defaults.object_class);
10389 klass->name = old_n;
10392 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10393 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10394 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10395 klass->instance_size = sizeof (MonoObject);
10396 klass->size_inited = 1;
10397 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10400 mono_class_setup_mono_type (klass);
10402 mono_class_setup_supertypes (klass);
10405 * FIXME: handle interfaces.
10408 tb->type.type = &klass->byval_arg;
10410 if (tb->nesting_type) {
10411 g_assert (tb->nesting_type->type);
10412 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10415 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10417 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10419 mono_loader_unlock ();
10423 mono_loader_unlock ();
10424 mono_error_raise_exception (&error);
10428 * mono_reflection_setup_generic_class:
10429 * @tb: a TypeBuilder object
10431 * Setup the generic class before adding the first generic parameter.
10434 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10439 * mono_reflection_create_generic_class:
10440 * @tb: a TypeBuilder object
10442 * Creates the generic class after all generic parameters have been added.
10445 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10450 klass = mono_class_from_mono_type (tb->type.type);
10452 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10454 if (klass->generic_container || (count == 0))
10457 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10459 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10461 klass->generic_container->owner.klass = klass;
10462 klass->generic_container->type_argc = count;
10463 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10465 klass->is_generic = 1;
10467 for (i = 0; i < count; i++) {
10468 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10469 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10470 klass->generic_container->type_params [i] = *param;
10471 /*Make sure we are a diferent type instance */
10472 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10473 klass->generic_container->type_params [i].info.pklass = NULL;
10474 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10476 g_assert (klass->generic_container->type_params [i].param.owner);
10479 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10483 * mono_reflection_create_internal_class:
10484 * @tb: a TypeBuilder object
10486 * Actually create the MonoClass that is associated with the TypeBuilder.
10489 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10493 klass = mono_class_from_mono_type (tb->type.type);
10495 mono_loader_lock ();
10496 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10497 MonoReflectionFieldBuilder *fb;
10499 MonoType *enum_basetype;
10501 g_assert (tb->fields != NULL);
10502 g_assert (mono_array_length (tb->fields) >= 1);
10504 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10506 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10507 mono_loader_unlock ();
10511 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10512 klass->element_class = mono_class_from_mono_type (enum_basetype);
10513 if (!klass->element_class)
10514 klass->element_class = mono_class_from_mono_type (enum_basetype);
10517 * get the element_class from the current corlib.
10519 ec = default_class_from_mono_type (enum_basetype);
10520 klass->instance_size = ec->instance_size;
10521 klass->size_inited = 1;
10523 * this is almost safe to do with enums and it's needed to be able
10524 * to create objects of the enum type (for use in SetConstant).
10526 /* FIXME: Does this mean enums can't have method overrides ? */
10527 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10529 mono_loader_unlock ();
10532 static MonoMarshalSpec*
10533 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10534 MonoReflectionMarshal *minfo)
10536 MonoMarshalSpec *res;
10538 res = image_g_new0 (image, MonoMarshalSpec, 1);
10539 res->native = (MonoMarshalNative)minfo->type;
10541 switch (minfo->type) {
10542 case MONO_NATIVE_LPARRAY:
10543 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10544 if (minfo->has_size) {
10545 res->data.array_data.param_num = minfo->param_num;
10546 res->data.array_data.num_elem = minfo->count;
10547 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10550 res->data.array_data.param_num = -1;
10551 res->data.array_data.num_elem = -1;
10552 res->data.array_data.elem_mult = -1;
10556 case MONO_NATIVE_BYVALTSTR:
10557 case MONO_NATIVE_BYVALARRAY:
10558 res->data.array_data.num_elem = minfo->count;
10561 case MONO_NATIVE_CUSTOM:
10562 if (minfo->marshaltyperef)
10563 res->data.custom_data.custom_name =
10564 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10565 if (minfo->mcookie)
10566 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10575 #endif /* !DISABLE_REFLECTION_EMIT */
10577 MonoReflectionMarshalAsAttribute*
10578 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10579 MonoMarshalSpec *spec)
10581 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10582 MonoReflectionMarshalAsAttribute *minfo;
10585 if (!System_Reflection_Emit_MarshalAsAttribute) {
10586 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10587 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10588 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10591 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10592 minfo->utype = spec->native;
10594 switch (minfo->utype) {
10595 case MONO_NATIVE_LPARRAY:
10596 minfo->array_subtype = spec->data.array_data.elem_type;
10597 minfo->size_const = spec->data.array_data.num_elem;
10598 if (spec->data.array_data.param_num != -1)
10599 minfo->size_param_index = spec->data.array_data.param_num;
10602 case MONO_NATIVE_BYVALTSTR:
10603 case MONO_NATIVE_BYVALARRAY:
10604 minfo->size_const = spec->data.array_data.num_elem;
10607 case MONO_NATIVE_CUSTOM:
10608 if (spec->data.custom_data.custom_name) {
10609 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10611 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10613 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10615 if (spec->data.custom_data.cookie)
10616 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10626 #ifndef DISABLE_REFLECTION_EMIT
10628 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10629 ReflectionMethodBuilder *rmb,
10630 MonoMethodSignature *sig)
10634 MonoMethodWrapper *wrapperm;
10635 MonoMarshalSpec **specs;
10636 MonoReflectionMethodAux *method_aux;
10641 mono_error_init (&error);
10643 * Methods created using a MethodBuilder should have their memory allocated
10644 * inside the image mempool, while dynamic methods should have their memory
10647 dynamic = rmb->refs != NULL;
10648 image = dynamic ? NULL : klass->image;
10651 g_assert (!klass->generic_class);
10653 mono_loader_lock ();
10655 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10656 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10657 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10659 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10661 wrapperm = (MonoMethodWrapper*)m;
10663 m->dynamic = dynamic;
10665 m->flags = rmb->attrs;
10666 m->iflags = rmb->iattrs;
10667 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10669 m->signature = sig;
10670 m->sre_method = TRUE;
10671 m->skip_visibility = rmb->skip_visibility;
10672 if (rmb->table_idx)
10673 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10675 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10676 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10677 m->string_ctor = 1;
10679 m->signature->pinvoke = 1;
10680 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10681 m->signature->pinvoke = 1;
10683 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10685 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10686 g_assert (mono_error_ok (&error));
10687 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10688 g_assert (mono_error_ok (&error));
10690 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10692 if (image_is_dynamic (klass->image))
10693 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10695 mono_loader_unlock ();
10698 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10699 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10700 MonoMethodHeader *header;
10702 gint32 max_stack, i;
10703 gint32 num_locals = 0;
10704 gint32 num_clauses = 0;
10708 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10709 code_size = rmb->ilgen->code_len;
10710 max_stack = rmb->ilgen->max_stack;
10711 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10712 if (rmb->ilgen->ex_handlers)
10713 num_clauses = method_count_clauses (rmb->ilgen);
10716 code = mono_array_addr (rmb->code, guint8, 0);
10717 code_size = mono_array_length (rmb->code);
10718 /* we probably need to run a verifier on the code... */
10728 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10729 header->code_size = code_size;
10730 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10731 memcpy ((char*)header->code, code, code_size);
10732 header->max_stack = max_stack;
10733 header->init_locals = rmb->init_locals;
10734 header->num_locals = num_locals;
10736 for (i = 0; i < num_locals; ++i) {
10737 MonoReflectionLocalBuilder *lb =
10738 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10740 header->locals [i] = image_g_new0 (image, MonoType, 1);
10741 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10744 header->num_clauses = num_clauses;
10746 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10747 rmb->ilgen, num_clauses);
10750 wrapperm->header = header;
10753 if (rmb->generic_params) {
10754 int count = mono_array_length (rmb->generic_params);
10755 MonoGenericContainer *container = rmb->generic_container;
10757 g_assert (container);
10759 container->type_argc = count;
10760 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10761 container->owner.method = m;
10762 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10764 m->is_generic = TRUE;
10765 mono_method_set_generic_container (m, container);
10767 for (i = 0; i < count; i++) {
10768 MonoReflectionGenericParam *gp =
10769 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10770 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10771 container->type_params [i] = *param;
10775 * The method signature might have pointers to generic parameters that belong to other methods.
10776 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10777 * generic parameters.
10779 for (i = 0; i < m->signature->param_count; ++i) {
10780 MonoType *t = m->signature->params [i];
10781 if (t->type == MONO_TYPE_MVAR) {
10782 MonoGenericParam *gparam = t->data.generic_param;
10783 if (gparam->num < count) {
10784 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10785 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10791 if (klass->generic_container) {
10792 container->parent = klass->generic_container;
10793 container->context.class_inst = klass->generic_container->context.class_inst;
10795 container->context.method_inst = mono_get_shared_generic_inst (container);
10799 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10803 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10805 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10806 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10807 for (i = 0; i < rmb->nrefs; ++i)
10808 data [i + 1] = rmb->refs [i];
10813 /* Parameter info */
10816 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10817 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10818 for (i = 0; i <= m->signature->param_count; ++i) {
10819 MonoReflectionParamBuilder *pb;
10820 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10821 if ((i > 0) && (pb->attrs)) {
10822 /* Make a copy since it might point to a shared type structure */
10823 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10824 m->signature->params [i - 1]->attrs = pb->attrs;
10827 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10828 MonoDynamicImage *assembly;
10830 MonoTypeEnum def_type;
10834 if (!method_aux->param_defaults) {
10835 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10836 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10838 assembly = (MonoDynamicImage*)klass->image;
10839 idx = encode_constant (assembly, pb->def_value, &def_type);
10840 /* Copy the data from the blob since it might get realloc-ed */
10841 p = assembly->blob.data + idx;
10842 len = mono_metadata_decode_blob_size (p, &p2);
10844 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10845 method_aux->param_default_types [i] = def_type;
10846 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10850 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10851 g_assert (mono_error_ok (&error));
10854 if (!method_aux->param_cattr)
10855 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10856 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10862 /* Parameter marshalling */
10865 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10866 MonoReflectionParamBuilder *pb;
10867 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10868 if (pb->marshal_info) {
10870 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10871 specs [pb->position] =
10872 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10876 if (specs != NULL) {
10878 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10879 method_aux->param_marshall = specs;
10882 if (image_is_dynamic (klass->image) && method_aux)
10883 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10885 mono_loader_unlock ();
10891 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10893 ReflectionMethodBuilder rmb;
10894 MonoMethodSignature *sig;
10896 mono_loader_lock ();
10897 sig = ctor_builder_to_signature (klass->image, mb);
10898 mono_loader_unlock ();
10900 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10902 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10903 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10905 /* If we are in a generic class, we might be called multiple times from inflate_method */
10906 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10907 /* ilgen is no longer needed */
10911 return mb->mhandle;
10915 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10917 ReflectionMethodBuilder rmb;
10918 MonoMethodSignature *sig;
10920 mono_loader_lock ();
10921 sig = method_builder_to_signature (klass->image, mb);
10922 mono_loader_unlock ();
10924 reflection_methodbuilder_from_method_builder (&rmb, mb);
10926 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10927 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10929 /* If we are in a generic class, we might be called multiple times from inflate_method */
10930 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10931 /* ilgen is no longer needed */
10934 return mb->mhandle;
10937 static MonoClassField*
10938 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10940 MonoClassField *field;
10944 field = g_new0 (MonoClassField, 1);
10946 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10947 g_assert (mono_error_ok (&error));
10948 if (fb->attrs || fb->modreq || fb->modopt) {
10949 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10950 field->type->attrs = fb->attrs;
10952 g_assert (image_is_dynamic (klass->image));
10953 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10954 g_free (field->type);
10955 field->type = mono_metadata_type_dup (klass->image, custom);
10958 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10960 if (fb->offset != -1)
10961 field->offset = fb->offset;
10962 field->parent = klass;
10963 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10965 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10972 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10975 MonoReflectionTypeBuilder *tb = NULL;
10976 gboolean is_dynamic = FALSE;
10977 MonoClass *geninst;
10979 mono_loader_lock ();
10981 if (is_sre_type_builder (mono_object_class (type))) {
10982 tb = (MonoReflectionTypeBuilder *) type;
10985 } else if (is_sre_generic_instance (mono_object_class (type))) {
10986 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10987 MonoReflectionType *gtd = rgi->generic_type;
10989 if (is_sre_type_builder (mono_object_class (gtd))) {
10990 tb = (MonoReflectionTypeBuilder *)gtd;
10995 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10996 if (tb && tb->generic_container)
10997 mono_reflection_create_generic_class (tb);
10999 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11000 if (!klass->generic_container) {
11001 mono_loader_unlock ();
11005 if (klass->wastypebuilder) {
11006 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11011 mono_loader_unlock ();
11013 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11015 return &geninst->byval_arg;
11019 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11021 MonoGenericClass *gclass;
11022 MonoGenericInst *inst;
11024 g_assert (klass->generic_container);
11026 inst = mono_metadata_get_generic_inst (type_argc, types);
11027 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11029 return mono_generic_class_get_class (gclass);
11032 MonoReflectionMethod*
11033 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11037 MonoMethod *method, *inflated;
11038 MonoMethodInflated *imethod;
11039 MonoGenericContext tmp_context;
11040 MonoGenericInst *ginst;
11041 MonoType **type_argv;
11044 /*FIXME but this no longer should happen*/
11045 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11046 #ifndef DISABLE_REFLECTION_EMIT
11047 MonoReflectionMethodBuilder *mb = NULL;
11048 MonoReflectionTypeBuilder *tb;
11051 mb = (MonoReflectionMethodBuilder *) rmethod;
11052 tb = (MonoReflectionTypeBuilder *) mb->type;
11053 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11055 method = methodbuilder_to_mono_method (klass, mb);
11057 g_assert_not_reached ();
11061 method = rmethod->method;
11064 klass = method->klass;
11066 if (method->is_inflated)
11067 method = ((MonoMethodInflated *) method)->declaring;
11069 count = mono_method_signature (method)->generic_param_count;
11070 if (count != mono_array_length (types))
11073 type_argv = g_new0 (MonoType *, count);
11074 for (i = 0; i < count; i++) {
11075 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11076 type_argv [i] = mono_reflection_type_get_handle (garg);
11078 ginst = mono_metadata_get_generic_inst (count, type_argv);
11079 g_free (type_argv);
11081 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11082 tmp_context.method_inst = ginst;
11084 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11085 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11086 imethod = (MonoMethodInflated *) inflated;
11088 /*FIXME but I think this is no longer necessary*/
11089 if (image_is_dynamic (method->klass->image)) {
11090 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11092 * This table maps metadata structures representing inflated methods/fields
11093 * to the reflection objects representing their generic definitions.
11095 mono_image_lock ((MonoImage*)image);
11096 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11097 mono_image_unlock ((MonoImage*)image);
11100 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11101 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11103 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11106 #ifndef DISABLE_REFLECTION_EMIT
11108 static MonoMethod *
11109 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11111 MonoMethodInflated *imethod;
11112 MonoGenericContext *context;
11116 * With generic code sharing the klass might not be inflated.
11117 * This can happen because classes inflated with their own
11118 * type arguments are "normalized" to the uninflated class.
11120 if (!klass->generic_class)
11123 context = mono_class_get_context (klass);
11125 if (klass->method.count && klass->methods) {
11126 /* Find the already created inflated method */
11127 for (i = 0; i < klass->method.count; ++i) {
11128 g_assert (klass->methods [i]->is_inflated);
11129 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11132 g_assert (i < klass->method.count);
11133 imethod = (MonoMethodInflated*)klass->methods [i];
11136 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11137 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11140 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11141 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11143 mono_image_lock ((MonoImage*)image);
11144 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11145 mono_image_unlock ((MonoImage*)image);
11147 return (MonoMethod *) imethod;
11150 static MonoMethod *
11151 inflate_method (MonoReflectionType *type, MonoObject *obj)
11153 MonoMethod *method;
11156 MonoClass *type_class = mono_object_class (type);
11158 if (is_sre_generic_instance (type_class)) {
11159 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11160 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11161 } else if (is_sre_type_builder (type_class)) {
11162 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11163 } else if (type->type) {
11164 gklass = mono_class_from_mono_type (type->type);
11165 gklass = mono_class_get_generic_type_definition (gklass);
11167 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11170 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11171 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11172 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11174 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11175 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11176 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11177 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11178 method = ((MonoReflectionMethod *) obj)->method;
11180 method = NULL; /* prevent compiler warning */
11181 g_error ("can't handle type %s", obj->vtable->klass->name);
11184 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11187 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11189 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11191 MonoGenericClass *gclass;
11192 MonoDynamicGenericClass *dgclass;
11193 MonoClass *klass, *gklass;
11197 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11198 klass = mono_class_from_mono_type (gtype);
11199 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11200 gclass = gtype->data.generic_class;
11202 if (!gclass->is_dynamic)
11205 dgclass = (MonoDynamicGenericClass *) gclass;
11207 if (dgclass->initialized)
11210 gklass = gclass->container_class;
11211 mono_class_init (gklass);
11213 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11215 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11216 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11217 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11219 for (i = 0; i < dgclass->count_fields; i++) {
11220 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11221 MonoClassField *field, *inflated_field = NULL;
11223 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11224 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11225 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11226 field = ((MonoReflectionField *) obj)->field;
11228 field = NULL; /* prevent compiler warning */
11229 g_assert_not_reached ();
11232 dgclass->fields [i] = *field;
11233 dgclass->fields [i].parent = klass;
11234 dgclass->fields [i].type = mono_class_inflate_generic_type (
11235 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11236 dgclass->field_generic_types [i] = field->type;
11237 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11238 dgclass->field_objects [i] = obj;
11240 if (inflated_field) {
11241 g_free (inflated_field);
11243 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11247 dgclass->initialized = TRUE;
11251 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11253 MonoDynamicGenericClass *dgclass;
11256 g_assert (gclass->is_dynamic);
11258 dgclass = (MonoDynamicGenericClass *)gclass;
11260 for (i = 0; i < dgclass->count_fields; ++i) {
11261 MonoClassField *field = dgclass->fields + i;
11262 mono_metadata_free_type (field->type);
11263 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11268 fix_partial_generic_class (MonoClass *klass)
11270 MonoClass *gklass = klass->generic_class->container_class;
11271 MonoDynamicGenericClass *dgclass;
11274 if (klass->wastypebuilder)
11277 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11278 if (klass->parent != gklass->parent) {
11280 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11281 if (mono_error_ok (&error)) {
11282 MonoClass *parent = mono_class_from_mono_type (parent_type);
11283 mono_metadata_free_type (parent_type);
11284 if (parent != klass->parent) {
11285 /*fool mono_class_setup_parent*/
11286 klass->supertypes = NULL;
11287 mono_class_setup_parent (klass, parent);
11290 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11291 mono_error_cleanup (&error);
11292 if (gklass->wastypebuilder)
11293 klass->wastypebuilder = TRUE;
11298 if (!dgclass->initialized)
11301 if (klass->method.count != gklass->method.count) {
11302 klass->method.count = gklass->method.count;
11303 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11305 for (i = 0; i < klass->method.count; i++) {
11307 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11308 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11309 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11313 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11314 klass->interface_count = gklass->interface_count;
11315 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11316 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11318 for (i = 0; i < gklass->interface_count; ++i) {
11319 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11320 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11321 mono_metadata_free_type (iface_type);
11323 ensure_runtime_vtable (klass->interfaces [i]);
11325 klass->interfaces_inited = 1;
11328 if (klass->field.count != gklass->field.count) {
11329 klass->field.count = gklass->field.count;
11330 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11332 for (i = 0; i < klass->field.count; i++) {
11333 klass->fields [i] = gklass->fields [i];
11334 klass->fields [i].parent = klass;
11335 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11339 /*We can only finish with this klass once it's parent has as well*/
11340 if (gklass->wastypebuilder)
11341 klass->wastypebuilder = TRUE;
11346 ensure_generic_class_runtime_vtable (MonoClass *klass)
11348 MonoClass *gklass = klass->generic_class->container_class;
11350 ensure_runtime_vtable (gklass);
11352 fix_partial_generic_class (klass);
11356 ensure_runtime_vtable (MonoClass *klass)
11358 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11361 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11364 ensure_runtime_vtable (klass->parent);
11367 num = tb->ctors? mono_array_length (tb->ctors): 0;
11368 num += tb->num_methods;
11369 klass->method.count = num;
11370 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11371 num = tb->ctors? mono_array_length (tb->ctors): 0;
11372 for (i = 0; i < num; ++i)
11373 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11374 num = tb->num_methods;
11376 for (i = 0; i < num; ++i)
11377 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11379 if (tb->interfaces) {
11380 klass->interface_count = mono_array_length (tb->interfaces);
11381 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11382 for (i = 0; i < klass->interface_count; ++i) {
11383 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11384 klass->interfaces [i] = mono_class_from_mono_type (iface);
11385 ensure_runtime_vtable (klass->interfaces [i]);
11387 klass->interfaces_inited = 1;
11389 } else if (klass->generic_class){
11390 ensure_generic_class_runtime_vtable (klass);
11393 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11395 for (i = 0; i < klass->method.count; ++i) {
11396 MonoMethod *im = klass->methods [i];
11397 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11398 im->slot = slot_num++;
11401 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11402 mono_class_setup_interface_offsets (klass);
11403 mono_class_setup_interface_id (klass);
11407 * The generic vtable is needed even if image->run is not set since some
11408 * runtime code like ves_icall_Type_GetMethodsByName depends on
11409 * method->slot being defined.
11413 * tb->methods could not be freed since it is used for determining
11414 * overrides during dynamic vtable construction.
11419 mono_reflection_method_get_handle (MonoObject *method)
11421 MonoClass *klass = mono_object_class (method);
11422 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11423 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11424 return sr_method->method;
11426 if (is_sre_method_builder (klass)) {
11427 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11428 return mb->mhandle;
11430 if (is_sre_method_on_tb_inst (klass)) {
11431 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11432 MonoMethod *result;
11433 /*FIXME move this to a proper method and unify with resolve_object*/
11434 if (m->method_args) {
11435 result = mono_reflection_method_on_tb_inst_get_handle (m);
11437 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11438 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11439 MonoMethod *mono_method;
11441 if (is_sre_method_builder (mono_object_class (m->mb)))
11442 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11443 else if (is_sr_mono_method (mono_object_class (m->mb)))
11444 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11446 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)));
11448 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11453 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11458 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11460 MonoReflectionTypeBuilder *tb;
11462 MonoReflectionMethod *m;
11465 *num_overrides = 0;
11467 g_assert (image_is_dynamic (klass->image));
11469 if (!mono_class_get_ref_info (klass))
11472 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11474 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
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 onum += mono_array_length (mb->override_methods);
11487 *overrides = g_new0 (MonoMethod*, onum * 2);
11490 for (i = 0; i < tb->num_methods; ++i) {
11491 MonoReflectionMethodBuilder *mb =
11492 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11493 if (mb->override_methods) {
11494 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11495 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11497 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11498 (*overrides) [onum * 2 + 1] = mb->mhandle;
11500 g_assert (mb->mhandle);
11508 *num_overrides = onum;
11512 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11515 MonoReflectionFieldBuilder *fb;
11516 MonoClassField *field;
11517 MonoImage *image = klass->image;
11518 const char *p, *p2;
11520 guint32 len, idx, real_size = 0;
11522 klass->field.count = tb->num_fields;
11523 klass->field.first = 0;
11525 mono_error_init (error);
11527 if (tb->class_size) {
11528 if ((tb->packing_size & 0xffffff00) != 0) {
11529 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11530 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11533 klass->packing_size = tb->packing_size;
11534 real_size = klass->instance_size + tb->class_size;
11537 if (!klass->field.count) {
11538 klass->instance_size = MAX (klass->instance_size, real_size);
11542 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11543 mono_class_alloc_ext (klass);
11544 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11546 This is, guess what, a hack.
11547 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11548 On the static path no field class is resolved, only types are built. This is the right thing to do
11550 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11552 klass->size_inited = 1;
11554 for (i = 0; i < klass->field.count; ++i) {
11555 MonoArray *rva_data;
11556 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11557 field = &klass->fields [i];
11558 field->name = mono_string_to_utf8_image (image, fb->name, error);
11559 if (!mono_error_ok (error))
11562 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11563 field->type->attrs = fb->attrs;
11565 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11568 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11569 char *base = mono_array_addr (rva_data, char, 0);
11570 size_t size = mono_array_length (rva_data);
11571 char *data = (char *)mono_image_alloc (klass->image, size);
11572 memcpy (data, base, size);
11573 klass->ext->field_def_values [i].data = data;
11575 if (fb->offset != -1)
11576 field->offset = fb->offset;
11577 field->parent = klass;
11578 fb->handle = field;
11579 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11581 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11582 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11584 if (fb->def_value) {
11585 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11586 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11587 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11588 /* Copy the data from the blob since it might get realloc-ed */
11589 p = assembly->blob.data + idx;
11590 len = mono_metadata_decode_blob_size (p, &p2);
11592 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11593 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11597 klass->instance_size = MAX (klass->instance_size, real_size);
11598 mono_class_layout_fields (klass);
11602 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11604 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11605 MonoReflectionPropertyBuilder *pb;
11606 MonoImage *image = klass->image;
11607 MonoProperty *properties;
11610 mono_error_init (error);
11613 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11615 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11616 klass->ext->property.first = 0;
11618 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11619 klass->ext->properties = properties;
11620 for (i = 0; i < klass->ext->property.count; ++i) {
11621 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11622 properties [i].parent = klass;
11623 properties [i].attrs = pb->attrs;
11624 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11625 if (!mono_error_ok (error))
11627 if (pb->get_method)
11628 properties [i].get = pb->get_method->mhandle;
11629 if (pb->set_method)
11630 properties [i].set = pb->set_method->mhandle;
11632 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11633 if (pb->def_value) {
11635 const char *p, *p2;
11636 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11637 if (!klass->ext->prop_def_values)
11638 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11639 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11640 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11641 /* Copy the data from the blob since it might get realloc-ed */
11642 p = assembly->blob.data + idx;
11643 len = mono_metadata_decode_blob_size (p, &p2);
11645 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11646 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11651 MonoReflectionEvent *
11652 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11654 MonoEvent *event = g_new0 (MonoEvent, 1);
11657 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11659 event->parent = klass;
11660 event->attrs = eb->attrs;
11661 event->name = mono_string_to_utf8 (eb->name);
11662 if (eb->add_method)
11663 event->add = eb->add_method->mhandle;
11664 if (eb->remove_method)
11665 event->remove = eb->remove_method->mhandle;
11666 if (eb->raise_method)
11667 event->raise = eb->raise_method->mhandle;
11669 #ifndef MONO_SMALL_CONFIG
11670 if (eb->other_methods) {
11672 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11673 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11674 MonoReflectionMethodBuilder *mb =
11675 mono_array_get (eb->other_methods,
11676 MonoReflectionMethodBuilder*, j);
11677 event->other [j] = mb->mhandle;
11682 return mono_event_get_object (mono_object_domain (tb), klass, event);
11686 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11688 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11689 MonoReflectionEventBuilder *eb;
11690 MonoImage *image = klass->image;
11694 mono_error_init (error);
11697 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11699 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11700 klass->ext->event.first = 0;
11702 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11703 klass->ext->events = events;
11704 for (i = 0; i < klass->ext->event.count; ++i) {
11705 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11706 events [i].parent = klass;
11707 events [i].attrs = eb->attrs;
11708 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11709 if (!mono_error_ok (error))
11711 if (eb->add_method)
11712 events [i].add = eb->add_method->mhandle;
11713 if (eb->remove_method)
11714 events [i].remove = eb->remove_method->mhandle;
11715 if (eb->raise_method)
11716 events [i].raise = eb->raise_method->mhandle;
11718 #ifndef MONO_SMALL_CONFIG
11719 if (eb->other_methods) {
11721 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11722 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11723 MonoReflectionMethodBuilder *mb =
11724 mono_array_get (eb->other_methods,
11725 MonoReflectionMethodBuilder*, j);
11726 events [i].other [j] = mb->mhandle;
11730 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11735 remove_instantiations_of_and_ensure_contents (gpointer key,
11737 gpointer user_data)
11739 MonoType *type = (MonoType*)key;
11740 MonoClass *klass = (MonoClass*)user_data;
11742 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11743 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11750 check_array_for_usertypes (MonoArray *arr)
11757 for (i = 0; i < mono_array_length (arr); ++i)
11758 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11761 MonoReflectionType*
11762 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11766 MonoDomain* domain;
11767 MonoReflectionType* res;
11770 domain = mono_object_domain (tb);
11771 klass = mono_class_from_mono_type (tb->type.type);
11774 * Check for user defined Type subclasses.
11776 RESOLVE_TYPE (tb->parent);
11777 check_array_for_usertypes (tb->interfaces);
11779 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11780 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11782 RESOLVE_TYPE (fb->type);
11783 check_array_for_usertypes (fb->modreq);
11784 check_array_for_usertypes (fb->modopt);
11785 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11786 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11791 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11792 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11794 RESOLVE_TYPE (mb->rtype);
11795 check_array_for_usertypes (mb->return_modreq);
11796 check_array_for_usertypes (mb->return_modopt);
11797 check_array_for_usertypes (mb->parameters);
11798 if (mb->param_modreq)
11799 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11800 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11801 if (mb->param_modopt)
11802 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11803 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11808 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11809 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11811 check_array_for_usertypes (mb->parameters);
11812 if (mb->param_modreq)
11813 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11814 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11815 if (mb->param_modopt)
11816 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11817 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11822 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11825 * we need to lock the domain because the lock will be taken inside
11826 * So, we need to keep the locking order correct.
11828 mono_loader_lock ();
11829 mono_domain_lock (domain);
11830 if (klass->wastypebuilder) {
11831 mono_domain_unlock (domain);
11832 mono_loader_unlock ();
11833 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11836 * Fields to set in klass:
11837 * the various flags: delegate/unicode/contextbound etc.
11839 klass->flags = tb->attrs;
11840 klass->has_cctor = 1;
11841 klass->has_finalize = 1;
11842 klass->has_finalize_inited = 1;
11844 mono_class_setup_parent (klass, klass->parent);
11845 /* fool mono_class_setup_supertypes */
11846 klass->supertypes = NULL;
11847 mono_class_setup_supertypes (klass);
11848 mono_class_setup_mono_type (klass);
11851 if (!((MonoDynamicImage*)klass->image)->run) {
11852 if (klass->generic_container) {
11853 /* FIXME: The code below can't handle generic classes */
11854 klass->wastypebuilder = TRUE;
11855 mono_loader_unlock ();
11856 mono_domain_unlock (domain);
11857 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11862 /* enums are done right away */
11863 if (!klass->enumtype)
11864 ensure_runtime_vtable (klass);
11866 if (tb->subtypes) {
11867 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11868 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11869 mono_class_alloc_ext (klass);
11870 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)));
11874 klass->nested_classes_inited = TRUE;
11876 /* fields and object layout */
11877 if (klass->parent) {
11878 if (!klass->parent->size_inited)
11879 mono_class_init (klass->parent);
11880 klass->instance_size = klass->parent->instance_size;
11881 klass->sizes.class_size = 0;
11882 klass->min_align = klass->parent->min_align;
11883 /* if the type has no fields we won't call the field_setup
11884 * routine which sets up klass->has_references.
11886 klass->has_references |= klass->parent->has_references;
11888 klass->instance_size = sizeof (MonoObject);
11889 klass->min_align = 1;
11892 /* FIXME: handle packing_size and instance_size */
11893 typebuilder_setup_fields (klass, &error);
11894 if (!mono_error_ok (&error))
11896 typebuilder_setup_properties (klass, &error);
11897 if (!mono_error_ok (&error))
11900 typebuilder_setup_events (klass, &error);
11901 if (!mono_error_ok (&error))
11904 klass->wastypebuilder = TRUE;
11907 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11908 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11909 * we want to return normal System.MonoType objects, so clear these out from the cache.
11911 * Together with this we must ensure the contents of all instances to match the created type.
11913 if (domain->type_hash && klass->generic_container)
11914 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11916 mono_domain_unlock (domain);
11917 mono_loader_unlock ();
11919 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11920 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11921 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11924 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11925 g_assert (res != (MonoReflectionType*)tb);
11930 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11931 klass->wastypebuilder = TRUE;
11932 mono_domain_unlock (domain);
11933 mono_loader_unlock ();
11934 mono_error_raise_exception (&error);
11939 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11941 MonoGenericParamFull *param;
11946 image = &gparam->tbuilder->module->dynamic_image->image;
11948 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11950 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11951 g_assert (mono_error_ok (&error));
11952 param->param.num = gparam->index;
11954 if (gparam->mbuilder) {
11955 if (!gparam->mbuilder->generic_container) {
11956 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11957 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11958 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11959 gparam->mbuilder->generic_container->is_method = TRUE;
11961 * Cannot set owner.method, since the MonoMethod is not created yet.
11962 * Set the image field instead, so type_in_image () works.
11964 gparam->mbuilder->generic_container->is_anonymous = TRUE;
11965 gparam->mbuilder->generic_container->owner.image = klass->image;
11967 param->param.owner = gparam->mbuilder->generic_container;
11968 } else if (gparam->tbuilder) {
11969 if (!gparam->tbuilder->generic_container) {
11970 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11971 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11972 gparam->tbuilder->generic_container->owner.klass = klass;
11974 param->param.owner = gparam->tbuilder->generic_container;
11977 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
11979 gparam->type.type = &pklass->byval_arg;
11981 mono_class_set_ref_info (pklass, gparam);
11982 mono_image_append_class_to_reflection_info_set (pklass);
11986 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11988 MonoReflectionModuleBuilder *module = sig->module;
11989 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11990 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11995 check_array_for_usertypes (sig->arguments);
11997 sigbuffer_init (&buf, 32);
11999 sigbuffer_add_value (&buf, 0x07);
12000 sigbuffer_add_value (&buf, na);
12001 if (assembly != NULL){
12002 for (i = 0; i < na; ++i) {
12003 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12004 encode_reflection_type (assembly, type, &buf);
12008 buflen = buf.p - buf.buf;
12009 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12010 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12011 sigbuffer_free (&buf);
12017 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12019 MonoDynamicImage *assembly = sig->module->dynamic_image;
12020 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12025 check_array_for_usertypes (sig->arguments);
12027 sigbuffer_init (&buf, 32);
12029 sigbuffer_add_value (&buf, 0x06);
12030 for (i = 0; i < na; ++i) {
12031 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12032 encode_reflection_type (assembly, type, &buf);
12035 buflen = buf.p - buf.buf;
12036 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12037 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12038 sigbuffer_free (&buf);
12044 MonoMethod *handle;
12045 MonoDomain *domain;
12046 } DynamicMethodReleaseData;
12049 * The runtime automatically clean up those after finalization.
12051 static MonoReferenceQueue *dynamic_method_queue;
12054 free_dynamic_method (void *dynamic_method)
12056 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12057 MonoDomain *domain = data->domain;
12058 MonoMethod *method = data->handle;
12061 mono_domain_lock (domain);
12062 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12063 g_hash_table_remove (domain->method_to_dyn_method, method);
12064 mono_domain_unlock (domain);
12065 g_assert (dis_link);
12066 mono_gchandle_free (dis_link);
12068 mono_runtime_free_method (domain, method);
12073 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12075 MonoReferenceQueue *queue;
12076 MonoMethod *handle;
12077 DynamicMethodReleaseData *release_data;
12078 ReflectionMethodBuilder rmb;
12079 MonoMethodSignature *sig;
12081 MonoDomain *domain;
12085 if (mono_runtime_is_shutting_down ())
12086 mono_raise_exception (mono_get_exception_invalid_operation (""));
12088 if (!(queue = dynamic_method_queue)) {
12089 mono_loader_lock ();
12090 if (!(queue = dynamic_method_queue))
12091 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12092 mono_loader_unlock ();
12095 sig = dynamic_method_to_signature (mb);
12097 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12100 * Resolve references.
12103 * Every second entry in the refs array is reserved for storing handle_class,
12104 * which is needed by the ldtoken implementation in the JIT.
12106 rmb.nrefs = mb->nrefs;
12107 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12108 for (i = 0; i < mb->nrefs; i += 2) {
12109 MonoClass *handle_class;
12111 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12113 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12114 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12116 * The referenced DynamicMethod should already be created by the managed
12117 * code, except in the case of circular references. In that case, we store
12118 * method in the refs array, and fix it up later when the referenced
12119 * DynamicMethod is created.
12121 if (method->mhandle) {
12122 ref = method->mhandle;
12124 /* FIXME: GC object stored in unmanaged memory */
12127 /* FIXME: GC object stored in unmanaged memory */
12128 method->referenced_by = g_slist_append (method->referenced_by, mb);
12130 handle_class = mono_defaults.methodhandle_class;
12132 MonoException *ex = NULL;
12133 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12135 ex = mono_get_exception_type_load (NULL, NULL);
12136 else if (mono_security_core_clr_enabled ())
12137 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12141 mono_raise_exception (ex);
12146 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12147 rmb.refs [i + 1] = handle_class;
12150 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12152 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12153 release_data = g_new (DynamicMethodReleaseData, 1);
12154 release_data->handle = handle;
12155 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12156 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12157 g_free (release_data);
12159 /* Fix up refs entries pointing at us */
12160 for (l = mb->referenced_by; l; l = l->next) {
12161 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12162 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12165 g_assert (method->mhandle);
12167 data = (gpointer*)wrapper->method_data;
12168 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12169 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12170 data [i + 1] = mb->mhandle;
12173 g_slist_free (mb->referenced_by);
12177 /* ilgen is no longer needed */
12180 domain = mono_domain_get ();
12181 mono_domain_lock (domain);
12182 if (!domain->method_to_dyn_method)
12183 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12184 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12185 mono_domain_unlock (domain);
12188 #endif /* DISABLE_REFLECTION_EMIT */
12192 * mono_reflection_is_valid_dynamic_token:
12194 * Returns TRUE if token is valid.
12198 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12200 return lookup_dyn_token (image, token) != NULL;
12203 MonoMethodSignature *
12204 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12206 MonoMethodSignature *sig;
12207 g_assert (image_is_dynamic (image));
12209 mono_error_init (error);
12211 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12215 return mono_method_signature_checked (method, error);
12218 #ifndef DISABLE_REFLECTION_EMIT
12221 * mono_reflection_lookup_dynamic_token:
12223 * Finish the Builder object pointed to by TOKEN and return the corresponding
12224 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12225 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12228 * LOCKING: Take the loader lock
12231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12233 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12237 obj = lookup_dyn_token (assembly, token);
12240 g_error ("Could not find required dynamic token 0x%08x", token);
12246 handle_class = &klass;
12247 return resolve_object (image, obj, handle_class, context);
12251 * ensure_complete_type:
12253 * Ensure that KLASS is completed if it is a dynamic type, or references
12257 ensure_complete_type (MonoClass *klass)
12259 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12260 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12262 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12264 // Asserting here could break a lot of code
12265 //g_assert (klass->wastypebuilder);
12268 if (klass->generic_class) {
12269 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12272 for (i = 0; i < inst->type_argc; ++i) {
12273 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12279 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12281 gpointer result = NULL;
12283 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12284 result = mono_string_intern ((MonoString*)obj);
12285 *handle_class = mono_defaults.string_class;
12287 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12288 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12289 MonoClass *mc = mono_class_from_mono_type (type);
12290 if (!mono_class_init (mc))
12291 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12294 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12295 result = mono_class_from_mono_type (inflated);
12296 mono_metadata_free_type (inflated);
12298 result = mono_class_from_mono_type (type);
12300 *handle_class = mono_defaults.typehandle_class;
12302 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12303 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12304 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12305 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12306 result = ((MonoReflectionMethod*)obj)->method;
12309 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12310 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12312 *handle_class = mono_defaults.methodhandle_class;
12314 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12315 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12316 result = mb->mhandle;
12318 /* Type is not yet created */
12319 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12321 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12324 * Hopefully this has been filled in by calling CreateType() on the
12328 * TODO: This won't work if the application finishes another
12329 * TypeBuilder instance instead of this one.
12331 result = mb->mhandle;
12335 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12336 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12338 *handle_class = mono_defaults.methodhandle_class;
12339 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12340 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12342 result = cb->mhandle;
12344 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12346 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12347 result = cb->mhandle;
12351 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12352 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12354 *handle_class = mono_defaults.methodhandle_class;
12355 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12356 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12358 ensure_complete_type (field->parent);
12360 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12361 MonoClass *klass = mono_class_from_mono_type (inflated);
12362 MonoClassField *inflated_field;
12363 gpointer iter = NULL;
12364 mono_metadata_free_type (inflated);
12365 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12366 if (!strcmp (field->name, inflated_field->name))
12369 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12370 result = inflated_field;
12374 *handle_class = mono_defaults.fieldhandle_class;
12376 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12377 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12378 result = fb->handle;
12381 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12383 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12384 result = fb->handle;
12387 if (fb->handle && fb->handle->parent->generic_container) {
12388 MonoClass *klass = fb->handle->parent;
12389 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12390 MonoClass *inflated = mono_class_from_mono_type (type);
12392 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12394 mono_metadata_free_type (type);
12396 *handle_class = mono_defaults.fieldhandle_class;
12397 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12398 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12399 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12402 klass = type->data.klass;
12403 if (klass->wastypebuilder) {
12404 /* Already created */
12408 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12409 result = type->data.klass;
12412 *handle_class = mono_defaults.typehandle_class;
12413 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12414 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12415 MonoMethodSignature *sig;
12418 if (helper->arguments)
12419 nargs = mono_array_length (helper->arguments);
12423 sig = mono_metadata_signature_alloc (image, nargs);
12424 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12425 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12427 if (helper->unmanaged_call_conv) { /* unmanaged */
12428 sig->call_convention = helper->unmanaged_call_conv - 1;
12429 sig->pinvoke = TRUE;
12430 } else if (helper->call_conv & 0x02) {
12431 sig->call_convention = MONO_CALL_VARARG;
12433 sig->call_convention = MONO_CALL_DEFAULT;
12436 sig->param_count = nargs;
12437 /* TODO: Copy type ? */
12438 sig->ret = helper->return_type->type;
12439 for (i = 0; i < nargs; ++i)
12440 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12443 *handle_class = NULL;
12444 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12445 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12446 /* Already created by the managed code */
12447 g_assert (method->mhandle);
12448 result = method->mhandle;
12449 *handle_class = mono_defaults.methodhandle_class;
12450 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12451 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12452 type = mono_class_inflate_generic_type (type, context);
12453 result = mono_class_from_mono_type (type);
12454 *handle_class = mono_defaults.typehandle_class;
12456 mono_metadata_free_type (type);
12457 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12458 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12459 type = mono_class_inflate_generic_type (type, context);
12460 result = mono_class_from_mono_type (type);
12461 *handle_class = mono_defaults.typehandle_class;
12463 mono_metadata_free_type (type);
12464 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12465 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12466 MonoClass *inflated;
12468 MonoClassField *field;
12470 if (is_sre_field_builder (mono_object_class (f->fb)))
12471 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12472 else if (is_sr_mono_field (mono_object_class (f->fb)))
12473 field = ((MonoReflectionField*)f->fb)->field;
12475 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)));
12477 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12478 inflated = mono_class_from_mono_type (type);
12480 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12481 ensure_complete_type (field->parent);
12483 mono_metadata_free_type (type);
12484 *handle_class = mono_defaults.fieldhandle_class;
12485 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12486 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12487 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12488 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12489 MonoMethod *method;
12491 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12492 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12493 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12494 method = ((MonoReflectionMethod *)c->cb)->method;
12496 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)));
12498 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12499 *handle_class = mono_defaults.methodhandle_class;
12500 mono_metadata_free_type (type);
12501 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12502 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12503 if (m->method_args) {
12504 result = mono_reflection_method_on_tb_inst_get_handle (m);
12507 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12508 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12511 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12512 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12513 MonoMethod *method;
12515 if (is_sre_method_builder (mono_object_class (m->mb)))
12516 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12517 else if (is_sr_mono_method (mono_object_class (m->mb)))
12518 method = ((MonoReflectionMethod *)m->mb)->method;
12520 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)));
12522 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12523 mono_metadata_free_type (type);
12525 *handle_class = mono_defaults.methodhandle_class;
12526 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12527 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12530 MonoMethod *method;
12534 mtype = mono_reflection_type_get_handle (m->parent);
12535 klass = mono_class_from_mono_type (mtype);
12537 /* Find the method */
12539 name = mono_string_to_utf8 (m->name);
12541 while ((method = mono_class_get_methods (klass, &iter))) {
12542 if (!strcmp (method->name, name))
12549 // FIXME: Check parameters/return value etc. match
12552 *handle_class = mono_defaults.methodhandle_class;
12553 } else if (is_sre_array (mono_object_get_class(obj)) ||
12554 is_sre_byref (mono_object_get_class(obj)) ||
12555 is_sre_pointer (mono_object_get_class(obj))) {
12556 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12557 MonoType *type = mono_reflection_type_get_handle (ref_type);
12560 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12561 result = mono_class_from_mono_type (inflated);
12562 mono_metadata_free_type (inflated);
12564 result = mono_class_from_mono_type (type);
12566 *handle_class = mono_defaults.typehandle_class;
12568 g_print ("%s\n", obj->vtable->klass->name);
12569 g_assert_not_reached ();
12574 #else /* DISABLE_REFLECTION_EMIT */
12577 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12579 g_assert_not_reached ();
12584 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12586 g_assert_not_reached ();
12590 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12592 g_assert_not_reached ();
12596 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12598 g_assert_not_reached ();
12602 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12604 g_assert_not_reached ();
12608 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12610 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12614 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12616 g_assert_not_reached ();
12620 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12622 g_assert_not_reached ();
12625 MonoReflectionModule *
12626 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12628 g_assert_not_reached ();
12633 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12635 g_assert_not_reached ();
12640 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12642 g_assert_not_reached ();
12647 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12648 gboolean create_open_instance, gboolean register_token)
12650 g_assert_not_reached ();
12655 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12660 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12662 g_assert_not_reached ();
12666 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12669 *num_overrides = 0;
12672 MonoReflectionEvent *
12673 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12675 g_assert_not_reached ();
12679 MonoReflectionType*
12680 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12682 g_assert_not_reached ();
12687 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12689 g_assert_not_reached ();
12693 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12695 g_assert_not_reached ();
12700 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12702 g_assert_not_reached ();
12707 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12712 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12718 mono_reflection_type_get_handle (MonoReflectionType* ref)
12726 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12728 g_assert_not_reached ();
12731 #endif /* DISABLE_REFLECTION_EMIT */
12733 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12734 const static guint32 declsec_flags_map[] = {
12735 0x00000000, /* empty */
12736 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12737 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12738 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12739 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12740 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12741 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12742 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12743 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12744 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12745 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12746 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12747 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12748 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12749 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12750 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12751 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12752 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12753 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12757 * Returns flags that includes all available security action associated to the handle.
12758 * @token: metadata token (either for a class or a method)
12759 * @image: image where resides the metadata.
12762 mono_declsec_get_flags (MonoImage *image, guint32 token)
12764 int index = mono_metadata_declsec_from_index (image, token);
12765 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12766 guint32 result = 0;
12770 /* HasSecurity can be present for other, not specially encoded, attributes,
12771 e.g. SuppressUnmanagedCodeSecurityAttribute */
12775 for (i = index; i < t->rows; i++) {
12776 guint32 cols [MONO_DECL_SECURITY_SIZE];
12778 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12779 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12782 action = cols [MONO_DECL_SECURITY_ACTION];
12783 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12784 result |= declsec_flags_map [action];
12786 g_assert_not_reached ();
12793 * Get the security actions (in the form of flags) associated with the specified method.
12795 * @method: The method for which we want the declarative security flags.
12796 * Return the declarative security flags for the method (only).
12798 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12799 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12802 mono_declsec_flags_from_method (MonoMethod *method)
12804 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12805 /* FIXME: No cache (for the moment) */
12806 guint32 idx = mono_method_get_index (method);
12807 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12808 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12809 return mono_declsec_get_flags (method->klass->image, idx);
12815 * Get the security actions (in the form of flags) associated with the specified class.
12817 * @klass: The class for which we want the declarative security flags.
12818 * Return the declarative security flags for the class.
12820 * Note: We cache the flags inside the MonoClass structure as this will get
12821 * called very often (at least for each method).
12824 mono_declsec_flags_from_class (MonoClass *klass)
12826 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12827 if (!klass->ext || !klass->ext->declsec_flags) {
12830 idx = mono_metadata_token_index (klass->type_token);
12831 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12832 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12833 mono_loader_lock ();
12834 mono_class_alloc_ext (klass);
12835 mono_loader_unlock ();
12836 /* we cache the flags on classes */
12837 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12839 return klass->ext->declsec_flags;
12845 * Get the security actions (in the form of flags) associated with the specified assembly.
12847 * @assembly: The assembly for which we want the declarative security flags.
12848 * Return the declarative security flags for the assembly.
12851 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12853 guint32 idx = 1; /* there is only one assembly */
12854 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12855 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12856 return mono_declsec_get_flags (assembly->image, idx);
12861 * Fill actions for the specific index (which may either be an encoded class token or
12862 * an encoded method token) from the metadata image.
12863 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12866 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12867 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12869 MonoBoolean result = FALSE;
12871 guint32 cols [MONO_DECL_SECURITY_SIZE];
12872 int index = mono_metadata_declsec_from_index (image, token);
12875 t = &image->tables [MONO_TABLE_DECLSECURITY];
12876 for (i = index; i < t->rows; i++) {
12877 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12879 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12882 /* if present only replace (class) permissions with method permissions */
12883 /* if empty accept either class or method permissions */
12884 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12885 if (!actions->demand.blob) {
12886 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12887 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12888 actions->demand.blob = (char*) (blob + 2);
12889 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12892 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12893 if (!actions->noncasdemand.blob) {
12894 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12895 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12896 actions->noncasdemand.blob = (char*) (blob + 2);
12897 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12900 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12901 if (!actions->demandchoice.blob) {
12902 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12903 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12904 actions->demandchoice.blob = (char*) (blob + 2);
12905 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12915 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12916 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12918 guint32 idx = mono_metadata_token_index (klass->type_token);
12919 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12920 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12921 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12925 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12926 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12928 guint32 idx = mono_method_get_index (method);
12929 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12930 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12931 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12935 * Collect all actions (that requires to generate code in mini) assigned for
12936 * the specified method.
12937 * Note: Don't use the content of actions if the function return FALSE.
12940 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12942 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12943 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12944 MonoBoolean result = FALSE;
12947 /* quick exit if no declarative security is present in the metadata */
12948 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12951 /* we want the original as the wrapper is "free" of the security informations */
12952 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12953 method = mono_marshal_method_from_wrapper (method);
12958 /* First we look for method-level attributes */
12959 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12960 mono_class_init (method->klass);
12961 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12963 result = mono_declsec_get_method_demands_params (method, demands,
12964 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12967 /* Here we use (or create) the class declarative cache to look for demands */
12968 flags = mono_declsec_flags_from_class (method->klass);
12969 if (flags & mask) {
12971 mono_class_init (method->klass);
12972 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12974 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12975 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12978 /* The boolean return value is used as a shortcut in case nothing needs to
12979 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12985 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12987 * Note: Don't use the content of actions if the function return FALSE.
12990 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12992 MonoBoolean result = FALSE;
12995 /* quick exit if no declarative security is present in the metadata */
12996 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12999 /* we want the original as the wrapper is "free" of the security informations */
13000 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13001 method = mono_marshal_method_from_wrapper (method);
13006 /* results are independant - zeroize both */
13007 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13008 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13010 /* First we look for method-level attributes */
13011 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13012 mono_class_init (method->klass);
13014 result = mono_declsec_get_method_demands_params (method, cmethod,
13015 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13018 /* Here we use (or create) the class declarative cache to look for demands */
13019 flags = mono_declsec_flags_from_class (method->klass);
13020 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13021 mono_class_init (method->klass);
13023 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13024 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13031 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13033 * @klass The inherited class - this is the class that provides the security check (attributes)
13035 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13037 * Note: Don't use the content of actions if the function return FALSE.
13040 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13042 MonoBoolean result = FALSE;
13045 /* quick exit if no declarative security is present in the metadata */
13046 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13049 /* Here we use (or create) the class declarative cache to look for demands */
13050 flags = mono_declsec_flags_from_class (klass);
13051 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13052 mono_class_init (klass);
13053 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13055 result |= mono_declsec_get_class_demands_params (klass, demands,
13056 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13063 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13065 * Note: Don't use the content of actions if the function return FALSE.
13068 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13070 /* quick exit if no declarative security is present in the metadata */
13071 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13074 /* we want the original as the wrapper is "free" of the security informations */
13075 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13076 method = mono_marshal_method_from_wrapper (method);
13081 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13082 mono_class_init (method->klass);
13083 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13085 return mono_declsec_get_method_demands_params (method, demands,
13086 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13093 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13095 guint32 cols [MONO_DECL_SECURITY_SIZE];
13099 int index = mono_metadata_declsec_from_index (image, token);
13103 t = &image->tables [MONO_TABLE_DECLSECURITY];
13104 for (i = index; i < t->rows; i++) {
13105 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13107 /* shortcut - index are ordered */
13108 if (token != cols [MONO_DECL_SECURITY_PARENT])
13111 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13112 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13113 entry->blob = (char*) (metadata + 2);
13114 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13123 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13125 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13126 guint32 idx = mono_method_get_index (method);
13127 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13128 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13129 return get_declsec_action (method->klass->image, idx, action, entry);
13135 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13138 guint32 flags = mono_declsec_flags_from_class (klass);
13139 if (declsec_flags_map [action] & flags) {
13140 guint32 idx = mono_metadata_token_index (klass->type_token);
13141 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13142 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13143 return get_declsec_action (klass->image, idx, action, entry);
13149 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13151 guint32 idx = 1; /* there is only one assembly */
13152 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13153 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13155 return get_declsec_action (assembly->image, idx, action, entry);
13159 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13161 MonoObject *res, *exc;
13163 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13164 static MonoMethod *method = NULL;
13166 if (!System_Reflection_Emit_TypeBuilder) {
13167 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13168 g_assert (System_Reflection_Emit_TypeBuilder);
13170 if (method == NULL) {
13171 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13176 * The result of mono_type_get_object () might be a System.MonoType but we
13177 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13179 g_assert (mono_class_get_ref_info (klass));
13180 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13182 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13184 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13188 return *(MonoBoolean*)mono_object_unbox (res);
13192 * mono_reflection_type_get_type:
13193 * @reftype: the System.Type object
13195 * Returns the MonoType* associated with the C# System.Type object @reftype.
13198 mono_reflection_type_get_type (MonoReflectionType *reftype)
13200 g_assert (reftype);
13202 return mono_reflection_type_get_handle (reftype);
13206 * mono_reflection_assembly_get_assembly:
13207 * @refassembly: the System.Reflection.Assembly object
13209 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13212 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13214 g_assert (refassembly);
13216 return refassembly->assembly;