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, MonoError *error);
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, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
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, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
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, MonoError *error);
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, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
226 dynamic_images_lock (void)
228 mono_os_mutex_lock (&dynamic_images_mutex);
232 dynamic_images_unlock (void)
234 mono_os_mutex_unlock (&dynamic_images_mutex);
238 * mono_find_dynamic_image_owner:
240 * Find the dynamic image, if any, which a given pointer is located in the memory of.
243 mono_find_dynamic_image_owner (void *ptr)
245 MonoImage *owner = NULL;
248 dynamic_images_lock ();
252 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254 if (mono_mempool_contains_addr (image->mempool, ptr))
259 dynamic_images_unlock ();
265 mono_reflection_init (void)
267 mono_os_mutex_init (&dynamic_images_mutex);
271 dynamic_image_lock (MonoDynamicImage *image)
273 MONO_PREPARE_BLOCKING;
274 mono_image_lock ((MonoImage*)image);
275 MONO_FINISH_BLOCKING;
279 dynamic_image_unlock (MonoDynamicImage *image)
281 mono_image_unlock ((MonoImage*)image);
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
287 MONO_REQ_GC_UNSAFE_MODE;
289 dynamic_image_lock (assembly);
290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291 dynamic_image_unlock (assembly);
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
297 MONO_REQ_GC_UNSAFE_MODE;
301 dynamic_image_lock (assembly);
302 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303 dynamic_image_unlock (assembly);
309 sigbuffer_init (SigBuffer *buf, int size)
311 MONO_REQ_GC_NEUTRAL_MODE;
313 buf->buf = (char *)g_malloc (size);
315 buf->end = buf->buf + size;
319 sigbuffer_make_room (SigBuffer *buf, int size)
321 MONO_REQ_GC_NEUTRAL_MODE;
323 if (buf->end - buf->p < size) {
324 int new_size = buf->end - buf->buf + size + 32;
325 char *p = (char *)g_realloc (buf->buf, new_size);
326 size = buf->p - buf->buf;
329 buf->end = buf->buf + new_size;
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
336 MONO_REQ_GC_NEUTRAL_MODE;
338 sigbuffer_make_room (buf, 6);
339 mono_metadata_encode_value (val, buf->p, &buf->p);
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 sigbuffer_make_room (buf, 1);
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
355 MONO_REQ_GC_NEUTRAL_MODE;
357 sigbuffer_make_room (buf, size);
358 memcpy (buf->p, p, size);
363 sigbuffer_free (SigBuffer *buf)
365 MONO_REQ_GC_NEUTRAL_MODE;
370 #ifndef DISABLE_REFLECTION_EMIT
374 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
378 image_g_malloc (MonoImage *image, guint size)
380 MONO_REQ_GC_NEUTRAL_MODE;
383 return mono_image_alloc (image, size);
385 return g_malloc (size);
387 #endif /* !DISABLE_REFLECTION_EMIT */
392 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 image_g_malloc0 (MonoImage *image, guint size)
398 MONO_REQ_GC_NEUTRAL_MODE;
401 return mono_image_alloc0 (image, size);
403 return g_malloc0 (size);
406 #ifndef DISABLE_REFLECTION_EMIT
408 image_strdup (MonoImage *image, const char *s)
410 MONO_REQ_GC_NEUTRAL_MODE;
413 return mono_image_strdup (image, s);
419 #define image_g_new(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
422 #define image_g_new0(image,struct_type, n_structs) \
423 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
427 alloc_table (MonoDynamicTable *table, guint nrows)
429 MONO_REQ_GC_NEUTRAL_MODE;
432 g_assert (table->columns);
433 if (nrows + 1 >= table->alloc_rows) {
434 while (nrows + 1 >= table->alloc_rows) {
435 if (table->alloc_rows == 0)
436 table->alloc_rows = 16;
438 table->alloc_rows *= 2;
441 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
446 make_room_in_stream (MonoDynamicStream *stream, int size)
448 MONO_REQ_GC_NEUTRAL_MODE;
450 if (size <= stream->alloc_size)
453 while (stream->alloc_size <= size) {
454 if (stream->alloc_size < 4096)
455 stream->alloc_size = 4096;
457 stream->alloc_size *= 2;
460 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
466 MONO_REQ_GC_NEUTRAL_MODE;
470 gpointer oldkey, oldval;
472 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473 return GPOINTER_TO_UINT (oldval);
475 len = strlen (str) + 1;
478 make_room_in_stream (sh, idx + len);
481 * We strdup the string even if we already copy them in sh->data
482 * so that the string pointers in the hash remain valid even if
483 * we need to realloc sh->data. We may want to avoid that later.
485 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486 memcpy (sh->data + idx, str, len);
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
494 MONO_REQ_GC_UNSAFE_MODE;
496 char *name = mono_string_to_utf8 (str);
498 idx = string_heap_insert (sh, name);
503 #ifndef DISABLE_REFLECTION_EMIT
505 string_heap_init (MonoDynamicStream *sh)
507 MONO_REQ_GC_NEUTRAL_MODE;
510 sh->alloc_size = 4096;
511 sh->data = (char *)g_malloc (4096);
512 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513 string_heap_insert (sh, "");
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 make_room_in_stream (stream, stream->index + len);
525 memcpy (stream->data + stream->index, data, len);
527 stream->index += len;
529 * align index? Not without adding an additional param that controls it since
530 * we may store a blob value in pieces.
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
538 MONO_REQ_GC_NEUTRAL_MODE;
542 make_room_in_stream (stream, stream->index + len);
543 memset (stream->data + stream->index, 0, len);
545 stream->index += len;
550 stream_data_align (MonoDynamicStream *stream)
552 MONO_REQ_GC_NEUTRAL_MODE;
555 guint32 count = stream->index % 4;
557 /* we assume the stream data will be aligned */
559 mono_image_add_stream_data (stream, buf, 4 - count);
562 #ifndef DISABLE_REFLECTION_EMIT
564 mono_blob_entry_hash (const char* str)
566 MONO_REQ_GC_NEUTRAL_MODE;
570 len = mono_metadata_decode_blob_size (str, &str);
574 for (str += 1; str < end; str++)
575 h = (h << 5) - h + *str;
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584 MONO_REQ_GC_NEUTRAL_MODE;
589 len = mono_metadata_decode_blob_size (str1, &end1);
590 len2 = mono_metadata_decode_blob_size (str2, &end2);
593 return memcmp (end1, end2, len) == 0;
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
599 MONO_REQ_GC_NEUTRAL_MODE;
603 gpointer oldkey, oldval;
605 copy = (char *)g_malloc (s1+s2);
606 memcpy (copy, b1, s1);
607 memcpy (copy + s1, b2, s2);
608 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
610 idx = GPOINTER_TO_UINT (oldval);
612 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613 mono_image_add_stream_data (&assembly->blob, b2, s2);
614 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
622 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 size = buf->p - buf->buf;
628 g_assert (size <= (buf->end - buf->buf));
629 mono_metadata_encode_value (size, b, &b);
630 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
634 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635 * dest may be misaligned.
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639 MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
643 for (elem = 0; elem < nelem; ++elem) {
669 g_assert_not_reached ();
675 memcpy (dest, val, len * nelem);
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
682 MONO_REQ_GC_UNSAFE_MODE;
686 guint32 idx = 0, len;
688 len = str->length * 2;
689 mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
692 char *swapped = g_malloc (2 * mono_string_length (str));
693 const char *p = (const char*)mono_string_chars (str);
695 swap_with_size (swapped, p, 2, mono_string_length (str));
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
700 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
705 #ifndef DISABLE_REFLECTION_EMIT
707 default_class_from_mono_type (MonoType *type)
709 MONO_REQ_GC_NEUTRAL_MODE;
711 switch (type->type) {
712 case MONO_TYPE_OBJECT:
713 return mono_defaults.object_class;
715 return mono_defaults.void_class;
716 case MONO_TYPE_BOOLEAN:
717 return mono_defaults.boolean_class;
719 return mono_defaults.char_class;
721 return mono_defaults.sbyte_class;
723 return mono_defaults.byte_class;
725 return mono_defaults.int16_class;
727 return mono_defaults.uint16_class;
729 return mono_defaults.int32_class;
731 return mono_defaults.uint32_class;
733 return mono_defaults.int_class;
735 return mono_defaults.uint_class;
737 return mono_defaults.int64_class;
739 return mono_defaults.uint64_class;
741 return mono_defaults.single_class;
743 return mono_defaults.double_class;
744 case MONO_TYPE_STRING:
745 return mono_defaults.string_class;
747 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748 g_assert_not_reached ();
756 * mono_class_get_ref_info:
758 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
761 mono_class_get_ref_info (MonoClass *klass)
763 MONO_REQ_GC_UNSAFE_MODE;
765 if (klass->ref_info_handle == 0)
768 return mono_gchandle_get_target (klass->ref_info_handle);
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
774 MONO_REQ_GC_UNSAFE_MODE;
776 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777 g_assert (klass->ref_info_handle != 0);
781 mono_class_free_ref_info (MonoClass *klass)
783 MONO_REQ_GC_NEUTRAL_MODE;
785 if (klass->ref_info_handle) {
786 mono_gchandle_free (klass->ref_info_handle);
787 klass->ref_info_handle = 0;
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
794 MONO_REQ_GC_NEUTRAL_MODE;
797 MonoGenericInst *class_inst;
802 class_inst = gclass->context.class_inst;
804 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805 klass = gclass->container_class;
806 sigbuffer_add_value (buf, klass->byval_arg.type);
807 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
809 sigbuffer_add_value (buf, class_inst->type_argc);
810 for (i = 0; i < class_inst->type_argc; ++i)
811 encode_type (assembly, class_inst->type_argv [i], buf);
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
818 MONO_REQ_GC_NEUTRAL_MODE;
821 g_assert_not_reached ();
826 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
830 case MONO_TYPE_BOOLEAN:
844 case MONO_TYPE_STRING:
845 case MONO_TYPE_OBJECT:
846 case MONO_TYPE_TYPEDBYREF:
847 sigbuffer_add_value (buf, type->type);
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, type->data.type, buf);
853 case MONO_TYPE_SZARRAY:
854 sigbuffer_add_value (buf, type->type);
855 encode_type (assembly, &type->data.klass->byval_arg, buf);
857 case MONO_TYPE_VALUETYPE:
858 case MONO_TYPE_CLASS: {
859 MonoClass *k = mono_class_from_mono_type (type);
861 if (k->generic_container) {
862 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863 encode_generic_class (assembly, gclass, buf);
866 * Make sure we use the correct type.
868 sigbuffer_add_value (buf, k->byval_arg.type);
870 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871 * otherwise two typerefs could point to the same type, leading to
872 * verification errors.
874 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
878 case MONO_TYPE_ARRAY:
879 sigbuffer_add_value (buf, type->type);
880 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881 sigbuffer_add_value (buf, type->data.array->rank);
882 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883 sigbuffer_add_value (buf, 0);
885 case MONO_TYPE_GENERICINST:
886 encode_generic_class (assembly, type->data.generic_class, buf);
890 sigbuffer_add_value (buf, type->type);
891 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
894 g_error ("need to encode type %x", type->type);
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
901 MONO_REQ_GC_UNSAFE_MODE;
904 sigbuffer_add_value (buf, MONO_TYPE_VOID);
908 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
914 MONO_REQ_GC_UNSAFE_MODE;
919 for (i = 0; i < mono_array_length (modreq); ++i) {
920 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926 for (i = 0; i < mono_array_length (modopt); ++i) {
927 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
934 #ifndef DISABLE_REFLECTION_EMIT
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
938 MONO_REQ_GC_UNSAFE_MODE;
942 guint32 nparams = sig->param_count;
948 sigbuffer_init (&buf, 32);
950 * FIXME: vararg, explicit_this, differenc call_conv values...
952 idx = sig->call_convention;
954 idx |= 0x20; /* hasthis */
955 if (sig->generic_param_count)
956 idx |= 0x10; /* generic */
957 sigbuffer_add_byte (&buf, idx);
958 if (sig->generic_param_count)
959 sigbuffer_add_value (&buf, sig->generic_param_count);
960 sigbuffer_add_value (&buf, nparams);
961 encode_type (assembly, sig->ret, &buf);
962 for (i = 0; i < nparams; ++i) {
963 if (i == sig->sentinelpos)
964 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965 encode_type (assembly, sig->params [i], &buf);
967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968 sigbuffer_free (&buf);
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
976 MONO_REQ_GC_UNSAFE_MODE;
979 * FIXME: reuse code from method_encode_signature().
983 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
984 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
988 sigbuffer_init (&buf, 32);
989 /* LAMESPEC: all the call conv spec is foobared */
990 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991 if (mb->call_conv & 2)
992 idx |= 0x5; /* vararg */
993 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994 idx |= 0x20; /* hasthis */
996 idx |= 0x10; /* generic */
997 sigbuffer_add_byte (&buf, idx);
999 sigbuffer_add_value (&buf, ngparams);
1000 sigbuffer_add_value (&buf, nparams + notypes);
1001 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002 encode_reflection_type (assembly, mb->rtype, &buf);
1003 for (i = 0; i < nparams; ++i) {
1004 MonoArray *modreq = NULL;
1005 MonoArray *modopt = NULL;
1006 MonoReflectionType *pt;
1008 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014 encode_reflection_type (assembly, pt, &buf);
1017 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018 for (i = 0; i < notypes; ++i) {
1019 MonoReflectionType *pt;
1021 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022 encode_reflection_type (assembly, pt, &buf);
1025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026 sigbuffer_free (&buf);
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1033 MONO_REQ_GC_UNSAFE_MODE;
1035 MonoDynamicTable *table;
1037 guint32 idx, sig_idx;
1038 guint nl = mono_array_length (ilgen->locals);
1042 sigbuffer_init (&buf, 32);
1043 sigbuffer_add_value (&buf, 0x07);
1044 sigbuffer_add_value (&buf, nl);
1045 for (i = 0; i < nl; ++i) {
1046 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1049 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1051 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1053 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1056 if (assembly->standalonesig_cache == NULL)
1057 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1062 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063 idx = table->next_idx ++;
1065 alloc_table (table, table->rows);
1066 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1068 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1070 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1078 MONO_REQ_GC_UNSAFE_MODE;
1080 guint32 num_clauses = 0;
1083 MonoILExceptionInfo *ex_info;
1084 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086 if (ex_info->handlers)
1087 num_clauses += mono_array_length (ex_info->handlers);
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 MonoExceptionClause *clauses;
1102 MonoExceptionClause *clause;
1103 MonoILExceptionInfo *ex_info;
1104 MonoILExceptionBlock *ex_block;
1105 guint32 finally_start;
1106 int i, j, clause_index;;
1108 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1111 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113 finally_start = ex_info->start + ex_info->len;
1114 if (!ex_info->handlers)
1116 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118 clause = &(clauses [clause_index]);
1120 clause->flags = ex_block->type;
1121 clause->try_offset = ex_info->start;
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124 clause->try_len = finally_start - ex_info->start;
1126 clause->try_len = ex_info->len;
1127 clause->handler_offset = ex_block->start;
1128 clause->handler_len = ex_block->len;
1129 if (ex_block->extype) {
1130 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1132 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133 clause->data.filter_offset = ex_block->filter_offset;
1135 clause->data.filter_offset = 0;
1137 finally_start = ex_block->start + ex_block->len;
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1148 * method_encode_code:
1150 * @assembly the assembly
1151 * @mb the managed MethodBuilder
1152 * @error set on error
1154 * Note that the return value is not sensible if @error is set.
1157 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1159 MONO_REQ_GC_UNSAFE_MODE;
1164 gint32 max_stack, i;
1165 gint32 num_locals = 0;
1166 gint32 num_exception = 0;
1169 char fat_header [12];
1171 guint16 short_value;
1172 guint32 local_sig = 0;
1173 guint32 header_size = 12;
1176 mono_error_init (error);
1178 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1179 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1183 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1185 code = mb->ilgen->code;
1186 code_size = mb->ilgen->code_len;
1187 max_stack = mb->ilgen->max_stack;
1188 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1189 if (mb->ilgen->ex_handlers)
1190 num_exception = method_count_clauses (mb->ilgen);
1194 char *name = mono_string_to_utf8 (mb->name);
1195 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1196 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1202 code_size = mono_array_length (code);
1203 max_stack = 8; /* we probably need to run a verifier on the code... */
1206 stream_data_align (&assembly->code);
1208 /* check for exceptions, maxstack, locals */
1209 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1211 if (code_size < 64 && !(code_size & 1)) {
1212 flags = (code_size << 2) | 0x2;
1213 } else if (code_size < 32 && (code_size & 1)) {
1214 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1218 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1219 /* add to the fixup todo list */
1220 if (mb->ilgen && mb->ilgen->num_token_fixups)
1221 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1222 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1223 return assembly->text_rva + idx;
1227 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1229 * FIXME: need to set also the header size in fat_flags.
1230 * (and more sects and init locals flags)
1234 fat_flags |= METHOD_HEADER_MORE_SECTS;
1235 if (mb->init_locals)
1236 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1237 fat_header [0] = fat_flags;
1238 fat_header [1] = (header_size / 4 ) << 4;
1239 short_value = GUINT16_TO_LE (max_stack);
1240 memcpy (fat_header + 2, &short_value, 2);
1241 int_value = GUINT32_TO_LE (code_size);
1242 memcpy (fat_header + 4, &int_value, 4);
1243 int_value = GUINT32_TO_LE (local_sig);
1244 memcpy (fat_header + 8, &int_value, 4);
1245 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1246 /* add to the fixup todo list */
1247 if (mb->ilgen && mb->ilgen->num_token_fixups)
1248 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1250 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1251 if (num_exception) {
1252 unsigned char sheader [4];
1253 MonoILExceptionInfo * ex_info;
1254 MonoILExceptionBlock * ex_block;
1257 stream_data_align (&assembly->code);
1258 /* always use fat format for now */
1259 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1260 num_exception *= 6 * sizeof (guint32);
1261 num_exception += 4; /* include the size of the header */
1262 sheader [1] = num_exception & 0xff;
1263 sheader [2] = (num_exception >> 8) & 0xff;
1264 sheader [3] = (num_exception >> 16) & 0xff;
1265 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1266 /* fat header, so we are already aligned */
1268 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1269 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1270 if (ex_info->handlers) {
1271 int finally_start = ex_info->start + ex_info->len;
1272 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1274 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1276 val = GUINT32_TO_LE (ex_block->type);
1277 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279 val = GUINT32_TO_LE (ex_info->start);
1280 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1281 /* need fault, too, probably */
1282 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1283 val = GUINT32_TO_LE (finally_start - ex_info->start);
1285 val = GUINT32_TO_LE (ex_info->len);
1286 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1287 /* handler offset */
1288 val = GUINT32_TO_LE (ex_block->start);
1289 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1291 val = GUINT32_TO_LE (ex_block->len);
1292 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293 finally_start = ex_block->start + ex_block->len;
1294 if (ex_block->extype) {
1295 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1297 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1298 val = ex_block->filter_offset;
1302 val = GUINT32_TO_LE (val);
1303 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1304 /*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",
1305 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);*/
1308 g_error ("No clauses for ex info block %d", i);
1312 return assembly->text_rva + idx;
1316 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1318 MONO_REQ_GC_NEUTRAL_MODE;
1321 MonoDynamicTable *table;
1324 table = &assembly->tables [table_idx];
1326 g_assert (col < table->columns);
1328 values = table->values + table->columns;
1329 for (i = 1; i <= table->rows; ++i) {
1330 if (values [col] == token)
1332 values += table->columns;
1338 * LOCKING: Acquires the loader lock.
1340 static MonoCustomAttrInfo*
1341 lookup_custom_attr (MonoImage *image, gpointer member)
1343 MONO_REQ_GC_NEUTRAL_MODE;
1345 MonoCustomAttrInfo* res;
1347 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1352 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1358 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1360 MONO_REQ_GC_UNSAFE_MODE;
1362 /* FIXME: Need to do more checks */
1363 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1364 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1366 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1373 static MonoCustomAttrInfo*
1374 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1376 MONO_REQ_GC_UNSAFE_MODE;
1378 int i, index, count, not_visible;
1379 MonoCustomAttrInfo *ainfo;
1380 MonoReflectionCustomAttr *cattr;
1384 /* FIXME: check in assembly the Run flag is set */
1386 count = mono_array_length (cattrs);
1388 /* Skip nonpublic attributes since MS.NET seems to do the same */
1389 /* FIXME: This needs to be done more globally */
1391 for (i = 0; i < count; ++i) {
1392 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1393 if (!custom_attr_visible (image, cattr))
1396 count -= not_visible;
1398 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1400 ainfo->image = image;
1401 ainfo->num_attrs = count;
1402 ainfo->cached = alloc_img != NULL;
1404 for (i = 0; i < count; ++i) {
1405 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1406 if (custom_attr_visible (image, cattr)) {
1407 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1408 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1409 ainfo->attrs [index].ctor = cattr->ctor->method;
1410 ainfo->attrs [index].data = saved;
1411 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1419 #ifndef DISABLE_REFLECTION_EMIT
1421 * LOCKING: Acquires the loader lock.
1424 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1426 MONO_REQ_GC_UNSAFE_MODE;
1428 MonoCustomAttrInfo *ainfo, *tmp;
1430 if (!cattrs || !mono_array_length (cattrs))
1433 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1435 mono_loader_lock ();
1436 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1438 mono_custom_attrs_free (tmp);
1439 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1440 mono_loader_unlock ();
1446 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1448 MONO_REQ_GC_NEUTRAL_MODE;
1455 * idx is the table index of the object
1456 * type is one of MONO_CUSTOM_ATTR_*
1459 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1461 MONO_REQ_GC_UNSAFE_MODE;
1463 MonoDynamicTable *table;
1464 MonoReflectionCustomAttr *cattr;
1466 guint32 count, i, token;
1468 char *p = blob_size;
1470 mono_error_init (error);
1472 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1475 count = mono_array_length (cattrs);
1476 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1477 table->rows += count;
1478 alloc_table (table, table->rows);
1479 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1480 idx <<= MONO_CUSTOM_ATTR_BITS;
1482 for (i = 0; i < count; ++i) {
1483 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1485 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1486 if (!mono_error_ok (error)) goto fail;
1487 type = mono_metadata_token_index (token);
1488 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1489 switch (mono_metadata_token_table (token)) {
1490 case MONO_TABLE_METHOD:
1491 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1493 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1494 * method, not the one returned by mono_image_create_token ().
1496 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1498 case MONO_TABLE_MEMBERREF:
1499 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1502 g_warning ("got wrong token in custom attr");
1505 values [MONO_CUSTOM_ATTR_TYPE] = type;
1507 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1508 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1509 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1510 values += MONO_CUSTOM_ATTR_SIZE;
1521 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1523 MONO_REQ_GC_UNSAFE_MODE;
1525 MonoDynamicTable *table;
1527 guint32 count, i, idx;
1528 MonoReflectionPermissionSet *perm;
1533 count = mono_array_length (permissions);
1534 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1535 table->rows += count;
1536 alloc_table (table, table->rows);
1538 for (i = 0; i < mono_array_length (permissions); ++i) {
1539 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1541 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1543 idx = mono_metadata_token_index (parent_token);
1544 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1545 switch (mono_metadata_token_table (parent_token)) {
1546 case MONO_TABLE_TYPEDEF:
1547 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1549 case MONO_TABLE_METHOD:
1550 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1552 case MONO_TABLE_ASSEMBLY:
1553 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1556 g_assert_not_reached ();
1559 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1560 values [MONO_DECL_SECURITY_PARENT] = idx;
1561 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1568 * Fill in the MethodDef and ParamDef tables for a method.
1569 * This is used for both normal methods and constructors.
1572 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1574 MONO_REQ_GC_UNSAFE_MODE;
1576 MonoDynamicTable *table;
1580 mono_error_init (error);
1582 /* room in this table is already allocated */
1583 table = &assembly->tables [MONO_TABLE_METHOD];
1584 *mb->table_idx = table->next_idx ++;
1585 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1586 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1587 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1588 values [MONO_METHOD_FLAGS] = mb->attrs;
1589 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1590 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1591 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1592 if (!mono_error_ok (error))
1595 table = &assembly->tables [MONO_TABLE_PARAM];
1596 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1598 mono_image_add_decl_security (assembly,
1599 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1602 MonoDynamicTable *mtable;
1605 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1606 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1609 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1610 if (mono_array_get (mb->pinfo, gpointer, i))
1613 table->rows += count;
1614 alloc_table (table, table->rows);
1615 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1616 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1617 MonoReflectionParamBuilder *pb;
1618 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1619 values [MONO_PARAM_FLAGS] = pb->attrs;
1620 values [MONO_PARAM_SEQUENCE] = i;
1621 if (pb->name != NULL) {
1622 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1624 values [MONO_PARAM_NAME] = 0;
1626 values += MONO_PARAM_SIZE;
1627 if (pb->marshal_info) {
1629 alloc_table (mtable, mtable->rows);
1630 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1631 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1632 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1634 pb->table_idx = table->next_idx++;
1635 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1636 guint32 field_type = 0;
1637 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1639 alloc_table (mtable, mtable->rows);
1640 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1641 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1642 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1643 mvalues [MONO_CONSTANT_TYPE] = field_type;
1644 mvalues [MONO_CONSTANT_PADDING] = 0;
1653 #ifndef DISABLE_REFLECTION_EMIT
1655 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1657 MONO_REQ_GC_UNSAFE_MODE;
1659 mono_error_init (error);
1660 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1662 rmb->ilgen = mb->ilgen;
1663 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1664 return_val_if_nok (error, FALSE);
1665 rmb->parameters = mb->parameters;
1666 rmb->generic_params = mb->generic_params;
1667 rmb->generic_container = mb->generic_container;
1668 rmb->opt_types = NULL;
1669 rmb->pinfo = mb->pinfo;
1670 rmb->attrs = mb->attrs;
1671 rmb->iattrs = mb->iattrs;
1672 rmb->call_conv = mb->call_conv;
1673 rmb->code = mb->code;
1674 rmb->type = mb->type;
1675 rmb->name = mb->name;
1676 rmb->table_idx = &mb->table_idx;
1677 rmb->init_locals = mb->init_locals;
1678 rmb->skip_visibility = FALSE;
1679 rmb->return_modreq = mb->return_modreq;
1680 rmb->return_modopt = mb->return_modopt;
1681 rmb->param_modreq = mb->param_modreq;
1682 rmb->param_modopt = mb->param_modopt;
1683 rmb->permissions = mb->permissions;
1684 rmb->mhandle = mb->mhandle;
1689 rmb->charset = mb->charset;
1690 rmb->extra_flags = mb->extra_flags;
1691 rmb->native_cc = mb->native_cc;
1692 rmb->dllentry = mb->dllentry;
1700 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1702 MONO_REQ_GC_UNSAFE_MODE;
1704 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1706 mono_error_init (error);
1708 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1710 rmb->ilgen = mb->ilgen;
1711 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1712 return_val_if_nok (error, FALSE);
1713 rmb->parameters = mb->parameters;
1714 rmb->generic_params = NULL;
1715 rmb->generic_container = NULL;
1716 rmb->opt_types = NULL;
1717 rmb->pinfo = mb->pinfo;
1718 rmb->attrs = mb->attrs;
1719 rmb->iattrs = mb->iattrs;
1720 rmb->call_conv = mb->call_conv;
1722 rmb->type = mb->type;
1723 rmb->name = mono_string_new (mono_domain_get (), name);
1724 rmb->table_idx = &mb->table_idx;
1725 rmb->init_locals = mb->init_locals;
1726 rmb->skip_visibility = FALSE;
1727 rmb->return_modreq = NULL;
1728 rmb->return_modopt = NULL;
1729 rmb->param_modreq = mb->param_modreq;
1730 rmb->param_modopt = mb->param_modopt;
1731 rmb->permissions = mb->permissions;
1732 rmb->mhandle = mb->mhandle;
1740 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1742 MONO_REQ_GC_UNSAFE_MODE;
1744 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1746 rmb->ilgen = mb->ilgen;
1747 rmb->rtype = mb->rtype;
1748 rmb->parameters = mb->parameters;
1749 rmb->generic_params = NULL;
1750 rmb->generic_container = NULL;
1751 rmb->opt_types = NULL;
1753 rmb->attrs = mb->attrs;
1755 rmb->call_conv = mb->call_conv;
1757 rmb->type = (MonoObject *) mb->owner;
1758 rmb->name = mb->name;
1759 rmb->table_idx = NULL;
1760 rmb->init_locals = mb->init_locals;
1761 rmb->skip_visibility = mb->skip_visibility;
1762 rmb->return_modreq = NULL;
1763 rmb->return_modopt = NULL;
1764 rmb->param_modreq = NULL;
1765 rmb->param_modopt = NULL;
1766 rmb->permissions = NULL;
1767 rmb->mhandle = mb->mhandle;
1774 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1776 MONO_REQ_GC_UNSAFE_MODE;
1778 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1779 MonoDynamicTable *table;
1782 MonoReflectionMethod *m;
1785 mono_error_init (error);
1787 if (!mb->override_methods)
1790 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1791 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1793 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1795 alloc_table (table, table->rows);
1796 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1797 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1798 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1800 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1801 return_val_if_nok (error, FALSE);
1803 switch (mono_metadata_token_table (tok)) {
1804 case MONO_TABLE_MEMBERREF:
1805 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1807 case MONO_TABLE_METHOD:
1808 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1811 g_assert_not_reached ();
1813 values [MONO_METHODIMPL_DECLARATION] = tok;
1819 #ifndef DISABLE_REFLECTION_EMIT
1821 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1823 MONO_REQ_GC_UNSAFE_MODE;
1825 MonoDynamicTable *table;
1827 ReflectionMethodBuilder rmb;
1830 mono_error_init (error);
1832 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1833 !mono_image_basic_method (&rmb, assembly, error))
1836 mb->table_idx = *rmb.table_idx;
1838 if (mb->dll) { /* It's a P/Invoke method */
1840 /* map CharSet values to on-disk values */
1841 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1842 int extra_flags = mb->extra_flags;
1843 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1845 alloc_table (table, table->rows);
1846 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1848 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1849 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1851 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1853 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1854 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1855 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1856 table = &assembly->tables [MONO_TABLE_MODULEREF];
1858 alloc_table (table, table->rows);
1859 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1860 values [MONO_IMPLMAP_SCOPE] = table->rows;
1864 if (mb->generic_params) {
1865 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1866 table->rows += mono_array_length (mb->generic_params);
1867 alloc_table (table, table->rows);
1868 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1869 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1871 mono_image_get_generic_param_info (
1872 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1880 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1882 MONO_REQ_GC_UNSAFE_MODE;
1884 ReflectionMethodBuilder rmb;
1886 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1889 if (!mono_image_basic_method (&rmb, assembly, error))
1892 mb->table_idx = *rmb.table_idx;
1899 type_get_fully_qualified_name (MonoType *type)
1901 MONO_REQ_GC_NEUTRAL_MODE;
1903 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1907 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1909 MONO_REQ_GC_UNSAFE_MODE;
1914 klass = mono_class_from_mono_type (type);
1916 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1917 ta = klass->image->assembly;
1918 if (assembly_is_dynamic (ta) || (ta == ass)) {
1919 if (klass->generic_class || klass->generic_container)
1920 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1921 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1923 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1926 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1929 #ifndef DISABLE_REFLECTION_EMIT
1930 /*field_image is the image to which the eventual custom mods have been encoded against*/
1932 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1934 MONO_REQ_GC_NEUTRAL_MODE;
1937 guint32 idx, i, token;
1939 if (!assembly->save)
1942 sigbuffer_init (&buf, 32);
1944 sigbuffer_add_value (&buf, 0x06);
1945 /* encode custom attributes before the type */
1946 if (type->num_mods) {
1947 for (i = 0; i < type->num_mods; ++i) {
1950 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1951 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1953 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1955 token = type->modifiers [i].token;
1958 if (type->modifiers [i].required)
1959 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1961 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1963 sigbuffer_add_value (&buf, token);
1966 encode_type (assembly, type, &buf);
1967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1968 sigbuffer_free (&buf);
1974 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1976 MONO_REQ_GC_UNSAFE_MODE;
1980 guint32 typespec = 0;
1984 init_type_builder_generics (fb->type);
1986 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1987 klass = mono_class_from_mono_type (type);
1989 sigbuffer_init (&buf, 32);
1991 sigbuffer_add_value (&buf, 0x06);
1992 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1993 /* encode custom attributes before the type */
1995 if (klass->generic_container)
1996 typespec = create_typespec (assembly, type);
1999 MonoGenericClass *gclass;
2000 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2001 encode_generic_class (assembly, gclass, &buf);
2003 encode_type (assembly, type, &buf);
2005 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2006 sigbuffer_free (&buf);
2011 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2013 MONO_REQ_GC_UNSAFE_MODE;
2015 char blob_size [64];
2016 char *b = blob_size;
2019 guint32 idx = 0, len = 0, dummy = 0;
2021 buf = (char *)g_malloc (64);
2023 *ret_type = MONO_TYPE_CLASS;
2025 box_val = (char*)&dummy;
2027 box_val = ((char*)val) + sizeof (MonoObject);
2028 *ret_type = val->vtable->klass->byval_arg.type;
2031 switch (*ret_type) {
2032 case MONO_TYPE_BOOLEAN:
2037 case MONO_TYPE_CHAR:
2054 case MONO_TYPE_VALUETYPE: {
2055 MonoClass *klass = val->vtable->klass;
2057 if (klass->enumtype) {
2058 *ret_type = mono_class_enum_basetype (klass)->type;
2060 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2063 g_error ("we can't encode valuetypes, we should have never reached this line");
2066 case MONO_TYPE_CLASS:
2068 case MONO_TYPE_STRING: {
2069 MonoString *str = (MonoString*)val;
2070 /* there is no signature */
2071 len = str->length * 2;
2072 mono_metadata_encode_value (len, b, &b);
2073 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2075 char *swapped = g_malloc (2 * mono_string_length (str));
2076 const char *p = (const char*)mono_string_chars (str);
2078 swap_with_size (swapped, p, 2, mono_string_length (str));
2079 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2083 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2089 case MONO_TYPE_GENERICINST:
2090 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2093 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2096 /* there is no signature */
2097 mono_metadata_encode_value (len, b, &b);
2098 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2099 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2100 swap_with_size (blob_size, box_val, len, 1);
2101 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2103 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2111 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2113 MONO_REQ_GC_UNSAFE_MODE;
2119 sigbuffer_init (&buf, 32);
2121 sigbuffer_add_value (&buf, minfo->type);
2123 switch (minfo->type) {
2124 case MONO_NATIVE_BYVALTSTR:
2125 case MONO_NATIVE_BYVALARRAY:
2126 sigbuffer_add_value (&buf, minfo->count);
2128 case MONO_NATIVE_LPARRAY:
2129 if (minfo->eltype || minfo->has_size) {
2130 sigbuffer_add_value (&buf, minfo->eltype);
2131 if (minfo->has_size) {
2132 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2133 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2135 /* LAMESPEC: ElemMult is undocumented */
2136 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2140 case MONO_NATIVE_SAFEARRAY:
2142 sigbuffer_add_value (&buf, minfo->eltype);
2144 case MONO_NATIVE_CUSTOM:
2146 str = mono_string_to_utf8 (minfo->guid);
2148 sigbuffer_add_value (&buf, len);
2149 sigbuffer_add_mem (&buf, str, len);
2152 sigbuffer_add_value (&buf, 0);
2154 /* native type name */
2155 sigbuffer_add_value (&buf, 0);
2156 /* custom marshaler type name */
2157 if (minfo->marshaltype || minfo->marshaltyperef) {
2158 if (minfo->marshaltyperef)
2159 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2161 str = mono_string_to_utf8 (minfo->marshaltype);
2163 sigbuffer_add_value (&buf, len);
2164 sigbuffer_add_mem (&buf, str, len);
2167 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2168 sigbuffer_add_value (&buf, 0);
2170 if (minfo->mcookie) {
2171 str = mono_string_to_utf8 (minfo->mcookie);
2173 sigbuffer_add_value (&buf, len);
2174 sigbuffer_add_mem (&buf, str, len);
2177 sigbuffer_add_value (&buf, 0);
2183 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2184 sigbuffer_free (&buf);
2189 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2191 MONO_REQ_GC_UNSAFE_MODE;
2193 MonoDynamicTable *table;
2196 /* maybe this fixup should be done in the C# code */
2197 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2198 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2199 table = &assembly->tables [MONO_TABLE_FIELD];
2200 fb->table_idx = table->next_idx ++;
2201 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2202 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2203 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2204 values [MONO_FIELD_FLAGS] = fb->attrs;
2205 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2207 if (fb->offset != -1) {
2208 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2210 alloc_table (table, table->rows);
2211 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2212 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2213 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2215 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2216 MonoTypeEnum field_type = (MonoTypeEnum)0;
2217 table = &assembly->tables [MONO_TABLE_CONSTANT];
2219 alloc_table (table, table->rows);
2220 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2221 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2222 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2223 values [MONO_CONSTANT_TYPE] = field_type;
2224 values [MONO_CONSTANT_PADDING] = 0;
2226 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2228 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2230 alloc_table (table, table->rows);
2231 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2232 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2234 * We store it in the code section because it's simpler for now.
2237 if (mono_array_length (fb->rva_data) >= 10)
2238 stream_data_align (&assembly->code);
2239 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2241 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2242 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2244 if (fb->marshal_info) {
2245 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2247 alloc_table (table, table->rows);
2248 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2249 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2250 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2255 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2257 MONO_REQ_GC_UNSAFE_MODE;
2260 guint32 nparams = 0;
2261 MonoReflectionMethodBuilder *mb = fb->get_method;
2262 MonoReflectionMethodBuilder *smb = fb->set_method;
2265 if (mb && mb->parameters)
2266 nparams = mono_array_length (mb->parameters);
2267 if (!mb && smb && smb->parameters)
2268 nparams = mono_array_length (smb->parameters) - 1;
2269 sigbuffer_init (&buf, 32);
2270 if (fb->call_conv & 0x20)
2271 sigbuffer_add_byte (&buf, 0x28);
2273 sigbuffer_add_byte (&buf, 0x08);
2274 sigbuffer_add_value (&buf, nparams);
2276 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2277 for (i = 0; i < nparams; ++i) {
2278 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2279 encode_reflection_type (assembly, pt, &buf);
2281 } else if (smb && smb->parameters) {
2282 /* the property type is the last param */
2283 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2284 for (i = 0; i < nparams; ++i) {
2285 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2286 encode_reflection_type (assembly, pt, &buf);
2289 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2292 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2293 sigbuffer_free (&buf);
2298 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2300 MONO_REQ_GC_UNSAFE_MODE;
2302 MonoDynamicTable *table;
2304 guint num_methods = 0;
2308 * we need to set things in the following tables:
2309 * PROPERTYMAP (info already filled in _get_type_info ())
2310 * PROPERTY (rows already preallocated in _get_type_info ())
2311 * METHOD (method info already done with the generic method code)
2315 table = &assembly->tables [MONO_TABLE_PROPERTY];
2316 pb->table_idx = table->next_idx ++;
2317 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2318 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2319 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2320 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2322 /* FIXME: we still don't handle 'other' methods */
2323 if (pb->get_method) num_methods ++;
2324 if (pb->set_method) num_methods ++;
2326 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2327 table->rows += num_methods;
2328 alloc_table (table, table->rows);
2330 if (pb->get_method) {
2331 semaidx = table->next_idx ++;
2332 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2333 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2334 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2335 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2337 if (pb->set_method) {
2338 semaidx = table->next_idx ++;
2339 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2340 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2341 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2342 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2344 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2345 MonoTypeEnum field_type = (MonoTypeEnum)0;
2346 table = &assembly->tables [MONO_TABLE_CONSTANT];
2348 alloc_table (table, table->rows);
2349 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2350 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2351 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2352 values [MONO_CONSTANT_TYPE] = field_type;
2353 values [MONO_CONSTANT_PADDING] = 0;
2358 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2360 MONO_REQ_GC_UNSAFE_MODE;
2362 MonoDynamicTable *table;
2364 guint num_methods = 0;
2368 * we need to set things in the following tables:
2369 * EVENTMAP (info already filled in _get_type_info ())
2370 * EVENT (rows already preallocated in _get_type_info ())
2371 * METHOD (method info already done with the generic method code)
2374 table = &assembly->tables [MONO_TABLE_EVENT];
2375 eb->table_idx = table->next_idx ++;
2376 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2377 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2378 values [MONO_EVENT_FLAGS] = eb->attrs;
2379 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2382 * FIXME: we still don't handle 'other' methods
2384 if (eb->add_method) num_methods ++;
2385 if (eb->remove_method) num_methods ++;
2386 if (eb->raise_method) num_methods ++;
2388 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2389 table->rows += num_methods;
2390 alloc_table (table, table->rows);
2392 if (eb->add_method) {
2393 semaidx = table->next_idx ++;
2394 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2395 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2396 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2397 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2399 if (eb->remove_method) {
2400 semaidx = table->next_idx ++;
2401 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2402 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2403 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2404 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2406 if (eb->raise_method) {
2407 semaidx = table->next_idx ++;
2408 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2409 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2410 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2411 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2416 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2418 MONO_REQ_GC_UNSAFE_MODE;
2420 MonoDynamicTable *table;
2421 guint32 num_constraints, i;
2425 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2426 num_constraints = gparam->iface_constraints ?
2427 mono_array_length (gparam->iface_constraints) : 0;
2428 table->rows += num_constraints;
2429 if (gparam->base_type)
2431 alloc_table (table, table->rows);
2433 if (gparam->base_type) {
2434 table_idx = table->next_idx ++;
2435 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2437 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2438 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2439 assembly, mono_reflection_type_get_handle (gparam->base_type));
2442 for (i = 0; i < num_constraints; i++) {
2443 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2444 gparam->iface_constraints, gpointer, i);
2446 table_idx = table->next_idx ++;
2447 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2449 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2450 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2451 assembly, mono_reflection_type_get_handle (constraint));
2456 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2458 MONO_REQ_GC_UNSAFE_MODE;
2460 GenericParamTableEntry *entry;
2463 * The GenericParam table must be sorted according to the `owner' field.
2464 * We need to do this sorting prior to writing the GenericParamConstraint
2465 * table, since we have to use the final GenericParam table indices there
2466 * and they must also be sorted.
2469 entry = g_new0 (GenericParamTableEntry, 1);
2470 entry->owner = owner;
2471 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2472 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2473 entry->gparam = gparam;
2475 g_ptr_array_add (assembly->gen_params, entry);
2479 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2481 MONO_REQ_GC_UNSAFE_MODE;
2483 MonoDynamicTable *table;
2484 MonoGenericParam *param;
2488 mono_error_init (error);
2490 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2491 table_idx = table->next_idx ++;
2492 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2494 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2496 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2497 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2498 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2499 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2501 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2504 encode_constraints (entry->gparam, table_idx, assembly);
2510 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2512 MONO_REQ_GC_UNSAFE_MODE;
2514 MonoDynamicTable *table;
2517 guint32 cols [MONO_ASSEMBLY_SIZE];
2521 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2524 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2525 table = &assembly->tables [MONO_TABLE_MODULEREF];
2526 token = table->next_idx ++;
2528 alloc_table (table, table->rows);
2529 values = table->values + token * MONO_MODULEREF_SIZE;
2530 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2532 token <<= MONO_RESOLUTION_SCOPE_BITS;
2533 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2534 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2539 if (assembly_is_dynamic (image->assembly))
2541 memset (cols, 0, sizeof (cols));
2543 /* image->assembly->image is the manifest module */
2544 image = image->assembly->image;
2545 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2548 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2549 token = table->next_idx ++;
2551 alloc_table (table, table->rows);
2552 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2553 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2554 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2555 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2556 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2557 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2558 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2559 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2560 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2562 if (strcmp ("", image->assembly->aname.culture)) {
2563 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2564 image->assembly->aname.culture);
2567 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2568 guchar pubtoken [9];
2570 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2571 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2573 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2575 token <<= MONO_RESOLUTION_SCOPE_BITS;
2576 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2577 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2582 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2584 MONO_REQ_GC_NEUTRAL_MODE;
2586 MonoDynamicTable *table;
2591 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2594 sigbuffer_init (&buf, 32);
2595 switch (type->type) {
2596 case MONO_TYPE_FNPTR:
2598 case MONO_TYPE_SZARRAY:
2599 case MONO_TYPE_ARRAY:
2601 case MONO_TYPE_MVAR:
2602 case MONO_TYPE_GENERICINST:
2603 encode_type (assembly, type, &buf);
2605 case MONO_TYPE_CLASS:
2606 case MONO_TYPE_VALUETYPE: {
2607 MonoClass *k = mono_class_from_mono_type (type);
2608 if (!k || !k->generic_container) {
2609 sigbuffer_free (&buf);
2612 encode_type (assembly, type, &buf);
2616 sigbuffer_free (&buf);
2620 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2621 if (assembly->save) {
2622 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2623 alloc_table (table, table->rows + 1);
2624 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2625 values [MONO_TYPESPEC_SIGNATURE] = token;
2627 sigbuffer_free (&buf);
2629 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2630 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2636 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2638 MONO_REQ_GC_UNSAFE_MODE;
2640 MonoDynamicTable *table;
2642 guint32 token, scope, enclosing;
2645 /* if the type requires a typespec, we must try that first*/
2646 if (try_typespec && (token = create_typespec (assembly, type)))
2648 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2651 klass = mono_class_from_mono_type (type);
2653 klass = mono_class_from_mono_type (type);
2656 * If it's in the same module and not a generic type parameter:
2658 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2659 (type->type != MONO_TYPE_MVAR)) {
2660 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2661 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2662 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2666 if (klass->nested_in) {
2667 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2668 /* get the typeref idx of the enclosing type */
2669 enclosing >>= MONO_TYPEDEFORREF_BITS;
2670 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2672 scope = resolution_scope_from_image (assembly, klass->image);
2674 table = &assembly->tables [MONO_TABLE_TYPEREF];
2675 if (assembly->save) {
2676 alloc_table (table, table->rows + 1);
2677 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2678 values [MONO_TYPEREF_SCOPE] = scope;
2679 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2680 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2682 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2683 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2685 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2690 * Despite the name, we handle also TypeSpec (with the above helper).
2693 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2695 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2698 #ifndef DISABLE_REFLECTION_EMIT
2700 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2702 MONO_REQ_GC_NEUTRAL_MODE;
2704 MonoDynamicTable *table;
2706 guint32 token, pclass;
2708 switch (parent & MONO_TYPEDEFORREF_MASK) {
2709 case MONO_TYPEDEFORREF_TYPEREF:
2710 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2712 case MONO_TYPEDEFORREF_TYPESPEC:
2713 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2715 case MONO_TYPEDEFORREF_TYPEDEF:
2716 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2719 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2722 /* extract the index */
2723 parent >>= MONO_TYPEDEFORREF_BITS;
2725 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2727 if (assembly->save) {
2728 alloc_table (table, table->rows + 1);
2729 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2730 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2731 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2732 values [MONO_MEMBERREF_SIGNATURE] = sig;
2735 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2742 * Insert a memberef row into the metadata: the token that point to the memberref
2743 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2744 * mono_image_get_fieldref_token()).
2745 * The sig param is an index to an already built signature.
2748 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2750 MONO_REQ_GC_NEUTRAL_MODE;
2752 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2753 return mono_image_add_memberef_row (assembly, parent, name, sig);
2758 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2760 MONO_REQ_GC_NEUTRAL_MODE;
2763 MonoMethodSignature *sig;
2765 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2767 if (create_typespec) {
2768 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2773 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2774 if (token && !create_typespec)
2777 g_assert (!method->is_inflated);
2780 * A methodref signature can't contain an unmanaged calling convention.
2782 sig = mono_metadata_signature_dup (mono_method_signature (method));
2783 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2784 sig->call_convention = MONO_CALL_DEFAULT;
2785 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2786 method->name, method_encode_signature (assembly, sig));
2788 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2791 if (create_typespec) {
2792 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2793 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2794 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2796 if (assembly->save) {
2799 alloc_table (table, table->rows + 1);
2800 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2801 values [MONO_METHODSPEC_METHOD] = token;
2802 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2805 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2807 /*methodspec and memberef tokens are diferent, */
2808 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2815 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2817 guint32 token, parent, sig;
2818 ReflectionMethodBuilder rmb;
2819 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2821 mono_error_init (error);
2822 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2826 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2830 * A methodref signature can't contain an unmanaged calling convention.
2831 * Since some flags are encoded as part of call_conv, we need to check against it.
2833 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2834 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2836 sig = method_builder_encode_signature (assembly, &rmb);
2838 if (tb->generic_params)
2839 parent = create_generic_typespec (assembly, tb);
2841 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2843 char *name = mono_string_to_utf8 (method->name);
2845 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2848 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2854 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2855 const gchar *name, guint32 sig)
2857 MonoDynamicTable *table;
2861 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2863 if (assembly->save) {
2864 alloc_table (table, table->rows + 1);
2865 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2866 values [MONO_MEMBERREF_CLASS] = original;
2867 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2868 values [MONO_MEMBERREF_SIGNATURE] = sig;
2871 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2878 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2882 guint32 nparams = mono_array_length (mb->generic_params);
2885 if (!assembly->save)
2888 sigbuffer_init (&buf, 32);
2890 sigbuffer_add_value (&buf, 0xa);
2891 sigbuffer_add_value (&buf, nparams);
2893 for (i = 0; i < nparams; i++) {
2894 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2895 sigbuffer_add_value (&buf, i);
2898 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2899 sigbuffer_free (&buf);
2904 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2906 MonoDynamicTable *table;
2908 guint32 token, mtoken = 0;
2910 mono_error_init (error);
2911 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2915 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2917 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2918 if (!mono_error_ok (error))
2921 switch (mono_metadata_token_table (mtoken)) {
2922 case MONO_TABLE_MEMBERREF:
2923 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2925 case MONO_TABLE_METHOD:
2926 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2929 g_assert_not_reached ();
2932 if (assembly->save) {
2933 alloc_table (table, table->rows + 1);
2934 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2935 values [MONO_METHODSPEC_METHOD] = mtoken;
2936 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2939 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2942 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2947 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2951 mono_error_init (error);
2953 if (mb->generic_params && create_methodspec)
2954 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2956 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2960 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2961 if (!mono_error_ok (error))
2963 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2968 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2970 guint32 token, parent, sig;
2971 ReflectionMethodBuilder rmb;
2973 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2975 mono_error_init (error);
2977 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2981 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
2984 if (tb->generic_params)
2985 parent = create_generic_typespec (assembly, tb);
2987 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2989 name = mono_string_to_utf8 (rmb.name);
2990 sig = method_builder_encode_signature (assembly, &rmb);
2992 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2995 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3001 is_field_on_inst (MonoClassField *field)
3003 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3007 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3010 get_field_on_inst_generic_type (MonoClassField *field)
3012 MonoClass *klass, *gtd;
3013 MonoDynamicGenericClass *dgclass;
3016 g_assert (is_field_on_inst (field));
3018 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3020 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3021 field_index = field - dgclass->fields;
3022 return dgclass->field_generic_types [field_index];
3025 klass = field->parent;
3026 gtd = klass->generic_class->container_class;
3028 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3029 field_index = field - klass->fields;
3030 return gtd->fields [field_index].type;
3033 g_assert_not_reached ();
3037 #ifndef DISABLE_REFLECTION_EMIT
3039 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3045 g_assert (field->parent);
3047 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3051 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3052 int index = field - field->parent->fields;
3053 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3055 if (is_field_on_inst (field))
3056 type = get_field_on_inst_generic_type (field);
3058 type = mono_field_get_type (field);
3060 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3061 mono_field_get_name (field),
3062 fieldref_encode_signature (assembly, field->parent->image, type));
3063 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3068 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3072 MonoGenericClass *gclass;
3076 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3079 if (is_sre_field_builder (mono_object_class (f->fb))) {
3080 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3081 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3082 klass = mono_class_from_mono_type (type);
3083 gclass = type->data.generic_class;
3084 g_assert (gclass->is_dynamic);
3086 name = mono_string_to_utf8 (fb->name);
3087 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3088 field_encode_signature (assembly, fb));
3090 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3092 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3094 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3095 klass = mono_class_from_mono_type (type);
3097 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3098 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3100 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3101 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3104 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3109 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3113 MonoGenericClass *gclass;
3116 mono_error_init (error);
3118 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3120 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3124 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3125 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3126 ReflectionMethodBuilder rmb;
3129 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3130 klass = mono_class_from_mono_type (type);
3132 gclass = type->data.generic_class;
3133 g_assert (gclass->is_dynamic);
3135 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3138 name = mono_string_to_utf8 (rmb.name);
3140 sig = method_builder_encode_signature (assembly, &rmb);
3142 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3144 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3145 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3147 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3148 klass = mono_class_from_mono_type (type);
3150 sig = method_encode_signature (assembly, mono_method_signature (mm));
3151 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3153 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3154 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3158 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3163 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3167 MonoGenericContext tmp_context;
3168 MonoType **type_argv;
3169 MonoGenericInst *ginst;
3170 MonoMethod *method, *inflated;
3173 init_type_builder_generics ((MonoObject*)m->inst);
3175 method = inflate_method (m->inst, (MonoObject*)m->mb);
3177 klass = method->klass;
3179 if (m->method_args == NULL)
3182 if (method->is_inflated)
3183 method = ((MonoMethodInflated *) method)->declaring;
3185 count = mono_array_length (m->method_args);
3187 type_argv = g_new0 (MonoType *, count);
3188 for (i = 0; i < count; i++) {
3189 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3190 type_argv [i] = mono_reflection_type_get_handle (garg);
3192 ginst = mono_metadata_get_generic_inst (count, type_argv);
3195 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3196 tmp_context.method_inst = ginst;
3198 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3199 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3204 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3206 guint32 sig, token = 0;
3210 mono_error_init (error);
3212 if (m->method_args) {
3213 MonoMethod *inflated;
3215 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3216 if (create_methodspec)
3217 token = mono_image_get_methodspec_token (assembly, inflated);
3219 token = mono_image_get_inflated_method_token (assembly, inflated);
3223 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3227 if (is_sre_method_builder (mono_object_class (m->mb))) {
3228 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3229 MonoGenericClass *gclass;
3230 ReflectionMethodBuilder rmb;
3233 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3234 klass = mono_class_from_mono_type (type);
3235 gclass = type->data.generic_class;
3236 g_assert (gclass->is_dynamic);
3238 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3241 name = mono_string_to_utf8 (rmb.name);
3243 sig = method_builder_encode_signature (assembly, &rmb);
3245 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3247 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3248 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3250 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3251 klass = mono_class_from_mono_type (type);
3253 sig = method_encode_signature (assembly, mono_method_signature (mm));
3254 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3256 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3257 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3260 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3265 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3269 guint32 nparams = context->method_inst->type_argc;
3272 if (!assembly->save)
3275 sigbuffer_init (&buf, 32);
3277 * FIXME: vararg, explicit_this, differenc call_conv values...
3279 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3280 sigbuffer_add_value (&buf, nparams);
3282 for (i = 0; i < nparams; i++)
3283 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3285 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3286 sigbuffer_free (&buf);
3291 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3293 MonoDynamicTable *table;
3295 guint32 token, mtoken = 0, sig;
3296 MonoMethodInflated *imethod;
3297 MonoMethod *declaring;
3299 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3301 g_assert (method->is_inflated);
3302 imethod = (MonoMethodInflated *) method;
3303 declaring = imethod->declaring;
3305 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3306 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3308 if (!mono_method_signature (declaring)->generic_param_count)
3311 switch (mono_metadata_token_table (mtoken)) {
3312 case MONO_TABLE_MEMBERREF:
3313 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3315 case MONO_TABLE_METHOD:
3316 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3319 g_assert_not_reached ();
3322 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3324 if (assembly->save) {
3325 alloc_table (table, table->rows + 1);
3326 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3327 values [MONO_METHODSPEC_METHOD] = mtoken;
3328 values [MONO_METHODSPEC_SIGNATURE] = sig;
3331 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3338 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3340 MonoMethodInflated *imethod;
3343 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3347 g_assert (method->is_inflated);
3348 imethod = (MonoMethodInflated *) method;
3350 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3351 token = method_encode_methodspec (assembly, method);
3353 guint32 sig = method_encode_signature (
3354 assembly, mono_method_signature (imethod->declaring));
3355 token = mono_image_get_memberref_token (
3356 assembly, &method->klass->byval_arg, method->name, sig);
3359 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3364 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3366 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3369 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3370 token = mono_image_get_memberref_token (
3371 assembly, &m->klass->byval_arg, m->name, sig);
3377 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3379 MonoDynamicTable *table;
3388 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3389 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3390 * Because of this, we must not insert it into the `typeref' hash table.
3392 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3393 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3397 sigbuffer_init (&buf, 32);
3399 g_assert (tb->generic_params);
3400 klass = mono_class_from_mono_type (type);
3402 if (tb->generic_container)
3403 mono_reflection_create_generic_class (tb);
3405 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3406 g_assert (klass->generic_container);
3407 sigbuffer_add_value (&buf, klass->byval_arg.type);
3408 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3410 count = mono_array_length (tb->generic_params);
3411 sigbuffer_add_value (&buf, count);
3412 for (i = 0; i < count; i++) {
3413 MonoReflectionGenericParam *gparam;
3415 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3417 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3420 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3422 if (assembly->save) {
3423 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3424 alloc_table (table, table->rows + 1);
3425 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3426 values [MONO_TYPESPEC_SIGNATURE] = token;
3428 sigbuffer_free (&buf);
3430 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3431 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3437 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3440 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3442 int i, count, len, pos;
3447 count += mono_array_length (modreq);
3449 count += mono_array_length (modopt);
3452 return mono_metadata_type_dup (NULL, type);
3454 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3455 t = (MonoType *)g_malloc (len);
3456 memcpy (t, type, MONO_SIZEOF_TYPE);
3458 t->num_mods = count;
3461 for (i = 0; i < mono_array_length (modreq); ++i) {
3462 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3463 t->modifiers [pos].required = 1;
3464 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3469 for (i = 0; i < mono_array_length (modopt); ++i) {
3470 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3471 t->modifiers [pos].required = 0;
3472 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3481 init_type_builder_generics (MonoObject *type)
3483 MonoReflectionTypeBuilder *tb;
3485 if (!is_sre_type_builder(mono_object_class (type)))
3487 tb = (MonoReflectionTypeBuilder *)type;
3489 if (tb && tb->generic_container)
3490 mono_reflection_create_generic_class (tb);
3494 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3496 MonoDynamicTable *table;
3497 MonoType *custom = NULL, *type;
3499 guint32 token, pclass, parent, sig;
3502 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3506 /* FIXME: is this call necessary? */
3507 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3508 name = mono_string_to_utf8 (fb->name);
3510 /*FIXME this is one more layer of ugliness due how types are created.*/
3511 init_type_builder_generics (fb->type);
3513 /* fb->type does not include the custom modifiers */
3514 /* FIXME: We should do this in one place when a fieldbuilder is created */
3515 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3516 if (fb->modreq || fb->modopt)
3517 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3519 sig = fieldref_encode_signature (assembly, NULL, type);
3522 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3523 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3525 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3526 parent >>= MONO_TYPEDEFORREF_BITS;
3528 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3530 if (assembly->save) {
3531 alloc_table (table, table->rows + 1);
3532 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3533 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3534 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3535 values [MONO_MEMBERREF_SIGNATURE] = sig;
3538 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3540 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3546 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3552 if (!assembly->save)
3555 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3556 g_assert (helper->type == 2);
3558 if (helper->arguments)
3559 nargs = mono_array_length (helper->arguments);
3563 sigbuffer_init (&buf, 32);
3565 /* Encode calling convention */
3566 /* Change Any to Standard */
3567 if ((helper->call_conv & 0x03) == 0x03)
3568 helper->call_conv = 0x01;
3569 /* explicit_this implies has_this */
3570 if (helper->call_conv & 0x40)
3571 helper->call_conv &= 0x20;
3573 if (helper->call_conv == 0) { /* Unmanaged */
3574 idx = helper->unmanaged_call_conv - 1;
3577 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3578 if (helper->call_conv & 0x02) /* varargs */
3582 sigbuffer_add_byte (&buf, idx);
3583 sigbuffer_add_value (&buf, nargs);
3584 encode_reflection_type (assembly, helper->return_type, &buf);
3585 for (i = 0; i < nargs; ++i) {
3586 MonoArray *modreqs = NULL;
3587 MonoArray *modopts = NULL;
3588 MonoReflectionType *pt;
3590 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3591 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3592 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3593 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3595 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3596 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3597 encode_reflection_type (assembly, pt, &buf);
3599 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3600 sigbuffer_free (&buf);
3606 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3609 MonoDynamicTable *table;
3612 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3613 idx = table->next_idx ++;
3615 alloc_table (table, table->rows);
3616 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3618 values [MONO_STAND_ALONE_SIGNATURE] =
3619 mono_reflection_encode_sighelper (assembly, helper);
3625 reflection_cc_to_file (int call_conv) {
3626 switch (call_conv & 0x3) {
3628 case 1: return MONO_CALL_DEFAULT;
3629 case 2: return MONO_CALL_VARARG;
3631 g_assert_not_reached ();
3635 #endif /* !DISABLE_REFLECTION_EMIT */
3639 MonoMethodSignature *sig;
3644 #ifndef DISABLE_REFLECTION_EMIT
3646 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3651 MonoMethodSignature *sig;
3655 name = mono_string_to_utf8 (m->name);
3656 nparams = mono_array_length (m->parameters);
3657 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3659 sig->sentinelpos = -1;
3660 sig->call_convention = reflection_cc_to_file (m->call_conv);
3661 sig->param_count = nparams;
3662 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3663 mtype = mono_reflection_type_get_handle (m->parent);
3664 for (i = 0; i < nparams; ++i)
3665 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3667 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3668 am = (ArrayMethod *)tmp->data;
3669 if (strcmp (name, am->name) == 0 &&
3670 mono_metadata_type_equal (am->parent, mtype) &&
3671 mono_metadata_signature_equal (am->sig, sig)) {
3674 m->table_idx = am->token & 0xffffff;
3678 am = g_new0 (ArrayMethod, 1);
3682 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3683 method_encode_signature (assembly, sig));
3684 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3685 m->table_idx = am->token & 0xffffff;
3690 * Insert into the metadata tables all the info about the TypeBuilder tb.
3691 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3694 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3696 MonoDynamicTable *table;
3698 int i, is_object = 0, is_system = 0;
3701 mono_error_init (error);
3703 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3704 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3705 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3706 n = mono_string_to_utf8 (tb->name);
3707 if (strcmp (n, "Object") == 0)
3709 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3711 n = mono_string_to_utf8 (tb->nspace);
3712 if (strcmp (n, "System") == 0)
3714 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3716 if (tb->parent && !(is_system && is_object) &&
3717 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3718 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3720 values [MONO_TYPEDEF_EXTENDS] = 0;
3722 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3723 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3726 * if we have explicitlayout or sequentiallayouts, output data in the
3727 * ClassLayout table.
3729 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3730 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3731 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3733 alloc_table (table, table->rows);
3734 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3735 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3736 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3737 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3740 /* handle interfaces */
3741 if (tb->interfaces) {
3742 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3744 table->rows += mono_array_length (tb->interfaces);
3745 alloc_table (table, table->rows);
3746 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3747 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3748 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3749 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3750 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3751 values += MONO_INTERFACEIMPL_SIZE;
3757 table = &assembly->tables [MONO_TABLE_FIELD];
3758 table->rows += tb->num_fields;
3759 alloc_table (table, table->rows);
3760 for (i = 0; i < tb->num_fields; ++i)
3761 mono_image_get_field_info (
3762 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3765 /* handle constructors */
3767 table = &assembly->tables [MONO_TABLE_METHOD];
3768 table->rows += mono_array_length (tb->ctors);
3769 alloc_table (table, table->rows);
3770 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3771 if (!mono_image_get_ctor_info (domain,
3772 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3778 /* handle methods */
3780 table = &assembly->tables [MONO_TABLE_METHOD];
3781 table->rows += tb->num_methods;
3782 alloc_table (table, table->rows);
3783 for (i = 0; i < tb->num_methods; ++i) {
3784 if (!mono_image_get_method_info (
3785 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3790 /* Do the same with properties etc.. */
3791 if (tb->events && mono_array_length (tb->events)) {
3792 table = &assembly->tables [MONO_TABLE_EVENT];
3793 table->rows += mono_array_length (tb->events);
3794 alloc_table (table, table->rows);
3795 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3797 alloc_table (table, table->rows);
3798 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3799 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3800 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3801 for (i = 0; i < mono_array_length (tb->events); ++i)
3802 mono_image_get_event_info (
3803 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3805 if (tb->properties && mono_array_length (tb->properties)) {
3806 table = &assembly->tables [MONO_TABLE_PROPERTY];
3807 table->rows += mono_array_length (tb->properties);
3808 alloc_table (table, table->rows);
3809 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3811 alloc_table (table, table->rows);
3812 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3813 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3814 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3815 for (i = 0; i < mono_array_length (tb->properties); ++i)
3816 mono_image_get_property_info (
3817 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3820 /* handle generic parameters */
3821 if (tb->generic_params) {
3822 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3823 table->rows += mono_array_length (tb->generic_params);
3824 alloc_table (table, table->rows);
3825 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3826 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3828 mono_image_get_generic_param_info (
3829 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3833 mono_image_add_decl_security (assembly,
3834 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3837 MonoDynamicTable *ntable;
3839 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3840 ntable->rows += mono_array_length (tb->subtypes);
3841 alloc_table (ntable, ntable->rows);
3842 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3844 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3845 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3847 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3848 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3849 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3850 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3851 mono_string_to_utf8 (tb->name), tb->table_idx,
3852 ntable->next_idx, ntable->rows);*/
3853 values += MONO_NESTED_CLASS_SIZE;
3863 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3867 mono_ptr_array_append (*types, type);
3869 if (!type->subtypes)
3872 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3873 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3874 collect_types (types, subtype);
3879 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3881 if ((*type1)->table_idx < (*type2)->table_idx)
3884 if ((*type1)->table_idx > (*type2)->table_idx)
3891 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3894 mono_error_init (error);
3897 for (i = 0; i < mono_array_length (pinfo); ++i) {
3898 MonoReflectionParamBuilder *pb;
3899 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3902 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3910 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3913 mono_error_init (error);
3915 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3918 for (i = 0; i < tb->num_fields; ++i) {
3919 MonoReflectionFieldBuilder* fb;
3920 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3921 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3926 for (i = 0; i < mono_array_length (tb->events); ++i) {
3927 MonoReflectionEventBuilder* eb;
3928 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3929 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3933 if (tb->properties) {
3934 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3935 MonoReflectionPropertyBuilder* pb;
3936 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3937 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3942 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3943 MonoReflectionCtorBuilder* cb;
3944 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3945 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3946 !params_add_cattrs (assembly, cb->pinfo, error))
3952 for (i = 0; i < tb->num_methods; ++i) {
3953 MonoReflectionMethodBuilder* mb;
3954 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3955 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3956 !params_add_cattrs (assembly, mb->pinfo, error))
3962 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3963 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3972 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3976 mono_error_init (error);
3978 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3981 if (moduleb->global_methods) {
3982 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3983 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3984 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3985 !params_add_cattrs (assembly, mb->pinfo, error))
3990 if (moduleb->global_fields) {
3991 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3992 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3993 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3998 if (moduleb->types) {
3999 for (i = 0; i < moduleb->num_types; ++i) {
4000 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4009 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4011 MonoDynamicTable *table;
4015 char *b = blob_size;
4018 table = &assembly->tables [MONO_TABLE_FILE];
4020 alloc_table (table, table->rows);
4021 values = table->values + table->next_idx * MONO_FILE_SIZE;
4022 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4023 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4024 if (image_is_dynamic (module->image)) {
4025 /* This depends on the fact that the main module is emitted last */
4026 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4027 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4030 path = g_strdup (module->image->name);
4032 mono_sha1_get_digest_from_file (path, hash);
4035 mono_metadata_encode_value (20, b, &b);
4036 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4037 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4042 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4044 MonoDynamicTable *table;
4047 table = &assembly->tables [MONO_TABLE_MODULE];
4048 mb->table_idx = table->next_idx ++;
4049 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4050 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4053 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4054 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4055 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4056 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4060 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4061 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4063 MonoDynamicTable *table;
4067 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4068 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4071 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4073 alloc_table (table, table->rows);
4074 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4076 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4077 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4078 if (klass->nested_in)
4079 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4081 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4082 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4083 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4085 res = table->next_idx;
4089 /* Emit nested types */
4090 if (klass->ext && klass->ext->nested_classes) {
4093 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4094 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4101 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4102 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4107 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4109 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4111 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4112 parent_index, assembly);
4116 * We need to do this ourselves since klass->nested_classes is not set up.
4119 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4120 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4125 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4126 guint32 module_index, MonoDynamicImage *assembly)
4128 MonoImage *image = module->image;
4132 t = &image->tables [MONO_TABLE_TYPEDEF];
4134 for (i = 0; i < t->rows; ++i) {
4136 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4137 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4139 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4140 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4145 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4147 MonoDynamicTable *table;
4149 guint32 scope, scope_idx, impl, current_idx;
4150 gboolean forwarder = TRUE;
4151 gpointer iter = NULL;
4154 if (klass->nested_in) {
4155 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4158 scope = resolution_scope_from_image (assembly, klass->image);
4159 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4160 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4161 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4164 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4167 alloc_table (table, table->rows);
4168 current_idx = table->next_idx;
4169 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4171 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4172 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4173 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4174 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4175 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4179 while ((nested = mono_class_get_nested_types (klass, &iter)))
4180 add_exported_type (assemblyb, assembly, nested, current_idx);
4184 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4189 if (!assemblyb->type_forwarders)
4192 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4193 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4198 type = mono_reflection_type_get_handle (t);
4201 klass = mono_class_from_mono_type (type);
4203 add_exported_type (assemblyb, assembly, klass, 0);
4207 #define align_pointer(base,p)\
4209 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4211 (p) += 4 - (__diff & 3);\
4215 compare_constants (const void *a, const void *b)
4217 const guint32 *a_values = (const guint32 *)a;
4218 const guint32 *b_values = (const guint32 *)b;
4219 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4223 compare_semantics (const void *a, const void *b)
4225 const guint32 *a_values = (const guint32 *)a;
4226 const guint32 *b_values = (const guint32 *)b;
4227 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4230 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4234 compare_custom_attrs (const void *a, const void *b)
4236 const guint32 *a_values = (const guint32 *)a;
4237 const guint32 *b_values = (const guint32 *)b;
4239 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4243 compare_field_marshal (const void *a, const void *b)
4245 const guint32 *a_values = (const guint32 *)a;
4246 const guint32 *b_values = (const guint32 *)b;
4248 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4252 compare_nested (const void *a, const void *b)
4254 const guint32 *a_values = (const guint32 *)a;
4255 const guint32 *b_values = (const guint32 *)b;
4257 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4261 compare_genericparam (const void *a, const void *b)
4263 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4264 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4266 if ((*b_entry)->owner == (*a_entry)->owner)
4268 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4269 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4271 return (*a_entry)->owner - (*b_entry)->owner;
4275 compare_declsecurity_attrs (const void *a, const void *b)
4277 const guint32 *a_values = (const guint32 *)a;
4278 const guint32 *b_values = (const guint32 *)b;
4280 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4284 compare_interface_impl (const void *a, const void *b)
4286 const guint32 *a_values = (const guint32 *)a;
4287 const guint32 *b_values = (const guint32 *)b;
4289 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4293 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4297 pad_heap (MonoDynamicStream *sh)
4299 if (sh->index & 3) {
4300 int sz = 4 - (sh->index & 3);
4301 memset (sh->data + sh->index, 0, sz);
4308 MonoDynamicStream *stream;
4312 * build_compressed_metadata() fills in the blob of data that represents the
4313 * raw metadata as it will be saved in the PE file. The five streams are output
4314 * and the metadata tables are comnpressed from the guint32 array representation,
4315 * to the compressed on-disk format.
4318 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4320 MonoDynamicTable *table;
4322 guint64 valid_mask = 0;
4323 guint64 sorted_mask;
4324 guint32 heapt_size = 0;
4325 guint32 meta_size = 256; /* allow for header and other stuff */
4326 guint32 table_offset;
4327 guint32 ntables = 0;
4333 struct StreamDesc stream_desc [5];
4335 mono_error_init (error);
4337 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4338 for (i = 0; i < assembly->gen_params->len; i++) {
4339 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4340 if (!write_generic_param_entry (assembly, entry, error))
4344 stream_desc [0].name = "#~";
4345 stream_desc [0].stream = &assembly->tstream;
4346 stream_desc [1].name = "#Strings";
4347 stream_desc [1].stream = &assembly->sheap;
4348 stream_desc [2].name = "#US";
4349 stream_desc [2].stream = &assembly->us;
4350 stream_desc [3].name = "#Blob";
4351 stream_desc [3].stream = &assembly->blob;
4352 stream_desc [4].name = "#GUID";
4353 stream_desc [4].stream = &assembly->guid;
4355 /* tables that are sorted */
4356 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4357 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4358 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4359 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4360 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4361 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4362 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4364 /* Compute table sizes */
4365 /* the MonoImage has already been created in mono_image_basic_init() */
4366 meta = &assembly->image;
4368 /* sizes should be multiple of 4 */
4369 pad_heap (&assembly->blob);
4370 pad_heap (&assembly->guid);
4371 pad_heap (&assembly->sheap);
4372 pad_heap (&assembly->us);
4374 /* Setup the info used by compute_sizes () */
4375 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4376 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4377 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4379 meta_size += assembly->blob.index;
4380 meta_size += assembly->guid.index;
4381 meta_size += assembly->sheap.index;
4382 meta_size += assembly->us.index;
4384 for (i=0; i < MONO_TABLE_NUM; ++i)
4385 meta->tables [i].rows = assembly->tables [i].rows;
4387 for (i = 0; i < MONO_TABLE_NUM; i++){
4388 if (meta->tables [i].rows == 0)
4390 valid_mask |= (guint64)1 << i;
4392 meta->tables [i].row_size = mono_metadata_compute_size (
4393 meta, i, &meta->tables [i].size_bitfield);
4394 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4396 heapt_size += 24; /* #~ header size */
4397 heapt_size += ntables * 4;
4398 /* make multiple of 4 */
4401 meta_size += heapt_size;
4402 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4403 p = (unsigned char*)meta->raw_metadata;
4404 /* the metadata signature */
4405 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4406 /* version numbers and 4 bytes reserved */
4407 int16val = (guint16*)p;
4408 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4409 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4411 /* version string */
4412 int32val = (guint32*)p;
4413 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4415 memcpy (p, meta->version, strlen (meta->version));
4416 p += GUINT32_FROM_LE (*int32val);
4417 align_pointer (meta->raw_metadata, p);
4418 int16val = (guint16*)p;
4419 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4420 *int16val = GUINT16_TO_LE (5); /* number of streams */
4424 * write the stream info.
4426 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4427 table_offset += 3; table_offset &= ~3;
4429 assembly->tstream.index = heapt_size;
4430 for (i = 0; i < 5; ++i) {
4431 int32val = (guint32*)p;
4432 stream_desc [i].stream->offset = table_offset;
4433 *int32val++ = GUINT32_TO_LE (table_offset);
4434 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4435 table_offset += GUINT32_FROM_LE (*int32val);
4436 table_offset += 3; table_offset &= ~3;
4438 strcpy ((char*)p, stream_desc [i].name);
4439 p += strlen (stream_desc [i].name) + 1;
4440 align_pointer (meta->raw_metadata, p);
4443 * now copy the data, the table stream header and contents goes first.
4445 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4446 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4447 int32val = (guint32*)p;
4448 *int32val = GUINT32_TO_LE (0); /* reserved */
4451 *p++ = 2; /* version */
4454 if (meta->idx_string_wide)
4456 if (meta->idx_guid_wide)
4458 if (meta->idx_blob_wide)
4461 *p++ = 1; /* reserved */
4462 int64val = (guint64*)p;
4463 *int64val++ = GUINT64_TO_LE (valid_mask);
4464 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4466 int32val = (guint32*)p;
4467 for (i = 0; i < MONO_TABLE_NUM; i++){
4468 if (meta->tables [i].rows == 0)
4470 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4472 p = (unsigned char*)int32val;
4474 /* sort the tables that still need sorting */
4475 table = &assembly->tables [MONO_TABLE_CONSTANT];
4477 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4478 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4480 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4481 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4483 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4484 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4486 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4487 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4489 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4490 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4491 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4493 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4494 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4496 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4498 /* compress the tables */
4499 for (i = 0; i < MONO_TABLE_NUM; i++){
4502 guint32 bitfield = meta->tables [i].size_bitfield;
4503 if (!meta->tables [i].rows)
4505 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4506 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4507 meta->tables [i].base = (char*)p;
4508 for (row = 1; row <= meta->tables [i].rows; ++row) {
4509 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4510 for (col = 0; col < assembly->tables [i].columns; ++col) {
4511 switch (mono_metadata_table_size (bitfield, col)) {
4513 *p++ = values [col];
4516 *p++ = values [col] & 0xff;
4517 *p++ = (values [col] >> 8) & 0xff;
4520 *p++ = values [col] & 0xff;
4521 *p++ = (values [col] >> 8) & 0xff;
4522 *p++ = (values [col] >> 16) & 0xff;
4523 *p++ = (values [col] >> 24) & 0xff;
4526 g_assert_not_reached ();
4530 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4533 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4534 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4535 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4536 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4537 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4539 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4545 * Some tables in metadata need to be sorted according to some criteria, but
4546 * when methods and fields are first created with reflection, they may be assigned a token
4547 * that doesn't correspond to the final token they will get assigned after the sorting.
4548 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4549 * with the reflection objects that represent them. Once all the tables are set up, the
4550 * reflection objects will contains the correct table index. fixup_method() will fixup the
4551 * tokens for the method with ILGenerator @ilgen.
4554 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4556 guint32 code_idx = GPOINTER_TO_UINT (value);
4557 MonoReflectionILTokenInfo *iltoken;
4558 MonoReflectionFieldBuilder *field;
4559 MonoReflectionCtorBuilder *ctor;
4560 MonoReflectionMethodBuilder *method;
4561 MonoReflectionTypeBuilder *tb;
4562 MonoReflectionArrayMethod *am;
4564 unsigned char *target;
4566 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4567 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4568 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4569 switch (target [3]) {
4570 case MONO_TABLE_FIELD:
4571 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4572 field = (MonoReflectionFieldBuilder *)iltoken->member;
4573 idx = field->table_idx;
4574 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4575 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4576 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4578 g_assert_not_reached ();
4581 case MONO_TABLE_METHOD:
4582 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4583 method = (MonoReflectionMethodBuilder *)iltoken->member;
4584 idx = method->table_idx;
4585 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4586 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4587 idx = ctor->table_idx;
4588 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4589 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4590 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4591 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4593 g_assert_not_reached ();
4596 case MONO_TABLE_TYPEDEF:
4597 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4598 g_assert_not_reached ();
4599 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4600 idx = tb->table_idx;
4602 case MONO_TABLE_MEMBERREF:
4603 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4604 am = (MonoReflectionArrayMethod*)iltoken->member;
4605 idx = am->table_idx;
4606 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4607 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4608 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4609 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4610 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4611 g_assert (m->klass->generic_class || m->klass->generic_container);
4613 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4615 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4616 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4617 g_assert (is_field_on_inst (f));
4619 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4620 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4622 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4624 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4626 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4629 g_assert_not_reached ();
4632 case MONO_TABLE_METHODSPEC:
4633 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4634 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4635 g_assert (mono_method_signature (m)->generic_param_count);
4637 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4639 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4642 g_assert_not_reached ();
4646 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4648 target [0] = idx & 0xff;
4649 target [1] = (idx >> 8) & 0xff;
4650 target [2] = (idx >> 16) & 0xff;
4657 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4658 * value is not known when the table is emitted.
4661 fixup_cattrs (MonoDynamicImage *assembly)
4663 MonoDynamicTable *table;
4665 guint32 type, i, idx, token;
4668 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4670 for (i = 0; i < table->rows; ++i) {
4671 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4673 type = values [MONO_CUSTOM_ATTR_TYPE];
4674 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4675 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4676 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4677 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4680 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4681 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4682 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4683 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4684 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4685 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4686 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4687 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4694 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4696 MonoDynamicTable *table;
4699 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4701 alloc_table (table, table->rows);
4702 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4703 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4704 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4705 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4706 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4711 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4713 MonoDynamicTable *table;
4717 char *b = blob_size;
4719 guint32 idx, offset;
4721 if (rsrc->filename) {
4722 name = mono_string_to_utf8 (rsrc->filename);
4723 sname = g_path_get_basename (name);
4725 table = &assembly->tables [MONO_TABLE_FILE];
4727 alloc_table (table, table->rows);
4728 values = table->values + table->next_idx * MONO_FILE_SIZE;
4729 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4730 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4733 mono_sha1_get_digest_from_file (name, hash);
4734 mono_metadata_encode_value (20, b, &b);
4735 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4736 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4738 idx = table->next_idx++;
4740 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4746 data = mono_array_addr (rsrc->data, char, 0);
4747 len = mono_array_length (rsrc->data);
4753 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4754 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4755 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4756 mono_image_add_stream_data (&assembly->resources, data, len);
4760 * The entry should be emitted into the MANIFESTRESOURCE table of
4761 * the main module, but that needs to reference the FILE table
4762 * which isn't emitted yet.
4769 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4773 set_version_from_string (MonoString *version, guint32 *values)
4775 gchar *ver, *p, *str;
4778 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4779 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4780 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4781 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4784 ver = str = mono_string_to_utf8 (version);
4785 for (i = 0; i < 4; ++i) {
4786 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4792 /* handle Revision and Build */
4802 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4806 char *b = blob_size;
4811 len = mono_array_length (pkey);
4812 mono_metadata_encode_value (len, b, &b);
4813 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4814 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4816 assembly->public_key = (guint8 *)g_malloc (len);
4817 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4818 assembly->public_key_len = len;
4820 /* Special case: check for ECMA key (16 bytes) */
4821 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4822 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4823 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4824 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4825 /* minimum key size (in 2.0) is 384 bits */
4826 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4828 /* FIXME - verifier */
4829 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4830 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4832 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4838 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4840 MonoDynamicTable *table;
4841 MonoDynamicImage *assembly;
4842 MonoReflectionAssemblyBuilder *assemblyb;
4846 guint32 module_index;
4848 assemblyb = moduleb->assemblyb;
4849 assembly = moduleb->dynamic_image;
4850 domain = mono_object_domain (assemblyb);
4852 /* Emit ASSEMBLY table */
4853 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4854 alloc_table (table, 1);
4855 values = table->values + MONO_ASSEMBLY_SIZE;
4856 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4857 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4858 if (assemblyb->culture) {
4859 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4861 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4863 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4864 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4865 set_version_from_string (assemblyb->version, values);
4867 /* Emit FILE + EXPORTED_TYPE table */
4869 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4871 MonoReflectionModuleBuilder *file_module =
4872 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4873 if (file_module != moduleb) {
4874 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4876 if (file_module->types) {
4877 for (j = 0; j < file_module->num_types; ++j) {
4878 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4879 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4884 if (assemblyb->loaded_modules) {
4885 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4886 MonoReflectionModule *file_module =
4887 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4888 mono_image_fill_file_table (domain, file_module, assembly);
4890 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4893 if (assemblyb->type_forwarders)
4894 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4896 /* Emit MANIFESTRESOURCE table */
4898 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4900 MonoReflectionModuleBuilder *file_module =
4901 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4902 /* The table for the main module is emitted later */
4903 if (file_module != moduleb) {
4905 if (file_module->resources) {
4906 int len = mono_array_length (file_module->resources);
4907 for (j = 0; j < len; ++j) {
4908 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4909 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4916 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4919 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4920 * for the modulebuilder @moduleb.
4921 * At the end of the process, method and field tokens are fixed up and the
4922 * on-disk compressed metadata representation is created.
4923 * Return TRUE on success, or FALSE on failure and sets @error
4926 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4928 MonoDynamicTable *table;
4929 MonoDynamicImage *assembly;
4930 MonoReflectionAssemblyBuilder *assemblyb;
4936 mono_error_init (error);
4938 assemblyb = moduleb->assemblyb;
4939 assembly = moduleb->dynamic_image;
4940 domain = mono_object_domain (assemblyb);
4942 if (assembly->text_rva)
4945 assembly->text_rva = START_TEXT_RVA;
4947 if (moduleb->is_main) {
4948 mono_image_emit_manifest (moduleb);
4951 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4952 table->rows = 1; /* .<Module> */
4954 alloc_table (table, table->rows);
4956 * Set the first entry.
4958 values = table->values + table->columns;
4959 values [MONO_TYPEDEF_FLAGS] = 0;
4960 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4961 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4962 values [MONO_TYPEDEF_EXTENDS] = 0;
4963 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4964 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4967 * handle global methods
4968 * FIXME: test what to do when global methods are defined in multiple modules.
4970 if (moduleb->global_methods) {
4971 table = &assembly->tables [MONO_TABLE_METHOD];
4972 table->rows += mono_array_length (moduleb->global_methods);
4973 alloc_table (table, table->rows);
4974 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4975 if (!mono_image_get_method_info (
4976 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
4980 if (moduleb->global_fields) {
4981 table = &assembly->tables [MONO_TABLE_FIELD];
4982 table->rows += mono_array_length (moduleb->global_fields);
4983 alloc_table (table, table->rows);
4984 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4985 mono_image_get_field_info (
4986 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4989 table = &assembly->tables [MONO_TABLE_MODULE];
4990 alloc_table (table, 1);
4991 mono_image_fill_module_table (domain, moduleb, assembly);
4993 /* Collect all types into a list sorted by their table_idx */
4994 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4997 for (i = 0; i < moduleb->num_types; ++i) {
4998 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4999 collect_types (&types, type);
5002 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5003 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5004 table->rows += mono_ptr_array_size (types);
5005 alloc_table (table, table->rows);
5008 * Emit type names + namespaces at one place inside the string heap,
5009 * so load_class_names () needs to touch fewer pages.
5011 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5012 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5013 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5015 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5016 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5017 string_heap_insert_mstring (&assembly->sheap, tb->name);
5020 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5021 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5022 if (!mono_image_get_type_info (domain, type, assembly, error))
5027 * table->rows is already set above and in mono_image_fill_module_table.
5029 /* add all the custom attributes at the end, once all the indexes are stable */
5030 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5033 /* CAS assembly permissions */
5034 if (assemblyb->permissions_minimum)
5035 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5036 if (assemblyb->permissions_optional)
5037 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5038 if (assemblyb->permissions_refused)
5039 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5041 if (!module_add_cattrs (assembly, moduleb, error))
5045 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5047 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5048 * the final tokens and don't need another fixup pass. */
5050 if (moduleb->global_methods) {
5051 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5052 MonoReflectionMethodBuilder *mb = mono_array_get (
5053 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5054 if (!mono_image_add_methodimpl (assembly, mb, error))
5059 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5060 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5061 if (type->methods) {
5062 for (j = 0; j < type->num_methods; ++j) {
5063 MonoReflectionMethodBuilder *mb = mono_array_get (
5064 type->methods, MonoReflectionMethodBuilder*, j);
5066 if (!mono_image_add_methodimpl (assembly, mb, error))
5072 fixup_cattrs (assembly);
5075 mono_ptr_array_destroy (types);
5078 return mono_error_ok (error);
5081 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5084 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5086 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5089 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5093 guint32 import_lookup_table;
5097 guint32 import_address_table_rva;
5105 #ifndef DISABLE_REFLECTION_EMIT
5108 * mono_image_insert_string:
5109 * @module: module builder object
5112 * Insert @str into the user string stream of @module.
5115 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5117 MonoDynamicImage *assembly;
5122 if (!module->dynamic_image)
5123 mono_image_module_basic_init (module);
5125 assembly = module->dynamic_image;
5127 if (assembly->save) {
5128 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5129 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5130 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5132 char *swapped = g_malloc (2 * mono_string_length (str));
5133 const char *p = (const char*)mono_string_chars (str);
5135 swap_with_size (swapped, p, 2, mono_string_length (str));
5136 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5140 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5142 mono_image_add_stream_data (&assembly->us, "", 1);
5144 idx = assembly->us.index ++;
5147 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5149 return MONO_TOKEN_STRING | idx;
5153 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5157 MonoMethodSignature *sig;
5159 mono_error_init (error);
5161 klass = obj->vtable->klass;
5162 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5163 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5164 MonoMethodSignature *old;
5165 guint32 sig_token, parent;
5168 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5170 nargs = mono_array_length (opt_param_types);
5171 old = mono_method_signature (method);
5172 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5174 sig->hasthis = old->hasthis;
5175 sig->explicit_this = old->explicit_this;
5176 sig->call_convention = old->call_convention;
5177 sig->generic_param_count = old->generic_param_count;
5178 sig->param_count = old->param_count + nargs;
5179 sig->sentinelpos = old->param_count;
5180 sig->ret = old->ret;
5182 for (i = 0; i < old->param_count; i++)
5183 sig->params [i] = old->params [i];
5185 for (i = 0; i < nargs; i++) {
5186 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5187 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5190 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5191 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5192 parent >>= MONO_TYPEDEFORREF_BITS;
5194 parent <<= MONO_MEMBERREF_PARENT_BITS;
5195 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5197 sig_token = method_encode_signature (assembly, sig);
5198 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5199 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5200 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5201 ReflectionMethodBuilder rmb;
5202 guint32 parent, sig_token;
5203 int nopt_args, nparams, ngparams, i;
5205 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5208 rmb.opt_types = opt_param_types;
5209 nopt_args = mono_array_length (opt_param_types);
5211 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5212 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5213 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5215 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5216 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5217 sig->call_convention = rmb.call_conv;
5218 sig->generic_param_count = ngparams;
5219 sig->param_count = nparams + nopt_args;
5220 sig->sentinelpos = nparams;
5221 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5223 for (i = 0; i < nparams; i++) {
5224 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5225 sig->params [i] = mono_reflection_type_get_handle (rt);
5228 for (i = 0; i < nopt_args; i++) {
5229 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5230 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5233 sig_token = method_builder_encode_signature (assembly, &rmb);
5235 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5236 if (!mono_error_ok (error))
5238 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5240 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5241 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5243 char *name = mono_string_to_utf8 (rmb.name);
5244 token = mono_image_get_varargs_method_token (
5245 assembly, parent, name, sig_token);
5248 g_error ("requested method token for %s\n", klass->name);
5251 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5252 register_dyn_token (assembly, token, obj);
5255 g_assert (!mono_error_ok (error));
5260 * mono_image_create_token:
5261 * @assembly: a dynamic assembly
5263 * @register_token: Whenever to register the token in the assembly->tokens hash.
5265 * Get a token to insert in the IL code stream for the given MemberInfo.
5266 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5267 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5271 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5272 gboolean create_open_instance, gboolean register_token,
5278 mono_error_init (error);
5280 klass = obj->vtable->klass;
5282 /* Check for user defined reflection objects */
5283 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5284 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5285 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5289 if (strcmp (klass->name, "MethodBuilder") == 0) {
5290 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5291 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5293 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5294 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5296 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5297 if (!mono_error_ok (error))
5300 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5301 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5302 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5303 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5305 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5306 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5308 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5309 if (!mono_error_ok (error))
5312 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5313 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5314 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5315 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5316 if (tb->generic_params) {
5317 token = mono_image_get_generic_field_token (assembly, fb);
5319 if (tb->module->dynamic_image == assembly) {
5320 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5322 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5325 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5326 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5327 if (create_open_instance && tb->generic_params) {
5329 init_type_builder_generics (obj);
5330 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5331 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5332 token = mono_metadata_token_from_dor (token);
5333 } else if (tb->module->dynamic_image == assembly) {
5334 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5337 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5338 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5340 } else if (strcmp (klass->name, "MonoType") == 0) {
5341 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5342 MonoClass *mc = mono_class_from_mono_type (type);
5343 token = mono_metadata_token_from_dor (
5344 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5345 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5346 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5347 token = mono_metadata_token_from_dor (
5348 mono_image_typedef_or_ref (assembly, type));
5349 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5350 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5351 token = mono_metadata_token_from_dor (
5352 mono_image_typedef_or_ref (assembly, type));
5353 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5354 strcmp (klass->name, "MonoMethod") == 0 ||
5355 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5356 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5357 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5358 if (m->method->is_inflated) {
5359 if (create_open_instance)
5360 token = mono_image_get_methodspec_token (assembly, m->method);
5362 token = mono_image_get_inflated_method_token (assembly, m->method);
5363 } else if ((m->method->klass->image == &assembly->image) &&
5364 !m->method->klass->generic_class) {
5365 static guint32 method_table_idx = 0xffffff;
5366 if (m->method->klass->wastypebuilder) {
5367 /* we use the same token as the one that was assigned
5368 * to the Methodbuilder.
5369 * FIXME: do the equivalent for Fields.
5371 token = m->method->token;
5374 * Each token should have a unique index, but the indexes are
5375 * assigned by managed code, so we don't know about them. An
5376 * easy solution is to count backwards...
5378 method_table_idx --;
5379 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5382 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5384 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5385 } else if (strcmp (klass->name, "MonoField") == 0) {
5386 MonoReflectionField *f = (MonoReflectionField *)obj;
5387 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5388 static guint32 field_table_idx = 0xffffff;
5390 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5392 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5394 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5395 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5396 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5397 token = mono_image_get_array_token (assembly, m);
5398 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5399 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5400 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5401 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5402 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5403 token = mono_metadata_token_from_dor (
5404 mono_image_typedef_or_ref (assembly, type));
5405 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5406 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5407 token = mono_image_get_field_on_inst_token (assembly, f);
5408 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5409 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5410 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5411 if (!mono_error_ok (error))
5413 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5414 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5415 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5416 if (!mono_error_ok (error))
5418 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5419 MonoReflectionType *type = (MonoReflectionType *)obj;
5420 token = mono_metadata_token_from_dor (
5421 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5423 g_error ("requested token for %s\n", klass->name);
5427 mono_image_register_token (assembly, token, obj);
5433 * mono_image_register_token:
5435 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5436 * the Module.ResolveXXXToken () methods to work.
5439 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5443 dynamic_image_lock (assembly);
5444 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5446 /* There could be multiple MethodInfo objects with the same token */
5447 //g_assert (prev == obj);
5449 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5451 dynamic_image_unlock (assembly);
5454 static MonoDynamicImage*
5455 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5457 static const guchar entrycode [16] = {0xff, 0x25, 0};
5458 MonoDynamicImage *image;
5461 const char *version;
5463 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5464 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5466 version = mono_get_runtime_info ()->runtime_version;
5469 /* The MonoGHashTable's need GC tracking */
5470 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5472 image = g_new0 (MonoDynamicImage, 1);
5475 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5477 /*g_print ("created image %p\n", image);*/
5478 /* keep in sync with image.c */
5479 image->image.name = assembly_name;
5480 image->image.assembly_name = image->image.name; /* they may be different */
5481 image->image.module_name = module_name;
5482 image->image.version = g_strdup (version);
5483 image->image.md_version_major = 1;
5484 image->image.md_version_minor = 1;
5485 image->image.dynamic = TRUE;
5487 image->image.references = g_new0 (MonoAssembly*, 1);
5488 image->image.references [0] = NULL;
5490 mono_image_init (&image->image);
5492 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");
5493 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5494 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5495 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5496 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5497 image->handleref = g_hash_table_new (NULL, NULL);
5498 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");
5499 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5500 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");
5501 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");
5502 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5503 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5504 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5505 image->gen_params = g_ptr_array_new ();
5506 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5508 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5509 string_heap_init (&image->sheap);
5510 mono_image_add_stream_data (&image->us, "", 1);
5511 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5512 /* import tables... */
5513 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5514 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5515 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5516 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5517 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5518 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5519 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5520 stream_data_align (&image->code);
5522 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5524 for (i=0; i < MONO_TABLE_NUM; ++i) {
5525 image->tables [i].next_idx = 1;
5526 image->tables [i].columns = table_sizes [i];
5529 image->image.assembly = (MonoAssembly*)assembly;
5530 image->run = assembly->run;
5531 image->save = assembly->save;
5532 image->pe_kind = 0x1; /* ILOnly */
5533 image->machine = 0x14c; /* I386 */
5535 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5537 dynamic_images_lock ();
5539 if (!dynamic_images)
5540 dynamic_images = g_ptr_array_new ();
5542 g_ptr_array_add (dynamic_images, image);
5544 dynamic_images_unlock ();
5551 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5557 release_hashtable (MonoGHashTable **hash)
5560 mono_g_hash_table_destroy (*hash);
5566 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5568 release_hashtable (&image->token_fixups);
5569 release_hashtable (&image->handleref_managed);
5570 release_hashtable (&image->tokens);
5571 release_hashtable (&image->remapped_tokens);
5572 release_hashtable (&image->generic_def_objects);
5573 release_hashtable (&image->methodspec);
5576 // Free dynamic image pass one: Free resources but not image itself
5578 mono_dynamic_image_free (MonoDynamicImage *image)
5580 MonoDynamicImage *di = image;
5585 mono_g_hash_table_destroy (di->methodspec);
5587 g_hash_table_destroy (di->typespec);
5589 g_hash_table_destroy (di->typeref);
5591 g_hash_table_destroy (di->handleref);
5592 if (di->handleref_managed)
5593 mono_g_hash_table_destroy (di->handleref_managed);
5595 mono_g_hash_table_destroy (di->tokens);
5596 if (di->remapped_tokens)
5597 mono_g_hash_table_destroy (di->remapped_tokens);
5598 if (di->generic_def_objects)
5599 mono_g_hash_table_destroy (di->generic_def_objects);
5600 if (di->blob_cache) {
5601 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5602 g_hash_table_destroy (di->blob_cache);
5604 if (di->standalonesig_cache)
5605 g_hash_table_destroy (di->standalonesig_cache);
5606 for (list = di->array_methods; list; list = list->next) {
5607 ArrayMethod *am = (ArrayMethod *)list->data;
5612 g_list_free (di->array_methods);
5613 if (di->gen_params) {
5614 for (i = 0; i < di->gen_params->len; i++) {
5615 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5616 mono_gc_deregister_root ((char*) &entry->gparam);
5619 g_ptr_array_free (di->gen_params, TRUE);
5621 if (di->token_fixups)
5622 mono_g_hash_table_destroy (di->token_fixups);
5623 if (di->method_to_table_idx)
5624 g_hash_table_destroy (di->method_to_table_idx);
5625 if (di->field_to_table_idx)
5626 g_hash_table_destroy (di->field_to_table_idx);
5627 if (di->method_aux_hash)
5628 g_hash_table_destroy (di->method_aux_hash);
5629 if (di->vararg_aux_hash)
5630 g_hash_table_destroy (di->vararg_aux_hash);
5631 g_free (di->strong_name);
5632 g_free (di->win32_res);
5634 g_free (di->public_key);
5636 /*g_print ("string heap destroy for image %p\n", di);*/
5637 mono_dynamic_stream_reset (&di->sheap);
5638 mono_dynamic_stream_reset (&di->code);
5639 mono_dynamic_stream_reset (&di->resources);
5640 mono_dynamic_stream_reset (&di->us);
5641 mono_dynamic_stream_reset (&di->blob);
5642 mono_dynamic_stream_reset (&di->tstream);
5643 mono_dynamic_stream_reset (&di->guid);
5644 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5645 g_free (di->tables [i].values);
5648 dynamic_images_lock ();
5651 g_ptr_array_remove (dynamic_images, di);
5653 dynamic_images_unlock ();
5656 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5658 mono_dynamic_image_free_image (MonoDynamicImage *image)
5660 /* See create_dynamic_mono_image () */
5662 /* Allocated using GC_MALLOC */
5668 #ifndef DISABLE_REFLECTION_EMIT
5671 * mono_image_basic_init:
5672 * @assembly: an assembly builder object
5674 * Create the MonoImage that represents the assembly builder and setup some
5675 * of the helper hash table and the basic metadata streams.
5678 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5680 MonoDynamicAssembly *assembly;
5681 MonoDynamicImage *image;
5682 MonoDomain *domain = mono_object_domain (assemblyb);
5684 if (assemblyb->dynamic_assembly)
5688 /* assembly->assembly.image might be GC allocated */
5689 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5691 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5694 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5696 assembly->assembly.ref_count = 1;
5697 assembly->assembly.dynamic = TRUE;
5698 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5699 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5700 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5701 if (assemblyb->culture)
5702 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5704 assembly->assembly.aname.culture = g_strdup ("");
5706 if (assemblyb->version) {
5707 char *vstr = mono_string_to_utf8 (assemblyb->version);
5708 char **version = g_strsplit (vstr, ".", 4);
5709 char **parts = version;
5710 assembly->assembly.aname.major = atoi (*parts++);
5711 assembly->assembly.aname.minor = atoi (*parts++);
5712 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5713 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5715 g_strfreev (version);
5718 assembly->assembly.aname.major = 0;
5719 assembly->assembly.aname.minor = 0;
5720 assembly->assembly.aname.build = 0;
5721 assembly->assembly.aname.revision = 0;
5724 assembly->run = assemblyb->access != 2;
5725 assembly->save = assemblyb->access != 1;
5726 assembly->domain = domain;
5728 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5729 image->initial_image = TRUE;
5730 assembly->assembly.aname.name = image->image.name;
5731 assembly->assembly.image = &image->image;
5732 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5733 /* -1 to correct for the trailing NULL byte */
5734 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5735 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5737 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5740 mono_domain_assemblies_lock (domain);
5741 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5742 mono_domain_assemblies_unlock (domain);
5744 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5746 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5748 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5751 #endif /* !DISABLE_REFLECTION_EMIT */
5753 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5756 calc_section_size (MonoDynamicImage *assembly)
5760 /* alignment constraints */
5761 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5762 g_assert ((assembly->code.index % 4) == 0);
5763 assembly->meta_size += 3;
5764 assembly->meta_size &= ~3;
5765 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5766 g_assert ((assembly->resources.index % 4) == 0);
5768 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5769 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5772 if (assembly->win32_res) {
5773 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5775 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5776 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5780 assembly->sections [MONO_SECTION_RELOC].size = 12;
5781 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5791 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5795 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5797 ResTreeNode *t1 = (ResTreeNode*)a;
5798 ResTreeNode *t2 = (ResTreeNode*)b;
5800 return t1->id - t2->id;
5804 * resource_tree_create:
5806 * Organize the resources into a resource tree.
5808 static ResTreeNode *
5809 resource_tree_create (MonoArray *win32_resources)
5811 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5815 tree = g_new0 (ResTreeNode, 1);
5817 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5818 MonoReflectionWin32Resource *win32_res =
5819 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5823 /* FIXME: BUG: this stores managed references in unmanaged memory */
5824 lang_node = g_new0 (ResTreeNode, 1);
5825 lang_node->id = win32_res->lang_id;
5826 lang_node->win32_res = win32_res;
5828 /* Create type node if neccesary */
5830 for (l = tree->children; l; l = l->next)
5831 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5832 type_node = (ResTreeNode*)l->data;
5837 type_node = g_new0 (ResTreeNode, 1);
5838 type_node->id = win32_res->res_type;
5841 * The resource types have to be sorted otherwise
5842 * Windows Explorer can't display the version information.
5844 tree->children = g_slist_insert_sorted (tree->children,
5845 type_node, resource_tree_compare_by_id);
5848 /* Create res node if neccesary */
5850 for (l = type_node->children; l; l = l->next)
5851 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5852 res_node = (ResTreeNode*)l->data;
5857 res_node = g_new0 (ResTreeNode, 1);
5858 res_node->id = win32_res->res_id;
5859 type_node->children = g_slist_append (type_node->children, res_node);
5862 res_node->children = g_slist_append (res_node->children, lang_node);
5869 * resource_tree_encode:
5871 * Encode the resource tree into the format used in the PE file.
5874 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5877 MonoPEResourceDir dir;
5878 MonoPEResourceDirEntry dir_entry;
5879 MonoPEResourceDataEntry data_entry;
5881 guint32 res_id_entries;
5884 * For the format of the resource directory, see the article
5885 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5889 memset (&dir, 0, sizeof (dir));
5890 memset (&dir_entry, 0, sizeof (dir_entry));
5891 memset (&data_entry, 0, sizeof (data_entry));
5893 g_assert (sizeof (dir) == 16);
5894 g_assert (sizeof (dir_entry) == 8);
5895 g_assert (sizeof (data_entry) == 16);
5897 node->offset = p - begin;
5899 /* IMAGE_RESOURCE_DIRECTORY */
5900 res_id_entries = g_slist_length (node->children);
5901 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5903 memcpy (p, &dir, sizeof (dir));
5906 /* Reserve space for entries */
5908 p += sizeof (dir_entry) * res_id_entries;
5910 /* Write children */
5911 for (l = node->children; l; l = l->next) {
5912 ResTreeNode *child = (ResTreeNode*)l->data;
5914 if (child->win32_res) {
5917 child->offset = p - begin;
5919 /* IMAGE_RESOURCE_DATA_ENTRY */
5920 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5921 size = mono_array_length (child->win32_res->res_data);
5922 data_entry.rde_size = GUINT32_TO_LE (size);
5924 memcpy (p, &data_entry, sizeof (data_entry));
5925 p += sizeof (data_entry);
5927 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5930 resource_tree_encode (child, begin, p, &p);
5934 /* IMAGE_RESOURCE_ENTRY */
5935 for (l = node->children; l; l = l->next) {
5936 ResTreeNode *child = (ResTreeNode*)l->data;
5938 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5939 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5941 memcpy (entries, &dir_entry, sizeof (dir_entry));
5942 entries += sizeof (dir_entry);
5949 resource_tree_free (ResTreeNode * node)
5952 for (list = node->children; list; list = list->next)
5953 resource_tree_free ((ResTreeNode*)list->data);
5954 g_slist_free(node->children);
5959 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5964 MonoReflectionWin32Resource *win32_res;
5967 if (!assemblyb->win32_resources)
5971 * Resources are stored in a three level tree inside the PE file.
5972 * - level one contains a node for each type of resource
5973 * - level two contains a node for each resource
5974 * - level three contains a node for each instance of a resource for a
5975 * specific language.
5978 tree = resource_tree_create (assemblyb->win32_resources);
5980 /* Estimate the size of the encoded tree */
5982 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5983 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5984 size += mono_array_length (win32_res->res_data);
5986 /* Directory structure */
5987 size += mono_array_length (assemblyb->win32_resources) * 256;
5988 p = buf = (char *)g_malloc (size);
5990 resource_tree_encode (tree, p, p, &p);
5992 g_assert (p - buf <= size);
5994 assembly->win32_res = (char *)g_malloc (p - buf);
5995 assembly->win32_res_size = p - buf;
5996 memcpy (assembly->win32_res, buf, p - buf);
5999 resource_tree_free (tree);
6003 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6005 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6008 p += sizeof (MonoPEResourceDir);
6009 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6010 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6011 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6012 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6013 fixup_resource_directory (res_section, child, rva);
6015 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6016 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6019 p += sizeof (MonoPEResourceDirEntry);
6024 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6027 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6028 g_error ("WriteFile returned %d\n", GetLastError ());
6032 * mono_image_create_pefile:
6033 * @mb: a module builder object
6035 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6036 * assembly->pefile where it can be easily retrieved later in chunks.
6039 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6041 MonoMSDOSHeader *msdos;
6042 MonoDotNetHeader *header;
6043 MonoSectionTable *section;
6044 MonoCLIHeader *cli_header;
6045 guint32 size, image_size, virtual_base, text_offset;
6046 guint32 header_start, section_start, file_offset, virtual_offset;
6047 MonoDynamicImage *assembly;
6048 MonoReflectionAssemblyBuilder *assemblyb;
6049 MonoDynamicStream pefile_stream = {0};
6050 MonoDynamicStream *pefile = &pefile_stream;
6052 guint32 *rva, value;
6054 static const unsigned char msheader[] = {
6055 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6056 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6059 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6060 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6061 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6062 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6065 mono_error_init (error);
6067 assemblyb = mb->assemblyb;
6069 mono_image_basic_init (assemblyb);
6070 assembly = mb->dynamic_image;
6072 assembly->pe_kind = assemblyb->pe_kind;
6073 assembly->machine = assemblyb->machine;
6074 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6075 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6077 if (!mono_image_build_metadata (mb, error))
6081 if (mb->is_main && assemblyb->resources) {
6082 int len = mono_array_length (assemblyb->resources);
6083 for (i = 0; i < len; ++i)
6084 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6087 if (mb->resources) {
6088 int len = mono_array_length (mb->resources);
6089 for (i = 0; i < len; ++i)
6090 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6093 if (!build_compressed_metadata (assembly, error))
6097 assembly_add_win32_resources (assembly, assemblyb);
6099 nsections = calc_section_size (assembly);
6101 /* The DOS header and stub */
6102 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6103 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6105 /* the dotnet header */
6106 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6108 /* the section tables */
6109 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6111 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6112 virtual_offset = VIRT_ALIGN;
6115 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6116 if (!assembly->sections [i].size)
6119 file_offset += FILE_ALIGN - 1;
6120 file_offset &= ~(FILE_ALIGN - 1);
6121 virtual_offset += VIRT_ALIGN - 1;
6122 virtual_offset &= ~(VIRT_ALIGN - 1);
6124 assembly->sections [i].offset = file_offset;
6125 assembly->sections [i].rva = virtual_offset;
6127 file_offset += assembly->sections [i].size;
6128 virtual_offset += assembly->sections [i].size;
6129 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6132 file_offset += FILE_ALIGN - 1;
6133 file_offset &= ~(FILE_ALIGN - 1);
6135 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6137 /* back-patch info */
6138 msdos = (MonoMSDOSHeader*)pefile->data;
6139 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6141 header = (MonoDotNetHeader*)(pefile->data + header_start);
6142 header->pesig [0] = 'P';
6143 header->pesig [1] = 'E';
6145 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6146 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6147 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6148 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6149 if (assemblyb->pekind == 1) {
6151 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6154 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6157 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6159 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6160 header->pe.pe_major = 6;
6161 header->pe.pe_minor = 0;
6162 size = assembly->sections [MONO_SECTION_TEXT].size;
6163 size += FILE_ALIGN - 1;
6164 size &= ~(FILE_ALIGN - 1);
6165 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6166 size = assembly->sections [MONO_SECTION_RSRC].size;
6167 size += FILE_ALIGN - 1;
6168 size &= ~(FILE_ALIGN - 1);
6169 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6170 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6171 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6172 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6173 /* pe_rva_entry_point always at the beginning of the text section */
6174 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6176 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6177 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6178 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6179 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6180 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6181 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6182 size = section_start;
6183 size += FILE_ALIGN - 1;
6184 size &= ~(FILE_ALIGN - 1);
6185 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6187 size += VIRT_ALIGN - 1;
6188 size &= ~(VIRT_ALIGN - 1);
6189 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6192 // Translate the PEFileKind value to the value expected by the Windows loader
6198 // PEFileKinds.Dll == 1
6199 // PEFileKinds.ConsoleApplication == 2
6200 // PEFileKinds.WindowApplication == 3
6203 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6204 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6206 if (assemblyb->pekind == 3)
6211 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6213 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6214 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6215 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6216 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6217 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6218 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6220 /* fill data directory entries */
6222 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6223 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6225 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6226 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6228 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6229 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6230 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6231 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6232 /* patch entrypoint name */
6233 if (assemblyb->pekind == 1)
6234 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6236 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6237 /* patch imported function RVA name */
6238 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6239 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6241 /* the import table */
6242 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6243 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6244 /* patch imported dll RVA name and other entries in the dir */
6245 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6246 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6247 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6248 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6249 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6250 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6252 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6253 value = (assembly->text_rva + assembly->imp_names_offset);
6254 *p++ = (value) & 0xff;
6255 *p++ = (value >> 8) & (0xff);
6256 *p++ = (value >> 16) & (0xff);
6257 *p++ = (value >> 24) & (0xff);
6259 /* the CLI header info */
6260 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6261 cli_header->ch_size = GUINT32_FROM_LE (72);
6262 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6263 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6264 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6265 if (assemblyb->entry_point) {
6266 guint32 table_idx = 0;
6267 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6268 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6269 table_idx = methodb->table_idx;
6271 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6273 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6275 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6277 /* The embedded managed resources */
6278 text_offset = assembly->text_rva + assembly->code.index;
6279 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6280 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6281 text_offset += assembly->resources.index;
6282 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6283 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6284 text_offset += assembly->meta_size;
6285 if (assembly->strong_name_size) {
6286 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6287 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6288 text_offset += assembly->strong_name_size;
6291 /* write the section tables and section content */
6292 section = (MonoSectionTable*)(pefile->data + section_start);
6293 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6294 static const char section_names [][7] = {
6295 ".text", ".rsrc", ".reloc"
6297 if (!assembly->sections [i].size)
6299 strcpy (section->st_name, section_names [i]);
6300 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6301 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6302 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6303 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6304 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6305 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6306 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6310 checked_write_file (file, pefile->data, pefile->index);
6312 mono_dynamic_stream_reset (pefile);
6314 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6315 if (!assembly->sections [i].size)
6318 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6319 g_error ("SetFilePointer returned %d\n", GetLastError ());
6322 case MONO_SECTION_TEXT:
6323 /* patch entry point */
6324 p = (guchar*)(assembly->code.data + 2);
6325 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6326 *p++ = (value) & 0xff;
6327 *p++ = (value >> 8) & 0xff;
6328 *p++ = (value >> 16) & 0xff;
6329 *p++ = (value >> 24) & 0xff;
6331 checked_write_file (file, assembly->code.data, assembly->code.index);
6332 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6333 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6334 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6337 g_free (assembly->image.raw_metadata);
6339 case MONO_SECTION_RELOC: {
6343 guint16 type_and_offset;
6347 g_assert (sizeof (reloc) == 12);
6349 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6350 reloc.block_size = GUINT32_FROM_LE (12);
6353 * the entrypoint is always at the start of the text section
6354 * 3 is IMAGE_REL_BASED_HIGHLOW
6355 * 2 is patch_size_rva - text_rva
6357 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6360 checked_write_file (file, &reloc, sizeof (reloc));
6364 case MONO_SECTION_RSRC:
6365 if (assembly->win32_res) {
6367 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6368 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6369 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6373 g_assert_not_reached ();
6377 /* check that the file is properly padded */
6378 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6379 g_error ("SetFilePointer returned %d\n", GetLastError ());
6380 if (! SetEndOfFile (file))
6381 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6383 mono_dynamic_stream_reset (&assembly->code);
6384 mono_dynamic_stream_reset (&assembly->us);
6385 mono_dynamic_stream_reset (&assembly->blob);
6386 mono_dynamic_stream_reset (&assembly->guid);
6387 mono_dynamic_stream_reset (&assembly->sheap);
6389 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6390 g_hash_table_destroy (assembly->blob_cache);
6391 assembly->blob_cache = NULL;
6396 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6399 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6401 g_assert_not_reached ();
6404 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6406 #ifndef DISABLE_REFLECTION_EMIT
6408 MonoReflectionModule *
6409 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6412 MonoReflectionModule *result = NULL;
6415 MonoImageOpenStatus status;
6416 MonoDynamicAssembly *assembly;
6417 guint32 module_count;
6418 MonoImage **new_modules;
6419 gboolean *new_modules_loaded;
6421 name = mono_string_to_utf8 (fileName);
6423 image = mono_image_open (name, &status);
6426 if (status == MONO_IMAGE_ERROR_ERRNO)
6427 exc = mono_get_exception_file_not_found (fileName);
6429 exc = mono_get_exception_bad_image_format (name);
6431 mono_raise_exception (exc);
6436 assembly = ab->dynamic_assembly;
6437 image->assembly = (MonoAssembly*)assembly;
6439 module_count = image->assembly->image->module_count;
6440 new_modules = g_new0 (MonoImage *, module_count + 1);
6441 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6443 if (image->assembly->image->modules)
6444 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6445 if (image->assembly->image->modules_loaded)
6446 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6447 new_modules [module_count] = image;
6448 new_modules_loaded [module_count] = TRUE;
6449 mono_image_addref (image);
6451 g_free (image->assembly->image->modules);
6452 image->assembly->image->modules = new_modules;
6453 image->assembly->image->modules_loaded = new_modules_loaded;
6454 image->assembly->image->module_count ++;
6456 mono_assembly_load_references (image, &status);
6458 mono_image_close (image);
6459 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6462 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6463 mono_error_raise_exception (&error); /* FIXME don't raise here */
6467 #endif /* DISABLE_REFLECTION_EMIT */
6470 * We need to return always the same object for MethodInfo, FieldInfo etc..
6471 * but we need to consider the reflected type.
6472 * type uses a different hash, since it uses custom hash/equal functions.
6477 MonoClass *refclass;
6481 reflected_equal (gconstpointer a, gconstpointer b) {
6482 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6483 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6485 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6489 reflected_hash (gconstpointer a) {
6490 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6491 return mono_aligned_addr_hash (ea->item);
6494 #define CHECK_OBJECT(t,p,k) \
6500 mono_domain_lock (domain); \
6501 if (!domain->refobject_hash) \
6502 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"); \
6503 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6504 mono_domain_unlock (domain); \
6507 mono_domain_unlock (domain); \
6510 #ifdef HAVE_BOEHM_GC
6511 /* ReflectedEntry doesn't need to be GC tracked */
6512 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6513 #define FREE_REFENTRY(entry) g_free ((entry))
6514 #define REFENTRY_REQUIRES_CLEANUP
6516 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6518 #define FREE_REFENTRY(entry)
6521 #define CACHE_OBJECT(t,p,o,k) \
6524 ReflectedEntry pe; \
6526 pe.refclass = (k); \
6527 mono_domain_lock (domain); \
6528 if (!domain->refobject_hash) \
6529 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"); \
6530 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6532 ReflectedEntry *e = ALLOC_REFENTRY; \
6534 e->refclass = (k); \
6535 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6538 mono_domain_unlock (domain); \
6543 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6545 mono_domain_lock (domain);
6546 if (domain->refobject_hash) {
6548 gpointer orig_pe, orig_value;
6551 pe.refclass = klass;
6552 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6553 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6554 FREE_REFENTRY (orig_pe);
6557 mono_domain_unlock (domain);
6560 #ifdef REFENTRY_REQUIRES_CLEANUP
6562 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6564 FREE_REFENTRY (key);
6569 mono_reflection_cleanup_domain (MonoDomain *domain)
6571 if (domain->refobject_hash) {
6572 /*let's avoid scanning the whole hashtable if not needed*/
6573 #ifdef REFENTRY_REQUIRES_CLEANUP
6574 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6576 mono_g_hash_table_destroy (domain->refobject_hash);
6577 domain->refobject_hash = NULL;
6581 #ifndef DISABLE_REFLECTION_EMIT
6583 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6585 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6589 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6591 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6595 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6597 MonoDynamicImage *image = moduleb->dynamic_image;
6598 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6602 MonoImage **new_modules;
6604 char *name, *fqname;
6606 * FIXME: we already created an image in mono_image_basic_init (), but
6607 * we don't know which module it belongs to, since that is only
6608 * determined at assembly save time.
6610 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6611 name = mono_string_to_utf8 (ab->name);
6612 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6613 if (!mono_error_ok (&error)) {
6615 mono_error_raise_exception (&error);
6617 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6619 moduleb->module.image = &image->image;
6620 moduleb->dynamic_image = image;
6621 register_module (mono_object_domain (moduleb), moduleb, image);
6623 /* register the module with the assembly */
6624 ass = ab->dynamic_assembly->assembly.image;
6625 module_count = ass->module_count;
6626 new_modules = g_new0 (MonoImage *, module_count + 1);
6629 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6630 new_modules [module_count] = &image->image;
6631 mono_image_addref (&image->image);
6633 g_free (ass->modules);
6634 ass->modules = new_modules;
6635 ass->module_count ++;
6640 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6642 MonoDynamicImage *image = moduleb->dynamic_image;
6644 g_assert (type->type);
6645 image->wrappers_type = mono_class_from_mono_type (type->type);
6651 * mono_assembly_get_object:
6652 * @domain: an app domain
6653 * @assembly: an assembly
6655 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6657 MonoReflectionAssembly*
6658 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6661 MonoReflectionAssembly *result;
6662 result = mono_assembly_get_object_checked (domain, assembly, &error);
6664 mono_error_set_pending_exception (&error);
6668 * mono_assembly_get_object:
6669 * @domain: an app domain
6670 * @assembly: an assembly
6672 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6674 MonoReflectionAssembly*
6675 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6677 static MonoClass *assembly_type;
6678 MonoReflectionAssembly *res;
6680 mono_error_init (error);
6682 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6683 if (!assembly_type) {
6684 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6686 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6688 assembly_type = klass;
6690 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, error);
6693 res->assembly = assembly;
6695 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6700 MonoReflectionModule*
6701 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6704 MonoReflectionModule *result;
6705 result = mono_module_get_object_checked (domain, image, &error);
6706 mono_error_raise_exception (&error);
6710 MonoReflectionModule*
6711 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6713 static MonoClass *module_type;
6714 MonoReflectionModule *res;
6717 mono_error_init (error);
6718 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6720 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6722 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6724 module_type = klass;
6726 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, error);
6731 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6734 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6736 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6737 basename = g_path_get_basename (image->name);
6738 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6739 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6743 if (image->assembly->image == image) {
6744 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6748 if (image->assembly->image->modules) {
6749 for (i = 0; i < image->assembly->image->module_count; i++) {
6750 if (image->assembly->image->modules [i] == image)
6751 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6753 g_assert (res->token);
6757 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6760 MonoReflectionModule*
6761 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6764 MonoReflectionModule *result;
6765 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6766 mono_error_raise_exception (&error);
6770 MonoReflectionModule*
6771 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6773 static MonoClass *module_type;
6774 MonoReflectionModule *res;
6775 MonoTableInfo *table;
6776 guint32 cols [MONO_FILE_SIZE];
6778 guint32 i, name_idx;
6781 mono_error_init (error);
6784 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6786 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6788 module_type = klass;
6790 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, error);
6794 table = &image->tables [MONO_TABLE_FILE];
6795 g_assert (table_index < table->rows);
6796 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6799 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6802 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6805 /* Check whenever the row has a corresponding row in the moduleref table */
6806 table = &image->tables [MONO_TABLE_MODULEREF];
6807 for (i = 0; i < table->rows; ++i) {
6808 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809 val = mono_metadata_string_heap (image, name_idx);
6810 if (strcmp (val, name) == 0)
6811 res->image = image->modules [i];
6814 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6824 verify_safe_for_managed_space (MonoType *type)
6826 switch (type->type) {
6828 case MONO_TYPE_ARRAY:
6829 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6831 return verify_safe_for_managed_space (type->data.type);
6832 case MONO_TYPE_SZARRAY:
6833 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834 case MONO_TYPE_GENERICINST: {
6835 MonoGenericInst *inst = type->data.generic_class->inst;
6839 for (i = 0; i < inst->type_argc; ++i)
6840 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6846 case MONO_TYPE_MVAR:
6854 mono_type_normalize (MonoType *type)
6857 MonoGenericClass *gclass;
6858 MonoGenericInst *ginst;
6860 MonoGenericContainer *gcontainer;
6861 MonoType **argv = NULL;
6862 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6864 if (type->type != MONO_TYPE_GENERICINST)
6867 gclass = type->data.generic_class;
6868 ginst = gclass->context.class_inst;
6869 if (!ginst->is_open)
6872 gtd = gclass->container_class;
6873 gcontainer = gtd->generic_container;
6874 argv = g_newa (MonoType*, ginst->type_argc);
6876 for (i = 0; i < ginst->type_argc; ++i) {
6877 MonoType *t = ginst->type_argv [i], *norm;
6878 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879 is_denorm_gtd = FALSE;
6880 norm = mono_type_normalize (t);
6883 requires_rebind = TRUE;
6887 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6889 if (requires_rebind) {
6890 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6897 * mono_type_get_object:
6898 * @domain: an app domain
6901 * Return an System.MonoType object representing the type @type.
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6907 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908 mono_error_raise_exception (&error);
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6916 MonoType *norm_type;
6917 MonoReflectionType *res;
6920 mono_error_init (error);
6922 klass = mono_class_from_mono_type (type);
6924 /*we must avoid using @type as it might have come
6925 * from a mono_metadata_type_dup and the caller
6926 * expects that is can be freed.
6927 * Using the right type from
6929 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6931 /* void is very common */
6932 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933 return (MonoReflectionType*)domain->typeof_void;
6936 * If the vtable of the given class was already created, we can use
6937 * the MonoType from there and avoid all locking and hash table lookups.
6939 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940 * that the resulting object is different.
6942 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944 if (vtable && vtable->type)
6945 return (MonoReflectionType *)vtable->type;
6948 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949 mono_domain_lock (domain);
6950 if (!domain->type_hash)
6951 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6952 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954 mono_domain_unlock (domain);
6955 mono_loader_unlock ();
6959 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963 * artifact of how generics are encoded and should be transparent to managed code so we
6964 * need to weed out this diference when retrieving managed System.Type objects.
6966 norm_type = mono_type_normalize (type);
6967 if (norm_type != type) {
6968 res = mono_type_get_object_checked (domain, norm_type, error);
6969 if (!mono_error_ok (error))
6971 mono_g_hash_table_insert (domain->type_hash, type, res);
6972 mono_domain_unlock (domain);
6973 mono_loader_unlock ();
6977 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6981 if (!verify_safe_for_managed_space (type)) {
6982 mono_domain_unlock (domain);
6983 mono_loader_unlock ();
6984 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6988 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989 gboolean is_type_done = TRUE;
6990 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6994 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6997 if (gparam->owner && gparam->owner->is_method) {
6998 MonoMethod *method = gparam->owner->owner.method;
6999 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000 is_type_done = FALSE;
7001 } else if (gparam->owner && !gparam->owner->is_method) {
7002 MonoClass *klass = gparam->owner->owner.klass;
7003 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004 is_type_done = FALSE;
7008 /* g_assert_not_reached (); */
7009 /* should this be considered an error condition? */
7010 if (is_type_done && !type->byref) {
7011 mono_domain_unlock (domain);
7012 mono_loader_unlock ();
7013 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7016 /* This is stored in vtables/JITted code so it has to be pinned */
7017 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018 if (!mono_error_ok (error))
7022 mono_g_hash_table_insert (domain->type_hash, type, res);
7024 if (type->type == MONO_TYPE_VOID)
7025 domain->typeof_void = (MonoObject*)res;
7027 mono_domain_unlock (domain);
7028 mono_loader_unlock ();
7033 * mono_method_get_object:
7034 * @domain: an app domain
7036 * @refclass: the reflected type (can be NULL)
7038 * Return an System.Reflection.MonoMethod object representing the method @method.
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7044 MonoReflectionMethod *ret = NULL;
7045 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046 mono_error_raise_exception (&error);
7051 * mono_method_get_object_checked:
7052 * @domain: an app domain
7054 * @refclass: the reflected type (can be NULL)
7055 * @error: set on error.
7057 * Return an System.Reflection.MonoMethod object representing the method @method.
7058 * Returns NULL and sets @error on error.
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7064 * We use the same C representation for methods and constructors, but the type
7065 * name in C# is different.
7067 static MonoClass *System_Reflection_MonoMethod = NULL;
7068 static MonoClass *System_Reflection_MonoCMethod = NULL;
7069 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
7070 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
7071 MonoReflectionType *rt;
7073 MonoReflectionMethod *ret;
7075 mono_error_init (error);
7077 if (method->is_inflated) {
7078 MonoReflectionGenericMethod *gret;
7081 refclass = method->klass;
7082 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7083 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7084 if (!System_Reflection_MonoGenericCMethod) {
7085 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
7086 if (!mono_error_ok (error))
7089 klass = System_Reflection_MonoGenericCMethod;
7091 if (!System_Reflection_MonoGenericMethod) {
7092 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
7093 if (!mono_error_ok (error))
7096 klass = System_Reflection_MonoGenericMethod;
7098 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7099 if (!mono_error_ok (error))
7101 gret->method.method = method;
7103 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7105 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7106 if (!mono_error_ok (error))
7109 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7111 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7115 refclass = method->klass;
7117 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7118 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7119 if (!System_Reflection_MonoCMethod) {
7120 System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7121 if (!mono_error_ok (error))
7124 klass = System_Reflection_MonoCMethod;
7127 if (!System_Reflection_MonoMethod) {
7128 System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7129 if (!mono_error_ok (error))
7132 klass = System_Reflection_MonoMethod;
7134 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7135 if (!mono_error_ok (error))
7137 ret->method = method;
7139 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7140 if (!mono_error_ok (error))
7143 MONO_OBJECT_SETREF (ret, reftype, rt);
7145 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7148 g_assert (!mono_error_ok (error));
7153 * mono_method_clear_object:
7155 * Clear the cached reflection objects for the dynamic method METHOD.
7158 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7161 g_assert (method_is_dynamic (method));
7163 klass = method->klass;
7165 clear_cached_object (domain, method, klass);
7166 klass = klass->parent;
7168 /* Added by mono_param_get_objects () */
7169 clear_cached_object (domain, &(method->signature), NULL);
7170 klass = method->klass;
7172 clear_cached_object (domain, &(method->signature), klass);
7173 klass = klass->parent;
7178 * mono_field_get_object:
7179 * @domain: an app domain
7183 * Return an System.Reflection.MonoField object representing the field @field
7186 MonoReflectionField*
7187 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7190 MonoReflectionField *result;
7191 result = mono_field_get_object_checked (domain, klass, field, &error);
7192 mono_error_raise_exception (&error);
7197 * mono_field_get_object_checked:
7198 * @domain: an app domain
7201 * @error: set on error
7203 * Return an System.Reflection.MonoField object representing the field @field
7204 * in class @klass. On error, returns NULL and sets @error.
7206 MonoReflectionField*
7207 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7209 MonoReflectionType *rt;
7210 MonoReflectionField *res;
7211 static MonoClass *monofield_klass;
7213 mono_error_init (error);
7215 CHECK_OBJECT (MonoReflectionField *, field, klass);
7216 if (!monofield_klass)
7217 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7218 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7219 mono_error_raise_exception (error); /* FIXME don't raise here */
7222 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7224 if (is_field_on_inst (field)) {
7225 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7227 rt = mono_type_get_object_checked (domain, field->type, error);
7228 if (!mono_error_ok (error))
7231 MONO_OBJECT_SETREF (res, type, rt);
7234 rt = mono_type_get_object_checked (domain, field->type, error);
7235 if (!mono_error_ok (error))
7238 MONO_OBJECT_SETREF (res, type, rt);
7240 res->attrs = mono_field_get_flags (field);
7242 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7246 * mono_property_get_object:
7247 * @domain: an app domain
7249 * @property: a property
7251 * Return an System.Reflection.MonoProperty object representing the property @property
7254 MonoReflectionProperty*
7255 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7258 MonoReflectionProperty *res;
7259 static MonoClass *monoproperty_klass;
7261 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7262 if (!monoproperty_klass)
7263 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7264 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7265 mono_error_raise_exception (&error); /* FIXME don't raise here */
7267 res->property = property;
7268 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7272 * mono_event_get_object:
7273 * @domain: an app domain
7277 * Return an System.Reflection.MonoEvent object representing the event @event
7280 MonoReflectionEvent*
7281 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7284 MonoReflectionEvent *res;
7285 MonoReflectionMonoEvent *mono_event;
7286 static MonoClass *monoevent_klass;
7288 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7289 if (!monoevent_klass)
7290 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7291 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7292 mono_error_raise_exception (&error); /* FIXME don't raise here */
7293 mono_event->klass = klass;
7294 mono_event->event = event;
7295 res = (MonoReflectionEvent*)mono_event;
7296 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7300 * mono_get_reflection_missing_object:
7301 * @domain: Domain where the object lives
7303 * Returns the System.Reflection.Missing.Value singleton object
7304 * (of type System.Reflection.Missing).
7306 * Used as the value for ParameterInfo.DefaultValue when Optional
7310 mono_get_reflection_missing_object (MonoDomain *domain)
7313 static MonoClassField *missing_value_field = NULL;
7315 if (!missing_value_field) {
7316 MonoClass *missing_klass;
7317 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7318 mono_class_init (missing_klass);
7319 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7320 g_assert (missing_value_field);
7322 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7328 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7331 *dbnull = mono_get_dbnull_object (domain);
7336 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7338 if (!*reflection_missing)
7339 *reflection_missing = mono_get_reflection_missing_object (domain);
7340 return *reflection_missing;
7344 * mono_param_get_objects:
7345 * @domain: an app domain
7348 * Return an System.Reflection.ParameterInfo array object representing the parameters
7349 * in the method @method.
7352 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7354 static MonoClass *System_Reflection_ParameterInfo;
7355 static MonoClass *System_Reflection_ParameterInfo_array;
7357 MonoArray *res = NULL;
7358 MonoReflectionMethod *member = NULL;
7359 MonoReflectionParameter *param = NULL;
7360 char **names, **blobs = NULL;
7361 guint32 *types = NULL;
7362 MonoType *type = NULL;
7363 MonoObject *dbnull = NULL;
7364 MonoObject *missing = NULL;
7365 MonoMarshalSpec **mspecs;
7366 MonoMethodSignature *sig;
7367 MonoVTable *pinfo_vtable;
7368 MonoReflectionType *rt;
7371 if (!System_Reflection_ParameterInfo_array) {
7374 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7376 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7378 mono_memory_barrier ();
7379 System_Reflection_ParameterInfo = klass;
7382 klass = mono_array_class_get (klass, 1);
7383 mono_memory_barrier ();
7384 System_Reflection_ParameterInfo_array = klass;
7387 sig = mono_method_signature_checked (method, &error);
7388 if (!mono_error_ok (&error))
7389 mono_error_raise_exception (&error);
7391 if (!sig->param_count) {
7392 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7393 mono_error_raise_exception (&error); /* FIXME don't raise here */
7398 /* Note: the cache is based on the address of the signature into the method
7399 * since we already cache MethodInfos with the method as keys.
7401 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7403 member = mono_method_get_object_checked (domain, method, refclass, &error);
7404 mono_error_raise_exception (&error); /* FIXME don't raise here */
7405 names = g_new (char *, sig->param_count);
7406 mono_method_get_param_names (method, (const char **) names);
7408 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7409 mono_method_get_marshal_info (method, mspecs);
7411 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7412 mono_error_raise_exception (&error); /* FIXME don't raise here */
7414 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7415 for (i = 0; i < sig->param_count; ++i) {
7416 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7417 mono_error_raise_exception (&error); /* FIXME don't raise here */
7419 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7420 mono_error_raise_exception (&error); /* FIXME don't raise here */
7422 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7424 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7426 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7428 param->PositionImpl = i;
7429 param->AttrsImpl = sig->params [i]->attrs;
7431 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7432 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7433 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7435 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7439 blobs = g_new0 (char *, sig->param_count);
7440 types = g_new0 (guint32, sig->param_count);
7441 get_default_param_value_blobs (method, blobs, types);
7444 /* Build MonoType for the type from the Constant Table */
7446 type = g_new0 (MonoType, 1);
7447 type->type = (MonoTypeEnum)types [i];
7448 type->data.klass = NULL;
7449 if (types [i] == MONO_TYPE_CLASS)
7450 type->data.klass = mono_defaults.object_class;
7451 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7452 /* For enums, types [i] contains the base type */
7454 type->type = MONO_TYPE_VALUETYPE;
7455 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7457 type->data.klass = mono_class_from_mono_type (type);
7459 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7461 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7462 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7463 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7464 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7466 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7472 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7474 mono_array_setref (res, i, param);
7481 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7483 mono_metadata_free_marshal_spec (mspecs [i]);
7486 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7490 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7492 return mono_param_get_objects_internal (domain, method, NULL);
7496 * mono_method_body_get_object:
7497 * @domain: an app domain
7500 * Return an System.Reflection.MethodBody object representing the method @method.
7502 MonoReflectionMethodBody*
7503 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7505 static MonoClass *System_Reflection_MethodBody = NULL;
7506 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7507 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7509 MonoReflectionMethodBody *ret;
7510 MonoMethodHeader *header;
7512 MonoReflectionType *rt;
7513 guint32 method_rva, local_var_sig_token;
7515 unsigned char format, flags;
7518 /* for compatibility with .net */
7519 if (method_is_dynamic (method))
7520 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7522 if (!System_Reflection_MethodBody)
7523 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7524 if (!System_Reflection_LocalVariableInfo)
7525 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7526 if (!System_Reflection_ExceptionHandlingClause)
7527 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7529 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7531 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7532 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7533 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7534 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7535 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7538 image = method->klass->image;
7539 header = mono_method_get_header (method);
7541 if (!image_is_dynamic (image)) {
7542 /* Obtain local vars signature token */
7543 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7544 ptr = mono_image_rva_map (image, method_rva);
7545 flags = *(const unsigned char *) ptr;
7546 format = flags & METHOD_HEADER_FORMAT_MASK;
7548 case METHOD_HEADER_TINY_FORMAT:
7549 local_var_sig_token = 0;
7551 case METHOD_HEADER_FAT_FORMAT:
7555 local_var_sig_token = read32 (ptr);
7558 g_assert_not_reached ();
7561 local_var_sig_token = 0; //FIXME
7563 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7564 mono_error_raise_exception (&error); /* FIXME don't raise here */
7566 ret->init_locals = header->init_locals;
7567 ret->max_stack = header->max_stack;
7568 ret->local_var_sig_token = local_var_sig_token;
7569 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7570 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7573 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7574 for (i = 0; i < header->num_locals; ++i) {
7575 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7576 mono_error_raise_exception (&error); /* FIXME don't raise here */
7578 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7579 mono_error_raise_exception (&error); /* FIXME don't raise here */
7581 MONO_OBJECT_SETREF (info, local_type, rt);
7583 info->is_pinned = header->locals [i]->pinned;
7584 info->local_index = i;
7585 mono_array_setref (ret->locals, i, info);
7589 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7590 for (i = 0; i < header->num_clauses; ++i) {
7591 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7592 mono_error_raise_exception (&error); /* FIXME don't raise here */
7593 MonoExceptionClause *clause = &header->clauses [i];
7595 info->flags = clause->flags;
7596 info->try_offset = clause->try_offset;
7597 info->try_length = clause->try_len;
7598 info->handler_offset = clause->handler_offset;
7599 info->handler_length = clause->handler_len;
7600 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7601 info->filter_offset = clause->data.filter_offset;
7602 else if (clause->data.catch_class) {
7603 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7604 mono_error_raise_exception (&error); /* FIXME don't raise here */
7606 MONO_OBJECT_SETREF (info, catch_type, rt);
7609 mono_array_setref (ret->clauses, i, info);
7612 mono_metadata_free_mh (header);
7613 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7618 * mono_get_dbnull_object:
7619 * @domain: Domain where the object lives
7621 * Returns the System.DBNull.Value singleton object
7623 * Used as the value for ParameterInfo.DefaultValue
7626 mono_get_dbnull_object (MonoDomain *domain)
7629 static MonoClassField *dbnull_value_field = NULL;
7631 if (!dbnull_value_field) {
7632 MonoClass *dbnull_klass;
7633 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7634 mono_class_init (dbnull_klass);
7635 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7636 g_assert (dbnull_value_field);
7638 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7644 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7646 guint32 param_index, i, lastp, crow = 0;
7647 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7650 MonoClass *klass = method->klass;
7651 MonoImage *image = klass->image;
7652 MonoMethodSignature *methodsig = mono_method_signature (method);
7654 MonoTableInfo *constt;
7655 MonoTableInfo *methodt;
7656 MonoTableInfo *paramt;
7658 if (!methodsig->param_count)
7661 mono_class_init (klass);
7663 if (image_is_dynamic (klass->image)) {
7664 MonoReflectionMethodAux *aux;
7665 if (method->is_inflated)
7666 method = ((MonoMethodInflated*)method)->declaring;
7667 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7668 if (aux && aux->param_defaults) {
7669 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7670 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7675 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7676 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7677 constt = &image->tables [MONO_TABLE_CONSTANT];
7679 idx = mono_method_get_index (method) - 1;
7680 g_assert (idx != -1);
7682 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7683 if (idx + 1 < methodt->rows)
7684 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7686 lastp = paramt->rows + 1;
7688 for (i = param_index; i < lastp; ++i) {
7691 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7692 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7694 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7697 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7702 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7703 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7704 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7711 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7717 MonoType *basetype = type;
7722 klass = mono_class_from_mono_type (type);
7723 if (klass->valuetype) {
7724 object = mono_object_new_checked (domain, klass, &error);
7725 mono_error_raise_exception (&error); /* FIXME don't raise here */
7726 retval = ((gchar *) object + sizeof (MonoObject));
7727 if (klass->enumtype)
7728 basetype = mono_class_enum_basetype (klass);
7733 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7740 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7743 gboolean quoted = FALSE;
7745 memset (assembly, 0, sizeof (MonoAssemblyName));
7746 assembly->culture = "";
7747 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7754 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7765 /* Remove trailing whitespace */
7767 while (*s && g_ascii_isspace (*s))
7770 while (g_ascii_isspace (*p))
7773 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7775 assembly->major = strtoul (p, &s, 10);
7776 if (s == p || *s != '.')
7779 assembly->minor = strtoul (p, &s, 10);
7780 if (s == p || *s != '.')
7783 assembly->build = strtoul (p, &s, 10);
7784 if (s == p || *s != '.')
7787 assembly->revision = strtoul (p, &s, 10);
7791 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7793 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7794 assembly->culture = "";
7797 assembly->culture = p;
7798 while (*p && *p != ',') {
7802 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7804 if (strncmp (p, "null", 4) == 0) {
7809 while (*p && *p != ',') {
7812 len = (p - start + 1);
7813 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7814 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7815 g_strlcpy ((char*)assembly->public_key_token, start, len);
7818 while (*p && *p != ',')
7822 while (g_ascii_isspace (*p) || *p == ',') {
7836 * mono_reflection_parse_type:
7839 * Parse a type name as accepted by the GetType () method and output the info
7840 * extracted in the info structure.
7841 * the name param will be mangled, so, make a copy before passing it to this function.
7842 * The fields in info will be valid until the memory pointed to by name is valid.
7844 * See also mono_type_get_name () below.
7846 * Returns: 0 on parse error.
7849 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7850 MonoTypeNameParse *info)
7852 char *start, *p, *w, *last_point, *startn;
7853 int in_modifiers = 0;
7854 int isbyref = 0, rank = 0, isptr = 0;
7856 start = p = w = name;
7858 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7859 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7860 info->name = info->name_space = NULL;
7861 info->nested = NULL;
7862 info->modifiers = NULL;
7863 info->type_arguments = NULL;
7865 /* last_point separates the namespace from the name */
7868 while (*p == ' ') p++, start++, w++, name++;
7873 *p = 0; /* NULL terminate the name */
7875 info->nested = g_list_append (info->nested, startn);
7876 /* we have parsed the nesting namespace + name */
7880 info->name_space = start;
7882 info->name = last_point + 1;
7884 info->name_space = (char *)"";
7912 info->name_space = start;
7914 info->name = last_point + 1;
7916 info->name_space = (char *)"";
7923 if (isbyref) /* only one level allowed by the spec */
7927 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7931 if (isbyref) /* pointer to ref not okay */
7933 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7938 if (isbyref) /* array of ref and generic ref are not okay */
7940 //Decide if it's an array of a generic argument list
7945 if (*p == ',' || *p == '*' || *p == ']') { //array
7953 else if (*p == '*') /* '*' means unknown lower bound */
7954 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7961 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7963 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7966 info->type_arguments = g_ptr_array_new ();
7968 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7969 gboolean fqname = FALSE;
7971 g_ptr_array_add (info->type_arguments, subinfo);
7973 while (*p == ' ') p++;
7979 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7982 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7983 if (fqname && (*p != ']')) {
7991 while (*p && (*p != ']'))
7999 if (g_ascii_isspace (*aname)) {
8006 !assembly_name_to_aname (&subinfo->assembly, aname))
8008 } else if (fqname && (*p == ']')) {
8030 if (g_ascii_isspace (*p)) {
8037 return 0; /* missing assembly name */
8038 if (!assembly_name_to_aname (&info->assembly, p))
8044 if (info->assembly.name)
8047 // *w = 0; /* terminate class name */
8049 if (!info->name || !*info->name)
8053 /* add other consistency checks */
8059 * mono_identifier_unescape_type_name_chars:
8060 * @identifier: the display name of a mono type
8063 * The name in internal form, that is without escaping backslashes.
8065 * The string is modified in place!
8068 mono_identifier_unescape_type_name_chars(char* identifier)
8073 for (w = r = identifier; *r != 0; r++)
8091 mono_identifier_unescape_info (MonoTypeNameParse* info);
8094 unescape_each_type_argument(void* data, void* user_data)
8096 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8097 mono_identifier_unescape_info (info);
8101 unescape_each_nested_name (void* data, void* user_data)
8103 char* nested_name = (char*) data;
8104 mono_identifier_unescape_type_name_chars(nested_name);
8108 * mono_identifier_unescape_info:
8110 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8114 * Destructively updates the info by unescaping the identifiers that
8115 * comprise the type namespace, name, nested types (if any) and
8116 * generic type arguments (if any).
8118 * The resulting info has the names in internal form.
8122 mono_identifier_unescape_info (MonoTypeNameParse *info)
8126 mono_identifier_unescape_type_name_chars(info->name_space);
8127 mono_identifier_unescape_type_name_chars(info->name);
8128 // but don't escape info->assembly
8129 if (info->type_arguments)
8130 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8132 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8136 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8138 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8140 mono_identifier_unescape_info (info);
8146 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8148 gboolean type_resolve = FALSE;
8150 MonoImage *rootimage = image;
8152 if (info->assembly.name) {
8153 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8154 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8156 * This could happen in the AOT compiler case when the search hook is not
8159 assembly = image->assembly;
8161 /* then we must load the assembly ourselve - see #60439 */
8162 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8166 image = assembly->image;
8167 } else if (!image) {
8168 image = mono_defaults.corlib;
8171 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8172 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8173 image = mono_defaults.corlib;
8174 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8181 * mono_reflection_get_type_internal:
8183 * Returns: may return NULL on success, sets error on failure.
8186 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8191 gboolean bounded = FALSE;
8193 mono_error_init (error);
8195 image = mono_defaults.corlib;
8198 rootimage = mono_defaults.corlib;
8201 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8202 g_assert (mono_error_ok (error)); /* FIXME Don't swallow the error */
8204 klass = mono_class_from_name (image, info->name_space, info->name);
8209 for (mod = info->nested; mod; mod = mod->next) {
8210 gpointer iter = NULL;
8214 mono_class_init (parent);
8216 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8218 char *nested_name, *nested_nspace;
8219 gboolean match = TRUE;
8221 lastp = strrchr ((const char *)mod->data, '.');
8223 /* Nested classes can have namespaces */
8226 nested_name = g_strdup (lastp + 1);
8227 nspace_len = lastp - (char*)mod->data;
8228 nested_nspace = (char *)g_malloc (nspace_len + 1);
8229 memcpy (nested_nspace, mod->data, nspace_len);
8230 nested_nspace [nspace_len] = '\0';
8233 nested_name = (char *)mod->data;
8234 nested_nspace = NULL;
8237 if (nested_nspace) {
8239 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8242 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8248 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8251 if (strcmp (klass->name, nested_name) != 0)
8256 g_free (nested_name);
8257 g_free (nested_nspace);
8269 if (info->type_arguments) {
8270 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8271 MonoReflectionType *the_type;
8275 for (i = 0; i < info->type_arguments->len; i++) {
8276 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8278 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8279 if (!type_args [i]) {
8285 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8289 instance = mono_reflection_bind_generic_parameters (
8290 the_type, info->type_arguments->len, type_args);
8296 klass = mono_class_from_mono_type (instance);
8299 for (mod = info->modifiers; mod; mod = mod->next) {
8300 modval = GPOINTER_TO_UINT (mod->data);
8301 if (!modval) { /* byref: must be last modifier */
8302 return &klass->this_arg;
8303 } else if (modval == -1) {
8304 klass = mono_ptr_class_get (&klass->byval_arg);
8305 } else if (modval == -2) {
8307 } else { /* array rank */
8308 klass = mono_bounded_array_class_get (klass, modval, bounded);
8312 return &klass->byval_arg;
8316 * mono_reflection_get_type:
8317 * @image: a metadata context
8318 * @info: type description structure
8319 * @ignorecase: flag for case-insensitive string compares
8320 * @type_resolve: whenever type resolve was already tried
8322 * Build a MonoType from the type description in @info.
8327 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8328 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8332 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8334 MonoReflectionAssemblyBuilder *abuilder;
8338 mono_error_init (error);
8339 g_assert (assembly_is_dynamic (assembly));
8340 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8344 /* Enumerate all modules */
8347 if (abuilder->modules) {
8348 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8349 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8350 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8353 if (!mono_error_ok (error))
8358 if (!type && abuilder->loaded_modules) {
8359 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8360 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8361 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8364 if (!mono_error_ok (error))
8373 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8377 MonoReflectionAssembly *assembly;
8381 if (image && image_is_dynamic (image))
8382 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8384 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8386 if (!mono_error_ok(&error))
8387 mono_error_raise_exception (&error); /* FIXME don't raise here */
8391 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8398 *type_resolve = TRUE;
8401 /* Reconstruct the type name */
8402 fullName = g_string_new ("");
8403 if (info->name_space && (info->name_space [0] != '\0'))
8404 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8406 g_string_printf (fullName, "%s", info->name);
8407 for (mod = info->nested; mod; mod = mod->next)
8408 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8410 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8412 if (assembly_is_dynamic (assembly->assembly))
8413 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8414 info, ignorecase, &error);
8416 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8417 info, ignorecase, &error);
8419 g_string_free (fullName, TRUE);
8420 if (!mono_error_ok (&error))
8421 mono_error_raise_exception (&error); /* FIXME don't raise here */
8426 mono_reflection_free_type_info (MonoTypeNameParse *info)
8428 g_list_free (info->modifiers);
8429 g_list_free (info->nested);
8431 if (info->type_arguments) {
8434 for (i = 0; i < info->type_arguments->len; i++) {
8435 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8437 mono_reflection_free_type_info (subinfo);
8438 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8442 g_ptr_array_free (info->type_arguments, TRUE);
8447 * mono_reflection_type_from_name:
8449 * @image: a metadata context (can be NULL).
8451 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8452 * it defaults to get the type from @image or, if @image is NULL or loading
8453 * from it fails, uses corlib.
8457 mono_reflection_type_from_name (char *name, MonoImage *image)
8459 MonoType *type = NULL;
8460 MonoTypeNameParse info;
8463 /* Make a copy since parse_type modifies its argument */
8464 tmp = g_strdup (name);
8466 /*g_print ("requested type %s\n", str);*/
8467 if (mono_reflection_parse_type (tmp, &info)) {
8468 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8472 mono_reflection_free_type_info (&info);
8477 * mono_reflection_get_token:
8479 * Return the metadata token of OBJ which should be an object
8480 * representing a metadata element.
8483 mono_reflection_get_token (MonoObject *obj)
8488 klass = obj->vtable->klass;
8490 if (strcmp (klass->name, "MethodBuilder") == 0) {
8491 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8493 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8494 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8495 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8497 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8498 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8499 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8501 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8502 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8504 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8505 } else if (strcmp (klass->name, "MonoType") == 0) {
8506 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8507 MonoClass *mc = mono_class_from_mono_type (type);
8508 if (!mono_class_init (mc))
8509 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8511 token = mc->type_token;
8512 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8513 strcmp (klass->name, "MonoMethod") == 0 ||
8514 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8515 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8516 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8517 if (m->method->is_inflated) {
8518 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8519 return inflated->declaring->token;
8521 token = m->method->token;
8523 } else if (strcmp (klass->name, "MonoField") == 0) {
8524 MonoReflectionField *f = (MonoReflectionField*)obj;
8526 if (is_field_on_inst (f->field)) {
8527 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8529 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8530 int field_index = f->field - dgclass->fields;
8533 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8534 obj = dgclass->field_objects [field_index];
8535 return mono_reflection_get_token (obj);
8538 token = mono_class_get_field_token (f->field);
8539 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8540 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8542 token = mono_class_get_property_token (p->property);
8543 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8544 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8546 token = mono_class_get_event_token (p->event);
8547 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8548 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8549 MonoClass *member_class = mono_object_class (p->MemberImpl);
8550 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8552 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8553 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8554 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8557 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8558 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8560 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8561 MonoException *ex = mono_get_exception_not_implemented (msg);
8563 mono_raise_exception (ex);
8570 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8574 int slen = mono_metadata_decode_value (p, &p);
8576 mono_error_init (error);
8578 n = (char *)g_memdup (p, slen + 1);
8580 t = mono_reflection_type_from_name (n, image);
8582 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8583 /* We don't free n, it's consumed by mono_error */
8584 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8590 return mono_class_from_mono_type (t);
8594 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8596 int slen, type = t->type;
8597 MonoClass *tklass = t->data.klass;
8599 mono_error_init (error);
8605 case MONO_TYPE_BOOLEAN: {
8606 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8611 case MONO_TYPE_CHAR:
8613 case MONO_TYPE_I2: {
8614 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8619 #if SIZEOF_VOID_P == 4
8625 case MONO_TYPE_I4: {
8626 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8631 #if SIZEOF_VOID_P == 8
8632 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8636 case MONO_TYPE_I8: {
8637 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8642 case MONO_TYPE_R8: {
8643 double *val = (double *)g_malloc (sizeof (double));
8648 case MONO_TYPE_VALUETYPE:
8649 if (t->data.klass->enumtype) {
8650 type = mono_class_enum_basetype (t->data.klass)->type;
8653 MonoClass *k = t->data.klass;
8655 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8656 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8662 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8665 case MONO_TYPE_STRING:
8666 if (*p == (char)0xFF) {
8670 slen = mono_metadata_decode_value (p, &p);
8672 return mono_string_new_len (mono_domain_get (), p, slen);
8673 case MONO_TYPE_CLASS: {
8674 MonoReflectionType *rt;
8677 if (*p == (char)0xFF) {
8682 slen = mono_metadata_decode_value (p, &p);
8683 n = (char *)g_memdup (p, slen + 1);
8685 t = mono_reflection_type_from_name (n, image);
8687 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8688 /* We don't free n, it's consumed by mono_error */
8689 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8695 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8696 if (!mono_error_ok (error))
8701 case MONO_TYPE_OBJECT: {
8704 MonoClass *subc = NULL;
8709 } else if (subt == 0x0E) {
8710 type = MONO_TYPE_STRING;
8712 } else if (subt == 0x1D) {
8713 MonoType simple_type = {{0}};
8717 type = MONO_TYPE_SZARRAY;
8718 if (etype == 0x50) {
8719 tklass = mono_defaults.systemtype_class;
8720 } else if (etype == 0x55) {
8721 tklass = load_cattr_enum_type (image, p, &p, error);
8722 if (!mono_error_ok (error))
8726 /* See Partition II, Appendix B3 */
8727 etype = MONO_TYPE_OBJECT;
8728 simple_type.type = (MonoTypeEnum)etype;
8729 tklass = mono_class_from_mono_type (&simple_type);
8732 } else if (subt == 0x55) {
8735 slen = mono_metadata_decode_value (p, &p);
8736 n = (char *)g_memdup (p, slen + 1);
8738 t = mono_reflection_type_from_name (n, image);
8740 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8741 /* We don't free n, it's consumed by mono_error */
8742 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8747 subc = mono_class_from_mono_type (t);
8748 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8749 MonoType simple_type = {{0}};
8750 simple_type.type = (MonoTypeEnum)subt;
8751 subc = mono_class_from_mono_type (&simple_type);
8753 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8755 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8757 if (mono_error_ok (error)) {
8758 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8759 g_assert (!subc->has_references);
8760 if (mono_error_ok (error))
8761 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8767 case MONO_TYPE_SZARRAY: {
8769 guint32 i, alen, basetype;
8772 if (alen == 0xffffffff) {
8776 arr = mono_array_new (mono_domain_get(), tklass, alen);
8777 basetype = tklass->byval_arg.type;
8778 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8779 basetype = mono_class_enum_basetype (tklass)->type;
8784 case MONO_TYPE_BOOLEAN:
8785 for (i = 0; i < alen; i++) {
8786 MonoBoolean val = *p++;
8787 mono_array_set (arr, MonoBoolean, i, val);
8790 case MONO_TYPE_CHAR:
8793 for (i = 0; i < alen; i++) {
8794 guint16 val = read16 (p);
8795 mono_array_set (arr, guint16, i, val);
8802 for (i = 0; i < alen; i++) {
8803 guint32 val = read32 (p);
8804 mono_array_set (arr, guint32, i, val);
8809 for (i = 0; i < alen; i++) {
8812 mono_array_set (arr, double, i, val);
8818 for (i = 0; i < alen; i++) {
8819 guint64 val = read64 (p);
8820 mono_array_set (arr, guint64, i, val);
8824 case MONO_TYPE_CLASS:
8825 case MONO_TYPE_OBJECT:
8826 case MONO_TYPE_STRING:
8827 case MONO_TYPE_SZARRAY:
8828 for (i = 0; i < alen; i++) {
8829 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8830 if (!mono_error_ok (error))
8832 mono_array_setref (arr, i, item);
8836 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8842 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8848 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8850 static MonoClass *klass;
8851 static MonoMethod *ctor;
8854 void *params [2], *unboxed;
8857 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8859 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8861 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8862 mono_error_raise_exception (&error); /* FIXME don't raise here */
8865 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8866 mono_error_raise_exception (&error); /* FIXME don't raise here */
8867 unboxed = mono_object_unbox (retval);
8869 mono_runtime_invoke_checked (ctor, unboxed, params, &error);
8870 mono_error_raise_exception (&error); /* FIXME don't raise here */
8876 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8878 static MonoClass *klass;
8879 static MonoMethod *ctor;
8882 void *unboxed, *params [2];
8885 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8887 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8890 params [1] = typedarg;
8891 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8892 mono_error_raise_exception (&error); /* FIXME don't raise here */
8893 unboxed = mono_object_unbox (retval);
8895 mono_runtime_invoke_checked (ctor, unboxed, params, &error);
8896 mono_error_raise_exception (&error); /* FIXME don't raise here */
8902 type_is_reference (MonoType *type)
8904 switch (type->type) {
8905 case MONO_TYPE_BOOLEAN:
8906 case MONO_TYPE_CHAR:
8919 case MONO_TYPE_VALUETYPE:
8927 free_param_data (MonoMethodSignature *sig, void **params) {
8929 for (i = 0; i < sig->param_count; ++i) {
8930 if (!type_is_reference (sig->params [i]))
8931 g_free (params [i]);
8936 * Find the field index in the metadata FieldDef table.
8939 find_field_index (MonoClass *klass, MonoClassField *field) {
8942 for (i = 0; i < klass->field.count; ++i) {
8943 if (field == &klass->fields [i])
8944 return klass->field.first + 1 + i;
8950 * Find the property index in the metadata Property table.
8953 find_property_index (MonoClass *klass, MonoProperty *property) {
8956 for (i = 0; i < klass->ext->property.count; ++i) {
8957 if (property == &klass->ext->properties [i])
8958 return klass->ext->property.first + 1 + i;
8964 * Find the event index in the metadata Event table.
8967 find_event_index (MonoClass *klass, MonoEvent *event) {
8970 for (i = 0; i < klass->ext->event.count; ++i) {
8971 if (event == &klass->ext->events [i])
8972 return klass->ext->event.first + 1 + i;
8978 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8980 const char *p = (const char*)data;
8982 guint32 i, j, num_named;
8984 void *params_buf [32];
8985 void **params = NULL;
8986 MonoMethodSignature *sig;
8987 MonoObject *exc = NULL;
8989 mono_error_init (error);
8991 mono_class_init (method->klass);
8993 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8994 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8999 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9000 if (!mono_error_ok (error)) return NULL;
9002 mono_runtime_invoke_checked (method, attr, NULL, error);
9003 if (!mono_error_ok (error))
9009 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9012 /*g_print ("got attr %s\n", method->klass->name);*/
9014 sig = mono_method_signature (method);
9015 if (sig->param_count < 32) {
9016 params = params_buf;
9017 memset (params, 0, sizeof (void*) * sig->param_count);
9019 /* Allocate using GC so it gets GC tracking */
9020 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9025 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9026 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9027 if (!mono_error_ok (error))
9032 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9033 if (!mono_error_ok (error)) goto fail;
9035 mono_runtime_try_invoke (method, attr, params, &exc, error);
9036 if (!mono_error_ok (error))
9041 num_named = read16 (named);
9043 for (j = 0; j < num_named; j++) {
9045 char *name, named_type, data_type;
9046 named_type = *named++;
9047 data_type = *named++; /* type of data */
9048 if (data_type == MONO_TYPE_SZARRAY)
9049 data_type = *named++;
9050 if (data_type == MONO_TYPE_ENUM) {
9053 type_len = mono_metadata_decode_blob_size (named, &named);
9054 type_name = (char *)g_malloc (type_len + 1);
9055 memcpy (type_name, named, type_len);
9056 type_name [type_len] = 0;
9058 /* FIXME: lookup the type and check type consistency */
9061 name_len = mono_metadata_decode_blob_size (named, &named);
9062 name = (char *)g_malloc (name_len + 1);
9063 memcpy (name, named, name_len);
9064 name [name_len] = 0;
9066 if (named_type == 0x53) {
9067 MonoClassField *field;
9070 /* how this fail is a blackbox */
9071 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9073 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9078 val = load_cattr_value (image, field->type, named, &named, error);
9079 if (!mono_error_ok (error)) {
9081 if (!type_is_reference (field->type))
9086 mono_field_set_value (attr, field, val);
9087 if (!type_is_reference (field->type))
9089 } else if (named_type == 0x54) {
9092 MonoType *prop_type;
9094 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9097 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9103 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9108 /* can we have more that 1 arg in a custom attr named property? */
9109 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9110 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9112 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9113 if (!mono_error_ok (error)) {
9115 if (!type_is_reference (prop_type))
9116 g_free (pparams [0]);
9121 mono_property_set_value (prop, attr, pparams, NULL);
9122 if (!type_is_reference (prop_type))
9123 g_free (pparams [0]);
9128 free_param_data (method->signature, params);
9129 if (params != params_buf)
9130 mono_gc_free_fixed (params);
9135 free_param_data (method->signature, params);
9136 if (params != params_buf)
9137 mono_gc_free_fixed (params);
9139 mono_raise_exception ((MonoException*)exc);
9144 * mono_reflection_create_custom_attr_data_args:
9146 * Create an array of typed and named arguments from the cattr blob given by DATA.
9147 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9148 * NAMED_ARG_INFO will contain information about the named arguments.
9151 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)
9153 MonoArray *typedargs, *namedargs;
9154 MonoClass *attrklass;
9156 const char *p = (const char*)data;
9158 guint32 i, j, num_named;
9159 CattrNamedArg *arginfo = NULL;
9163 *named_arg_info = NULL;
9165 mono_error_init (error);
9167 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9168 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9172 mono_class_init (method->klass);
9174 domain = mono_domain_get ();
9176 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9179 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9183 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9187 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9188 if (!mono_error_ok (error)) {
9189 if (!type_is_reference (mono_method_signature (method)->params [i]))
9194 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9195 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9196 mono_array_setref (typedargs, i, obj);
9198 if (!type_is_reference (mono_method_signature (method)->params [i]))
9203 num_named = read16 (named);
9204 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9206 attrklass = method->klass;
9208 arginfo = g_new0 (CattrNamedArg, num_named);
9209 *named_arg_info = arginfo;
9211 for (j = 0; j < num_named; j++) {
9213 char *name, named_type, data_type;
9214 named_type = *named++;
9215 data_type = *named++; /* type of data */
9216 if (data_type == MONO_TYPE_SZARRAY)
9217 data_type = *named++;
9218 if (data_type == MONO_TYPE_ENUM) {
9221 type_len = mono_metadata_decode_blob_size (named, &named);
9222 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9225 type_name = (char *)g_malloc (type_len + 1);
9226 memcpy (type_name, named, type_len);
9227 type_name [type_len] = 0;
9229 /* FIXME: lookup the type and check type consistency */
9232 name_len = mono_metadata_decode_blob_size (named, &named);
9233 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9235 name = (char *)g_malloc (name_len + 1);
9236 memcpy (name, named, name_len);
9237 name [name_len] = 0;
9239 if (named_type == 0x53) {
9241 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9249 arginfo [j].type = field->type;
9250 arginfo [j].field = field;
9252 val = load_cattr_value (image, field->type, named, &named, error);
9253 if (!mono_error_ok (error)) {
9254 if (!type_is_reference (field->type))
9260 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9261 mono_array_setref (namedargs, j, obj);
9262 if (!type_is_reference (field->type))
9264 } else if (named_type == 0x54) {
9266 MonoType *prop_type;
9267 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9270 if (!prop || !prop->set) {
9275 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9276 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9278 arginfo [j].type = prop_type;
9279 arginfo [j].prop = prop;
9281 val = load_cattr_value (image, prop_type, named, &named, error);
9282 if (!mono_error_ok (error)) {
9283 if (!type_is_reference (prop_type))
9289 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9290 mono_array_setref (namedargs, j, obj);
9291 if (!type_is_reference (prop_type))
9297 *typed_args = typedargs;
9298 *named_args = namedargs;
9301 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9303 *named_arg_info = NULL;
9307 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9310 MonoArray *typedargs, *namedargs;
9313 CattrNamedArg *arginfo = NULL;
9317 mono_error_init (&error);
9325 image = assembly->assembly->image;
9326 method = ref_method->method;
9327 domain = mono_object_domain (ref_method);
9329 if (!mono_class_init (method->klass))
9330 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9332 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9333 if (!mono_error_ok (&error))
9336 if (mono_loader_get_last_error ()) {
9337 mono_error_set_from_loader_error (&error);
9341 if (!typedargs || !namedargs)
9344 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9345 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9346 MonoObject *typedarg;
9348 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9349 mono_array_setref (typedargs, i, typedarg);
9352 for (i = 0; i < mono_array_length (namedargs); ++i) {
9353 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9354 MonoObject *typedarg, *namedarg, *minfo;
9356 if (arginfo [i].prop)
9357 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9359 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9360 if (!mono_error_ok (&error))
9364 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9365 namedarg = create_cattr_named_arg (minfo, typedarg);
9367 mono_array_setref (namedargs, i, namedarg);
9370 *ctor_args = typedargs;
9371 *named_args = namedargs;
9374 mono_error_raise_exception (&error);
9379 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9381 static MonoMethod *ctor;
9388 g_assert (image->assembly);
9391 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9393 domain = mono_domain_get ();
9394 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9395 mono_error_raise_exception (&error); /* FIXME don't raise here */
9396 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9397 mono_error_raise_exception (&error); /* FIXME don't raise here */
9398 params [1] = mono_assembly_get_object_checked (domain, image->assembly, &error);
9399 mono_error_raise_exception (&error); /* FIXME don't raise here */
9400 params [2] = (gpointer)&cattr->data;
9401 params [3] = &cattr->data_size;
9403 mono_runtime_invoke_checked (ctor, attr, params, &error);
9404 mono_error_raise_exception (&error); /* FIXME don't raise here */
9410 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9416 mono_error_init (error);
9419 for (i = 0; i < cinfo->num_attrs; ++i) {
9420 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9424 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9426 for (i = 0; i < cinfo->num_attrs; ++i) {
9427 if (!cinfo->attrs [i].ctor)
9428 /* The cattr type is not finished yet */
9429 /* We should include the type name but cinfo doesn't contain it */
9430 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9431 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9432 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9433 if (!mono_error_ok (error))
9435 mono_array_setref (result, n, attr);
9443 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9446 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9447 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9453 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9459 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9460 for (i = 0; i < cinfo->num_attrs; ++i) {
9461 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9462 mono_array_setref (result, i, attr);
9468 * mono_custom_attrs_from_index:
9470 * Returns: NULL if no attributes are found or if a loading error occurs.
9473 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9475 guint32 mtoken, i, len;
9476 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9478 MonoCustomAttrInfo *ainfo;
9479 GList *tmp, *list = NULL;
9481 MonoCustomAttrEntry* attr;
9483 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9485 i = mono_metadata_custom_attrs_from_index (image, idx);
9489 while (i < ca->rows) {
9490 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9492 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9495 len = g_list_length (list);
9498 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9499 ainfo->num_attrs = len;
9500 ainfo->image = image;
9501 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9503 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9504 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9505 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9506 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9507 mtoken |= MONO_TOKEN_METHOD_DEF;
9509 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9510 mtoken |= MONO_TOKEN_MEMBER_REF;
9513 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9516 attr = &ainfo->attrs [i - 1];
9517 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9519 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9520 mono_loader_set_error_from_mono_error (&error);
9526 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9527 /*FIXME raising an exception here doesn't make any sense*/
9528 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9533 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9534 attr->data_size = mono_metadata_decode_value (data, &data);
9535 attr->data = (guchar*)data;
9543 mono_custom_attrs_from_method (MonoMethod *method)
9548 * An instantiated method has the same cattrs as the generic method definition.
9550 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9551 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9553 if (method->is_inflated)
9554 method = ((MonoMethodInflated *) method)->declaring;
9556 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9557 return lookup_custom_attr (method->klass->image, method);
9560 /* Synthetic methods */
9563 idx = mono_method_get_index (method);
9564 idx <<= MONO_CUSTOM_ATTR_BITS;
9565 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9566 return mono_custom_attrs_from_index (method->klass->image, idx);
9570 mono_custom_attrs_from_class (MonoClass *klass)
9574 if (klass->generic_class)
9575 klass = klass->generic_class->container_class;
9577 if (image_is_dynamic (klass->image))
9578 return lookup_custom_attr (klass->image, klass);
9580 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9581 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9582 idx <<= MONO_CUSTOM_ATTR_BITS;
9583 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9585 idx = mono_metadata_token_index (klass->type_token);
9586 idx <<= MONO_CUSTOM_ATTR_BITS;
9587 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9589 return mono_custom_attrs_from_index (klass->image, idx);
9593 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9597 if (image_is_dynamic (assembly->image))
9598 return lookup_custom_attr (assembly->image, assembly);
9599 idx = 1; /* there is only one assembly */
9600 idx <<= MONO_CUSTOM_ATTR_BITS;
9601 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9602 return mono_custom_attrs_from_index (assembly->image, idx);
9605 static MonoCustomAttrInfo*
9606 mono_custom_attrs_from_module (MonoImage *image)
9610 if (image_is_dynamic (image))
9611 return lookup_custom_attr (image, image);
9612 idx = 1; /* there is only one module */
9613 idx <<= MONO_CUSTOM_ATTR_BITS;
9614 idx |= MONO_CUSTOM_ATTR_MODULE;
9615 return mono_custom_attrs_from_index (image, idx);
9619 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9623 if (image_is_dynamic (klass->image)) {
9624 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9625 return lookup_custom_attr (klass->image, property);
9627 idx = find_property_index (klass, property);
9628 idx <<= MONO_CUSTOM_ATTR_BITS;
9629 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9630 return mono_custom_attrs_from_index (klass->image, idx);
9634 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9638 if (image_is_dynamic (klass->image)) {
9639 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9640 return lookup_custom_attr (klass->image, event);
9642 idx = find_event_index (klass, event);
9643 idx <<= MONO_CUSTOM_ATTR_BITS;
9644 idx |= MONO_CUSTOM_ATTR_EVENT;
9645 return mono_custom_attrs_from_index (klass->image, idx);
9649 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9652 if (image_is_dynamic (klass->image)) {
9653 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9654 return lookup_custom_attr (klass->image, field);
9656 idx = find_field_index (klass, field);
9657 idx <<= MONO_CUSTOM_ATTR_BITS;
9658 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9659 return mono_custom_attrs_from_index (klass->image, idx);
9663 * mono_custom_attrs_from_param:
9664 * @method: handle to the method that we want to retrieve custom parameter information from
9665 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9667 * The result must be released with mono_custom_attrs_free().
9669 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9672 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9675 guint32 i, idx, method_index;
9676 guint32 param_list, param_last, param_pos, found;
9678 MonoReflectionMethodAux *aux;
9681 * An instantiated method has the same cattrs as the generic method definition.
9683 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9684 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9686 if (method->is_inflated)
9687 method = ((MonoMethodInflated *) method)->declaring;
9689 if (image_is_dynamic (method->klass->image)) {
9690 MonoCustomAttrInfo *res, *ainfo;
9693 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9694 if (!aux || !aux->param_cattr)
9697 /* Need to copy since it will be freed later */
9698 ainfo = aux->param_cattr [param];
9701 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9702 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9703 memcpy (res, ainfo, size);
9707 image = method->klass->image;
9708 method_index = mono_method_get_index (method);
9711 ca = &image->tables [MONO_TABLE_METHOD];
9713 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9714 if (method_index == ca->rows) {
9715 ca = &image->tables [MONO_TABLE_PARAM];
9716 param_last = ca->rows + 1;
9718 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9719 ca = &image->tables [MONO_TABLE_PARAM];
9722 for (i = param_list; i < param_last; ++i) {
9723 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9724 if (param_pos == param) {
9732 idx <<= MONO_CUSTOM_ATTR_BITS;
9733 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9734 return mono_custom_attrs_from_index (image, idx);
9738 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9742 for (i = 0; i < ainfo->num_attrs; ++i) {
9743 klass = ainfo->attrs [i].ctor->klass;
9744 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9751 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9754 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9755 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9760 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9766 mono_error_init (error);
9769 for (i = 0; i < ainfo->num_attrs; ++i) {
9770 klass = ainfo->attrs [i].ctor->klass;
9771 if (mono_class_has_parent (klass, attr_klass)) {
9776 if (attr_index == -1)
9779 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9780 if (!mono_error_ok (error))
9782 return mono_array_get (attrs, MonoObject*, attr_index);
9786 * mono_reflection_get_custom_attrs_info:
9787 * @obj: a reflection object handle
9789 * Return the custom attribute info for attributes defined for the
9790 * reflection handle @obj. The objects.
9792 * FIXME this function leaks like a sieve for SRE objects.
9795 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9798 MonoCustomAttrInfo *cinfo = NULL;
9800 klass = obj->vtable->klass;
9801 if (klass == mono_defaults.monotype_class) {
9802 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9803 klass = mono_class_from_mono_type (type);
9804 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9805 cinfo = mono_custom_attrs_from_class (klass);
9806 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9807 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9808 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9809 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9810 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9811 cinfo = mono_custom_attrs_from_module (module->image);
9812 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9813 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9814 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9815 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9816 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9817 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9818 } else if (strcmp ("MonoField", klass->name) == 0) {
9819 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9820 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9821 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9822 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9823 cinfo = mono_custom_attrs_from_method (rmethod->method);
9824 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9825 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9826 cinfo = mono_custom_attrs_from_method (rmethod->method);
9827 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9828 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9829 MonoClass *member_class = mono_object_class (param->MemberImpl);
9830 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9831 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9832 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9833 } else if (is_sr_mono_property (member_class)) {
9834 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9836 if (!(method = prop->property->get))
9837 method = prop->property->set;
9840 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9842 #ifndef DISABLE_REFLECTION_EMIT
9843 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9844 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9845 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9846 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9847 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9848 MonoMethod *method = NULL;
9849 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9850 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9851 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9852 method = ((MonoReflectionMethod *)c->cb)->method;
9854 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));
9856 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9860 char *type_name = mono_type_get_full_name (member_class);
9861 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9862 MonoException *ex = mono_get_exception_not_supported (msg);
9865 mono_raise_exception (ex);
9867 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9868 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9869 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9870 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9871 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9872 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9873 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9874 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9875 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9876 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9877 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9878 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9879 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9880 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9881 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9882 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9883 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9884 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9885 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9886 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9887 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9888 } else { /* handle other types here... */
9889 g_error ("get custom attrs not yet supported for %s", klass->name);
9896 * mono_reflection_get_custom_attrs_by_type:
9897 * @obj: a reflection object handle
9899 * Return an array with all the custom attributes defined of the
9900 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9901 * of that type are returned. The objects are fully build. Return NULL if a loading error
9905 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9908 MonoCustomAttrInfo *cinfo;
9910 mono_error_init (error);
9912 cinfo = mono_reflection_get_custom_attrs_info (obj);
9914 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9916 mono_custom_attrs_free (cinfo);
9918 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9919 if (mono_loader_get_last_error ())
9921 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9928 * mono_reflection_get_custom_attrs:
9929 * @obj: a reflection object handle
9931 * Return an array with all the custom attributes defined of the
9932 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9936 mono_reflection_get_custom_attrs (MonoObject *obj)
9940 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9944 * mono_reflection_get_custom_attrs_data:
9945 * @obj: a reflection obj handle
9947 * Returns an array of System.Reflection.CustomAttributeData,
9948 * which include information about attributes reflected on
9949 * types loaded using the Reflection Only methods
9952 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9955 MonoCustomAttrInfo *cinfo;
9957 cinfo = mono_reflection_get_custom_attrs_info (obj);
9959 result = mono_custom_attrs_data_construct (cinfo);
9961 mono_custom_attrs_free (cinfo);
9963 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9968 static MonoReflectionType*
9969 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9971 static MonoMethod *method_get_underlying_system_type = NULL;
9973 MonoReflectionType *rt;
9974 MonoMethod *usertype_method;
9976 if (!method_get_underlying_system_type)
9977 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9979 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9981 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, &error);
9982 mono_error_raise_exception (&error); /* FIXME don't raise here */
9989 is_corlib_type (MonoClass *klass)
9991 return klass->image == mono_defaults.corlib;
9994 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9995 static MonoClass *cached_class; \
9997 return cached_class == _class; \
9998 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9999 cached_class = _class; \
10006 #ifndef DISABLE_REFLECTION_EMIT
10008 is_sre_array (MonoClass *klass)
10010 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10014 is_sre_byref (MonoClass *klass)
10016 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10020 is_sre_pointer (MonoClass *klass)
10022 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10026 is_sre_generic_instance (MonoClass *klass)
10028 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10032 is_sre_type_builder (MonoClass *klass)
10034 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10038 is_sre_method_builder (MonoClass *klass)
10040 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10044 is_sre_ctor_builder (MonoClass *klass)
10046 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10050 is_sre_field_builder (MonoClass *klass)
10052 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10056 is_sre_method_on_tb_inst (MonoClass *klass)
10058 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10062 is_sre_ctor_on_tb_inst (MonoClass *klass)
10064 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10068 mono_reflection_type_get_handle (MonoReflectionType* ref)
10076 if (is_usertype (ref)) {
10077 ref = mono_reflection_type_get_underlying_system_type (ref);
10078 if (ref == NULL || is_usertype (ref))
10084 klass = mono_object_class (ref);
10086 if (is_sre_array (klass)) {
10088 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10089 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10091 if (sre_array->rank == 0) //single dimentional array
10092 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10094 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10095 sre_array->type.type = res;
10097 } else if (is_sre_byref (klass)) {
10099 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10100 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10102 res = &mono_class_from_mono_type (base)->this_arg;
10103 sre_byref->type.type = res;
10105 } else if (is_sre_pointer (klass)) {
10107 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10108 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10110 res = &mono_ptr_class_get (base)->byval_arg;
10111 sre_pointer->type.type = res;
10113 } else if (is_sre_generic_instance (klass)) {
10114 MonoType *res, **types;
10115 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10118 count = mono_array_length (gclass->type_arguments);
10119 types = g_new0 (MonoType*, count);
10120 for (i = 0; i < count; ++i) {
10121 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10122 types [i] = mono_reflection_type_get_handle (t);
10129 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10132 gclass->type.type = res;
10136 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10143 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10145 mono_reflection_type_get_handle (type);
10149 mono_reflection_register_with_runtime (MonoReflectionType *type)
10151 MonoType *res = mono_reflection_type_get_handle (type);
10152 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10156 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10158 klass = mono_class_from_mono_type (res);
10160 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10161 mono_domain_lock (domain);
10163 if (!image_is_dynamic (klass->image)) {
10164 mono_class_setup_supertypes (klass);
10166 if (!domain->type_hash)
10167 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10168 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10169 mono_g_hash_table_insert (domain->type_hash, res, type);
10171 mono_domain_unlock (domain);
10172 mono_loader_unlock ();
10176 * LOCKING: Assumes the loader lock is held.
10178 static MonoMethodSignature*
10179 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10180 MonoMethodSignature *sig;
10183 count = parameters? mono_array_length (parameters): 0;
10185 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10186 sig->param_count = count;
10187 sig->sentinelpos = -1; /* FIXME */
10188 for (i = 0; i < count; ++i)
10189 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10194 * LOCKING: Assumes the loader lock is held.
10196 static MonoMethodSignature*
10197 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10198 MonoMethodSignature *sig;
10200 sig = parameters_to_signature (image, ctor->parameters);
10201 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10202 sig->ret = &mono_defaults.void_class->byval_arg;
10207 * LOCKING: Assumes the loader lock is held.
10209 static MonoMethodSignature*
10210 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10211 MonoMethodSignature *sig;
10213 sig = parameters_to_signature (image, method->parameters);
10214 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10215 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10216 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10220 static MonoMethodSignature*
10221 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10222 MonoMethodSignature *sig;
10224 sig = parameters_to_signature (NULL, method->parameters);
10225 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10226 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10227 sig->generic_param_count = 0;
10232 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10234 MonoClass *klass = mono_object_class (prop);
10235 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10236 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10237 *name = mono_string_to_utf8 (pb->name);
10238 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10240 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10241 *name = g_strdup (p->property->name);
10242 if (p->property->get)
10243 *type = mono_method_signature (p->property->get)->ret;
10245 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10250 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10252 MonoClass *klass = mono_object_class (field);
10253 if (strcmp (klass->name, "FieldBuilder") == 0) {
10254 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10255 *name = mono_string_to_utf8 (fb->name);
10256 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10258 MonoReflectionField *f = (MonoReflectionField *)field;
10259 *name = g_strdup (mono_field_get_name (f->field));
10260 *type = f->field->type;
10264 #else /* DISABLE_REFLECTION_EMIT */
10267 mono_reflection_register_with_runtime (MonoReflectionType *type)
10269 /* This is empty */
10273 is_sre_type_builder (MonoClass *klass)
10279 is_sre_generic_instance (MonoClass *klass)
10285 init_type_builder_generics (MonoObject *type)
10289 #endif /* !DISABLE_REFLECTION_EMIT */
10293 is_sr_mono_field (MonoClass *klass)
10295 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10299 is_sr_mono_property (MonoClass *klass)
10301 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10305 is_sr_mono_method (MonoClass *klass)
10307 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10311 is_sr_mono_cmethod (MonoClass *klass)
10313 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10317 is_sr_mono_generic_method (MonoClass *klass)
10319 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10323 is_sr_mono_generic_cmethod (MonoClass *klass)
10325 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10329 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10331 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10335 is_usertype (MonoReflectionType *ref)
10337 MonoClass *klass = mono_object_class (ref);
10338 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10341 static MonoReflectionType*
10342 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10344 mono_error_init (error);
10345 if (!type || type->type)
10348 if (is_usertype (type)) {
10349 type = mono_reflection_type_get_underlying_system_type (type);
10350 if (is_usertype (type)) {
10351 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10359 * Encode a value in a custom attribute stream of bytes.
10360 * The value to encode is either supplied as an object in argument val
10361 * (valuetypes are boxed), or as a pointer to the data in the
10363 * @type represents the type of the value
10364 * @buffer is the start of the buffer
10365 * @p the current position in the buffer
10366 * @buflen contains the size of the buffer and is used to return the new buffer size
10367 * if this needs to be realloced.
10368 * @retbuffer and @retp return the start and the position of the buffer
10371 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10373 MonoTypeEnum simple_type;
10375 if ((p-buffer) + 10 >= *buflen) {
10378 newbuf = (char *)g_realloc (buffer, *buflen);
10379 p = newbuf + (p-buffer);
10383 argval = ((char*)arg + sizeof (MonoObject));
10384 simple_type = type->type;
10386 switch (simple_type) {
10387 case MONO_TYPE_BOOLEAN:
10392 case MONO_TYPE_CHAR:
10395 swap_with_size (p, argval, 2, 1);
10401 swap_with_size (p, argval, 4, 1);
10405 swap_with_size (p, argval, 8, 1);
10410 swap_with_size (p, argval, 8, 1);
10413 case MONO_TYPE_VALUETYPE:
10414 if (type->data.klass->enumtype) {
10415 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10418 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10421 case MONO_TYPE_STRING: {
10428 str = mono_string_to_utf8 ((MonoString*)arg);
10429 slen = strlen (str);
10430 if ((p-buffer) + 10 + slen >= *buflen) {
10434 newbuf = (char *)g_realloc (buffer, *buflen);
10435 p = newbuf + (p-buffer);
10438 mono_metadata_encode_value (slen, p, &p);
10439 memcpy (p, str, slen);
10444 case MONO_TYPE_CLASS: {
10452 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10453 slen = strlen (str);
10454 if ((p-buffer) + 10 + slen >= *buflen) {
10458 newbuf = (char *)g_realloc (buffer, *buflen);
10459 p = newbuf + (p-buffer);
10462 mono_metadata_encode_value (slen, p, &p);
10463 memcpy (p, str, slen);
10468 case MONO_TYPE_SZARRAY: {
10470 MonoClass *eclass, *arg_eclass;
10473 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10476 len = mono_array_length ((MonoArray*)arg);
10478 *p++ = (len >> 8) & 0xff;
10479 *p++ = (len >> 16) & 0xff;
10480 *p++ = (len >> 24) & 0xff;
10482 *retbuffer = buffer;
10483 eclass = type->data.klass;
10484 arg_eclass = mono_object_class (arg)->element_class;
10487 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10488 eclass = mono_defaults.object_class;
10490 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10491 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10492 int elsize = mono_class_array_element_size (arg_eclass);
10493 for (i = 0; i < len; ++i) {
10494 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10497 } else if (eclass->valuetype && arg_eclass->valuetype) {
10498 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10499 int elsize = mono_class_array_element_size (eclass);
10500 for (i = 0; i < len; ++i) {
10501 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10505 for (i = 0; i < len; ++i) {
10506 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10511 case MONO_TYPE_OBJECT: {
10517 * The parameter type is 'object' but the type of the actual
10518 * argument is not. So we have to add type information to the blob
10519 * too. This is completely undocumented in the spec.
10523 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10528 klass = mono_object_class (arg);
10530 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10533 } else if (klass->enumtype) {
10535 } else if (klass == mono_defaults.string_class) {
10536 simple_type = MONO_TYPE_STRING;
10539 } else if (klass->rank == 1) {
10541 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10542 /* See Partition II, Appendix B3 */
10545 *p++ = klass->element_class->byval_arg.type;
10546 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10548 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10549 *p++ = simple_type = klass->byval_arg.type;
10552 g_error ("unhandled type in custom attr");
10554 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10555 slen = strlen (str);
10556 if ((p-buffer) + 10 + slen >= *buflen) {
10560 newbuf = (char *)g_realloc (buffer, *buflen);
10561 p = newbuf + (p-buffer);
10564 mono_metadata_encode_value (slen, p, &p);
10565 memcpy (p, str, slen);
10568 simple_type = mono_class_enum_basetype (klass)->type;
10572 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10575 *retbuffer = buffer;
10579 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10581 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10582 char *str = type_get_qualified_name (type, NULL);
10583 int slen = strlen (str);
10587 * This seems to be optional...
10590 mono_metadata_encode_value (slen, p, &p);
10591 memcpy (p, str, slen);
10594 } else if (type->type == MONO_TYPE_OBJECT) {
10596 } else if (type->type == MONO_TYPE_CLASS) {
10597 /* it should be a type: encode_cattr_value () has the check */
10600 mono_metadata_encode_value (type->type, p, &p);
10601 if (type->type == MONO_TYPE_SZARRAY)
10602 /* See the examples in Partition VI, Annex B */
10603 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10609 #ifndef DISABLE_REFLECTION_EMIT
10611 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10614 /* Preallocate a large enough buffer */
10615 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10616 char *str = type_get_qualified_name (type, NULL);
10617 len = strlen (str);
10619 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10620 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10621 len = strlen (str);
10626 len += strlen (name);
10628 if ((p-buffer) + 20 + len >= *buflen) {
10632 newbuf = (char *)g_realloc (buffer, *buflen);
10633 p = newbuf + (p-buffer);
10637 encode_field_or_prop_type (type, p, &p);
10639 len = strlen (name);
10640 mono_metadata_encode_value (len, p, &p);
10641 memcpy (p, name, len);
10643 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10645 *retbuffer = buffer;
10649 * mono_reflection_get_custom_attrs_blob:
10650 * @ctor: custom attribute constructor
10651 * @ctorArgs: arguments o the constructor
10657 * Creates the blob of data that needs to be saved in the metadata and that represents
10658 * the custom attributed described by @ctor, @ctorArgs etc.
10659 * Returns: a Byte array representing the blob of data.
10662 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10665 MonoMethodSignature *sig;
10670 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10671 /* sig is freed later so allocate it in the heap */
10672 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10674 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10677 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10679 p = buffer = (char *)g_malloc (buflen);
10680 /* write the prolog */
10683 for (i = 0; i < sig->param_count; ++i) {
10684 arg = mono_array_get (ctorArgs, MonoObject*, i);
10685 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10689 i += mono_array_length (properties);
10691 i += mono_array_length (fields);
10693 *p++ = (i >> 8) & 0xff;
10696 for (i = 0; i < mono_array_length (properties); ++i) {
10700 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10701 get_prop_name_and_type (prop, &pname, &ptype);
10702 *p++ = 0x54; /* PROPERTY signature */
10703 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10710 for (i = 0; i < mono_array_length (fields); ++i) {
10714 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10715 get_field_name_and_type (field, &fname, &ftype);
10716 *p++ = 0x53; /* FIELD signature */
10717 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10722 g_assert (p - buffer <= buflen);
10723 buflen = p - buffer;
10724 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10725 p = mono_array_addr (result, char, 0);
10726 memcpy (p, buffer, buflen);
10728 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10734 * mono_reflection_setup_internal_class:
10735 * @tb: a TypeBuilder object
10737 * Creates a MonoClass that represents the TypeBuilder.
10738 * This is a trick that lets us simplify a lot of reflection code
10739 * (and will allow us to support Build and Run assemblies easier).
10742 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10745 MonoClass *klass, *parent;
10747 RESOLVE_TYPE (tb->parent, &error);
10748 mono_error_raise_exception (&error); /* FIXME don't raise here */
10750 mono_loader_lock ();
10753 /* check so we can compile corlib correctly */
10754 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10755 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10756 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10758 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10764 /* the type has already being created: it means we just have to change the parent */
10765 if (tb->type.type) {
10766 klass = mono_class_from_mono_type (tb->type.type);
10767 klass->parent = NULL;
10768 /* fool mono_class_setup_parent */
10769 klass->supertypes = NULL;
10770 mono_class_setup_parent (klass, parent);
10771 mono_class_setup_mono_type (klass);
10772 mono_loader_unlock ();
10776 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10778 klass->image = &tb->module->dynamic_image->image;
10780 klass->inited = 1; /* we lie to the runtime */
10781 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10782 if (!mono_error_ok (&error))
10784 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10785 if (!mono_error_ok (&error))
10787 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10788 klass->flags = tb->attrs;
10790 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10792 klass->element_class = klass;
10794 if (mono_class_get_ref_info (klass) == NULL) {
10796 mono_class_set_ref_info (klass, tb);
10798 /* Put into cache so mono_class_get_checked () will find it.
10799 Skip nested types as those should not be available on the global scope. */
10800 if (!tb->nesting_type)
10801 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10804 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10805 by performing a mono_class_get which does the full resolution.
10807 Working around this semantics would require us to write a lot of code for no clear advantage.
10809 mono_image_append_class_to_reflection_info_set (klass);
10811 g_assert (mono_class_get_ref_info (klass) == tb);
10814 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10816 if (parent != NULL) {
10817 mono_class_setup_parent (klass, parent);
10818 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10819 const char *old_n = klass->name;
10820 /* trick to get relative numbering right when compiling corlib */
10821 klass->name = "BuildingObject";
10822 mono_class_setup_parent (klass, mono_defaults.object_class);
10823 klass->name = old_n;
10826 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10827 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10828 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10829 klass->instance_size = sizeof (MonoObject);
10830 klass->size_inited = 1;
10831 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10834 mono_class_setup_mono_type (klass);
10836 mono_class_setup_supertypes (klass);
10839 * FIXME: handle interfaces.
10842 tb->type.type = &klass->byval_arg;
10844 if (tb->nesting_type) {
10845 g_assert (tb->nesting_type->type);
10846 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10849 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10851 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10853 mono_loader_unlock ();
10857 mono_loader_unlock ();
10858 mono_error_raise_exception (&error);
10862 * mono_reflection_setup_generic_class:
10863 * @tb: a TypeBuilder object
10865 * Setup the generic class before adding the first generic parameter.
10868 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10873 * mono_reflection_create_generic_class:
10874 * @tb: a TypeBuilder object
10876 * Creates the generic class after all generic parameters have been added.
10879 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10884 klass = mono_class_from_mono_type (tb->type.type);
10886 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10888 if (klass->generic_container || (count == 0))
10891 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10893 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10895 klass->generic_container->owner.klass = klass;
10896 klass->generic_container->type_argc = count;
10897 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10899 klass->is_generic = 1;
10901 for (i = 0; i < count; i++) {
10902 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10903 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10904 klass->generic_container->type_params [i] = *param;
10905 /*Make sure we are a diferent type instance */
10906 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10907 klass->generic_container->type_params [i].info.pklass = NULL;
10908 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10910 g_assert (klass->generic_container->type_params [i].param.owner);
10913 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10917 * mono_reflection_create_internal_class:
10918 * @tb: a TypeBuilder object
10920 * Actually create the MonoClass that is associated with the TypeBuilder.
10923 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10927 klass = mono_class_from_mono_type (tb->type.type);
10929 mono_loader_lock ();
10930 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10931 MonoReflectionFieldBuilder *fb;
10933 MonoType *enum_basetype;
10935 g_assert (tb->fields != NULL);
10936 g_assert (mono_array_length (tb->fields) >= 1);
10938 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10940 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10941 mono_loader_unlock ();
10945 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10946 klass->element_class = mono_class_from_mono_type (enum_basetype);
10947 if (!klass->element_class)
10948 klass->element_class = mono_class_from_mono_type (enum_basetype);
10951 * get the element_class from the current corlib.
10953 ec = default_class_from_mono_type (enum_basetype);
10954 klass->instance_size = ec->instance_size;
10955 klass->size_inited = 1;
10957 * this is almost safe to do with enums and it's needed to be able
10958 * to create objects of the enum type (for use in SetConstant).
10960 /* FIXME: Does this mean enums can't have method overrides ? */
10961 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10963 mono_loader_unlock ();
10966 static MonoMarshalSpec*
10967 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10968 MonoReflectionMarshal *minfo)
10970 MonoMarshalSpec *res;
10972 res = image_g_new0 (image, MonoMarshalSpec, 1);
10973 res->native = (MonoMarshalNative)minfo->type;
10975 switch (minfo->type) {
10976 case MONO_NATIVE_LPARRAY:
10977 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10978 if (minfo->has_size) {
10979 res->data.array_data.param_num = minfo->param_num;
10980 res->data.array_data.num_elem = minfo->count;
10981 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10984 res->data.array_data.param_num = -1;
10985 res->data.array_data.num_elem = -1;
10986 res->data.array_data.elem_mult = -1;
10990 case MONO_NATIVE_BYVALTSTR:
10991 case MONO_NATIVE_BYVALARRAY:
10992 res->data.array_data.num_elem = minfo->count;
10995 case MONO_NATIVE_CUSTOM:
10996 if (minfo->marshaltyperef)
10997 res->data.custom_data.custom_name =
10998 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10999 if (minfo->mcookie)
11000 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11009 #endif /* !DISABLE_REFLECTION_EMIT */
11011 MonoReflectionMarshalAsAttribute*
11012 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11013 MonoMarshalSpec *spec)
11015 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
11017 MonoReflectionType *rt;
11018 MonoReflectionMarshalAsAttribute *minfo;
11021 if (!System_Reflection_Emit_MarshalAsAttribute) {
11022 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
11023 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
11024 g_assert (System_Reflection_Emit_MarshalAsAttribute);
11027 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
11028 mono_error_raise_exception (&error); /* FIXME don't raise here */
11029 minfo->utype = spec->native;
11031 switch (minfo->utype) {
11032 case MONO_NATIVE_LPARRAY:
11033 minfo->array_subtype = spec->data.array_data.elem_type;
11034 minfo->size_const = spec->data.array_data.num_elem;
11035 if (spec->data.array_data.param_num != -1)
11036 minfo->size_param_index = spec->data.array_data.param_num;
11039 case MONO_NATIVE_BYVALTSTR:
11040 case MONO_NATIVE_BYVALARRAY:
11041 minfo->size_const = spec->data.array_data.num_elem;
11044 case MONO_NATIVE_CUSTOM:
11045 if (spec->data.custom_data.custom_name) {
11046 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11048 rt = mono_type_get_object_checked (domain, mtype, &error);
11049 mono_error_raise_exception (&error); /* FIXME don't raise here */
11051 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11054 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11056 if (spec->data.custom_data.cookie)
11057 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11067 #ifndef DISABLE_REFLECTION_EMIT
11069 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11070 ReflectionMethodBuilder *rmb,
11071 MonoMethodSignature *sig)
11075 MonoMethodWrapper *wrapperm;
11076 MonoMarshalSpec **specs;
11077 MonoReflectionMethodAux *method_aux;
11082 mono_error_init (&error);
11084 * Methods created using a MethodBuilder should have their memory allocated
11085 * inside the image mempool, while dynamic methods should have their memory
11088 dynamic = rmb->refs != NULL;
11089 image = dynamic ? NULL : klass->image;
11092 g_assert (!klass->generic_class);
11094 mono_loader_lock ();
11096 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11097 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11098 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11100 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11102 wrapperm = (MonoMethodWrapper*)m;
11104 m->dynamic = dynamic;
11106 m->flags = rmb->attrs;
11107 m->iflags = rmb->iattrs;
11108 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11110 m->signature = sig;
11111 m->sre_method = TRUE;
11112 m->skip_visibility = rmb->skip_visibility;
11113 if (rmb->table_idx)
11114 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11116 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11117 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11118 m->string_ctor = 1;
11120 m->signature->pinvoke = 1;
11121 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11122 m->signature->pinvoke = 1;
11124 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11126 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11127 g_assert (mono_error_ok (&error));
11128 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11129 g_assert (mono_error_ok (&error));
11131 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11133 if (image_is_dynamic (klass->image))
11134 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11136 mono_loader_unlock ();
11139 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11140 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11141 MonoMethodHeader *header;
11143 gint32 max_stack, i;
11144 gint32 num_locals = 0;
11145 gint32 num_clauses = 0;
11149 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11150 code_size = rmb->ilgen->code_len;
11151 max_stack = rmb->ilgen->max_stack;
11152 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11153 if (rmb->ilgen->ex_handlers)
11154 num_clauses = method_count_clauses (rmb->ilgen);
11157 code = mono_array_addr (rmb->code, guint8, 0);
11158 code_size = mono_array_length (rmb->code);
11159 /* we probably need to run a verifier on the code... */
11169 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11170 header->code_size = code_size;
11171 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11172 memcpy ((char*)header->code, code, code_size);
11173 header->max_stack = max_stack;
11174 header->init_locals = rmb->init_locals;
11175 header->num_locals = num_locals;
11177 for (i = 0; i < num_locals; ++i) {
11178 MonoReflectionLocalBuilder *lb =
11179 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11181 header->locals [i] = image_g_new0 (image, MonoType, 1);
11182 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11185 header->num_clauses = num_clauses;
11187 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11188 rmb->ilgen, num_clauses);
11191 wrapperm->header = header;
11194 if (rmb->generic_params) {
11195 int count = mono_array_length (rmb->generic_params);
11196 MonoGenericContainer *container = rmb->generic_container;
11198 g_assert (container);
11200 container->type_argc = count;
11201 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11202 container->owner.method = m;
11203 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11205 m->is_generic = TRUE;
11206 mono_method_set_generic_container (m, container);
11208 for (i = 0; i < count; i++) {
11209 MonoReflectionGenericParam *gp =
11210 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11211 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11212 container->type_params [i] = *param;
11216 * The method signature might have pointers to generic parameters that belong to other methods.
11217 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11218 * generic parameters.
11220 for (i = 0; i < m->signature->param_count; ++i) {
11221 MonoType *t = m->signature->params [i];
11222 if (t->type == MONO_TYPE_MVAR) {
11223 MonoGenericParam *gparam = t->data.generic_param;
11224 if (gparam->num < count) {
11225 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11226 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11232 if (klass->generic_container) {
11233 container->parent = klass->generic_container;
11234 container->context.class_inst = klass->generic_container->context.class_inst;
11236 container->context.method_inst = mono_get_shared_generic_inst (container);
11240 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11244 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11246 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11247 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11248 for (i = 0; i < rmb->nrefs; ++i)
11249 data [i + 1] = rmb->refs [i];
11254 /* Parameter info */
11257 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11258 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11259 for (i = 0; i <= m->signature->param_count; ++i) {
11260 MonoReflectionParamBuilder *pb;
11261 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11262 if ((i > 0) && (pb->attrs)) {
11263 /* Make a copy since it might point to a shared type structure */
11264 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11265 m->signature->params [i - 1]->attrs = pb->attrs;
11268 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11269 MonoDynamicImage *assembly;
11271 MonoTypeEnum def_type;
11275 if (!method_aux->param_defaults) {
11276 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11277 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11279 assembly = (MonoDynamicImage*)klass->image;
11280 idx = encode_constant (assembly, pb->def_value, &def_type);
11281 /* Copy the data from the blob since it might get realloc-ed */
11282 p = assembly->blob.data + idx;
11283 len = mono_metadata_decode_blob_size (p, &p2);
11285 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11286 method_aux->param_default_types [i] = def_type;
11287 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11291 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11292 g_assert (mono_error_ok (&error));
11295 if (!method_aux->param_cattr)
11296 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11297 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11303 /* Parameter marshalling */
11306 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11307 MonoReflectionParamBuilder *pb;
11308 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11309 if (pb->marshal_info) {
11311 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11312 specs [pb->position] =
11313 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11317 if (specs != NULL) {
11319 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11320 method_aux->param_marshall = specs;
11323 if (image_is_dynamic (klass->image) && method_aux)
11324 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11326 mono_loader_unlock ();
11332 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11335 ReflectionMethodBuilder rmb;
11336 MonoMethodSignature *sig;
11338 mono_loader_lock ();
11339 sig = ctor_builder_to_signature (klass->image, mb);
11340 mono_loader_unlock ();
11342 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, &error))
11343 mono_error_raise_exception (&error); /* FIXME don't raise here*/
11345 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11346 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11348 /* If we are in a generic class, we might be called multiple times from inflate_method */
11349 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11350 /* ilgen is no longer needed */
11354 return mb->mhandle;
11358 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11361 ReflectionMethodBuilder rmb;
11362 MonoMethodSignature *sig;
11364 mono_loader_lock ();
11365 sig = method_builder_to_signature (klass->image, mb);
11366 mono_loader_unlock ();
11368 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
11369 mono_error_raise_exception (&error); /* FIXME don't raise here */
11371 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11372 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11374 /* If we are in a generic class, we might be called multiple times from inflate_method */
11375 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11376 /* ilgen is no longer needed */
11379 return mb->mhandle;
11382 static MonoClassField*
11383 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11385 MonoClassField *field;
11389 field = g_new0 (MonoClassField, 1);
11391 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11392 g_assert (mono_error_ok (&error));
11393 if (fb->attrs || fb->modreq || fb->modopt) {
11394 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11395 field->type->attrs = fb->attrs;
11397 g_assert (image_is_dynamic (klass->image));
11398 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11399 g_free (field->type);
11400 field->type = mono_metadata_type_dup (klass->image, custom);
11403 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11405 if (fb->offset != -1)
11406 field->offset = fb->offset;
11407 field->parent = klass;
11408 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11410 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11417 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11420 MonoReflectionTypeBuilder *tb = NULL;
11421 gboolean is_dynamic = FALSE;
11422 MonoClass *geninst;
11424 mono_loader_lock ();
11426 if (is_sre_type_builder (mono_object_class (type))) {
11427 tb = (MonoReflectionTypeBuilder *) type;
11430 } else if (is_sre_generic_instance (mono_object_class (type))) {
11431 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11432 MonoReflectionType *gtd = rgi->generic_type;
11434 if (is_sre_type_builder (mono_object_class (gtd))) {
11435 tb = (MonoReflectionTypeBuilder *)gtd;
11440 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11441 if (tb && tb->generic_container)
11442 mono_reflection_create_generic_class (tb);
11444 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11445 if (!klass->generic_container) {
11446 mono_loader_unlock ();
11450 if (klass->wastypebuilder) {
11451 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11456 mono_loader_unlock ();
11458 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11460 return &geninst->byval_arg;
11464 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11466 MonoGenericClass *gclass;
11467 MonoGenericInst *inst;
11469 g_assert (klass->generic_container);
11471 inst = mono_metadata_get_generic_inst (type_argc, types);
11472 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11474 return mono_generic_class_get_class (gclass);
11477 MonoReflectionMethod*
11478 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11482 MonoMethod *method, *inflated;
11483 MonoMethodInflated *imethod;
11484 MonoGenericContext tmp_context;
11485 MonoGenericInst *ginst;
11486 MonoType **type_argv;
11489 /*FIXME but this no longer should happen*/
11490 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11491 #ifndef DISABLE_REFLECTION_EMIT
11492 MonoReflectionMethodBuilder *mb = NULL;
11493 MonoReflectionTypeBuilder *tb;
11496 mb = (MonoReflectionMethodBuilder *) rmethod;
11497 tb = (MonoReflectionTypeBuilder *) mb->type;
11498 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11500 method = methodbuilder_to_mono_method (klass, mb);
11502 g_assert_not_reached ();
11506 method = rmethod->method;
11509 klass = method->klass;
11511 if (method->is_inflated)
11512 method = ((MonoMethodInflated *) method)->declaring;
11514 count = mono_method_signature (method)->generic_param_count;
11515 if (count != mono_array_length (types))
11518 type_argv = g_new0 (MonoType *, count);
11519 for (i = 0; i < count; i++) {
11520 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11521 type_argv [i] = mono_reflection_type_get_handle (garg);
11523 ginst = mono_metadata_get_generic_inst (count, type_argv);
11524 g_free (type_argv);
11526 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11527 tmp_context.method_inst = ginst;
11529 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11530 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11531 imethod = (MonoMethodInflated *) inflated;
11533 /*FIXME but I think this is no longer necessary*/
11534 if (image_is_dynamic (method->klass->image)) {
11535 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11537 * This table maps metadata structures representing inflated methods/fields
11538 * to the reflection objects representing their generic definitions.
11540 mono_image_lock ((MonoImage*)image);
11541 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11542 mono_image_unlock ((MonoImage*)image);
11545 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11546 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11548 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11549 mono_error_raise_exception (&error); /* FIXME don't raise here */
11553 #ifndef DISABLE_REFLECTION_EMIT
11555 static MonoMethod *
11556 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11558 MonoMethodInflated *imethod;
11559 MonoGenericContext *context;
11563 * With generic code sharing the klass might not be inflated.
11564 * This can happen because classes inflated with their own
11565 * type arguments are "normalized" to the uninflated class.
11567 if (!klass->generic_class)
11570 context = mono_class_get_context (klass);
11572 if (klass->method.count && klass->methods) {
11573 /* Find the already created inflated method */
11574 for (i = 0; i < klass->method.count; ++i) {
11575 g_assert (klass->methods [i]->is_inflated);
11576 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11579 g_assert (i < klass->method.count);
11580 imethod = (MonoMethodInflated*)klass->methods [i];
11583 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11584 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11587 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11588 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11590 mono_image_lock ((MonoImage*)image);
11591 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11592 mono_image_unlock ((MonoImage*)image);
11594 return (MonoMethod *) imethod;
11597 static MonoMethod *
11598 inflate_method (MonoReflectionType *type, MonoObject *obj)
11600 MonoMethod *method;
11603 MonoClass *type_class = mono_object_class (type);
11605 if (is_sre_generic_instance (type_class)) {
11606 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11607 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11608 } else if (is_sre_type_builder (type_class)) {
11609 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11610 } else if (type->type) {
11611 gklass = mono_class_from_mono_type (type->type);
11612 gklass = mono_class_get_generic_type_definition (gklass);
11614 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11617 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11618 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11619 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11621 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11622 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11623 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11624 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11625 method = ((MonoReflectionMethod *) obj)->method;
11627 method = NULL; /* prevent compiler warning */
11628 g_error ("can't handle type %s", obj->vtable->klass->name);
11631 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11634 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11636 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11638 MonoGenericClass *gclass;
11639 MonoDynamicGenericClass *dgclass;
11640 MonoClass *klass, *gklass;
11644 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11645 klass = mono_class_from_mono_type (gtype);
11646 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11647 gclass = gtype->data.generic_class;
11649 if (!gclass->is_dynamic)
11652 dgclass = (MonoDynamicGenericClass *) gclass;
11654 if (dgclass->initialized)
11657 gklass = gclass->container_class;
11658 mono_class_init (gklass);
11660 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11662 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11663 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11664 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11666 for (i = 0; i < dgclass->count_fields; i++) {
11667 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11668 MonoClassField *field, *inflated_field = NULL;
11670 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11671 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11672 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11673 field = ((MonoReflectionField *) obj)->field;
11675 field = NULL; /* prevent compiler warning */
11676 g_assert_not_reached ();
11679 dgclass->fields [i] = *field;
11680 dgclass->fields [i].parent = klass;
11681 dgclass->fields [i].type = mono_class_inflate_generic_type (
11682 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11683 dgclass->field_generic_types [i] = field->type;
11684 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11685 dgclass->field_objects [i] = obj;
11687 if (inflated_field) {
11688 g_free (inflated_field);
11690 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11694 dgclass->initialized = TRUE;
11698 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11700 MonoDynamicGenericClass *dgclass;
11703 g_assert (gclass->is_dynamic);
11705 dgclass = (MonoDynamicGenericClass *)gclass;
11707 for (i = 0; i < dgclass->count_fields; ++i) {
11708 MonoClassField *field = dgclass->fields + i;
11709 mono_metadata_free_type (field->type);
11710 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11715 fix_partial_generic_class (MonoClass *klass)
11717 MonoClass *gklass = klass->generic_class->container_class;
11718 MonoDynamicGenericClass *dgclass;
11721 if (klass->wastypebuilder)
11724 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11725 if (klass->parent != gklass->parent) {
11727 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11728 if (mono_error_ok (&error)) {
11729 MonoClass *parent = mono_class_from_mono_type (parent_type);
11730 mono_metadata_free_type (parent_type);
11731 if (parent != klass->parent) {
11732 /*fool mono_class_setup_parent*/
11733 klass->supertypes = NULL;
11734 mono_class_setup_parent (klass, parent);
11737 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11738 mono_error_cleanup (&error);
11739 if (gklass->wastypebuilder)
11740 klass->wastypebuilder = TRUE;
11745 if (!dgclass->initialized)
11748 if (klass->method.count != gklass->method.count) {
11749 klass->method.count = gklass->method.count;
11750 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11752 for (i = 0; i < klass->method.count; i++) {
11754 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11755 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11756 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11760 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11761 klass->interface_count = gklass->interface_count;
11762 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11763 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11765 for (i = 0; i < gklass->interface_count; ++i) {
11766 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11767 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11768 mono_metadata_free_type (iface_type);
11770 ensure_runtime_vtable (klass->interfaces [i]);
11772 klass->interfaces_inited = 1;
11775 if (klass->field.count != gklass->field.count) {
11776 klass->field.count = gklass->field.count;
11777 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11779 for (i = 0; i < klass->field.count; i++) {
11780 klass->fields [i] = gklass->fields [i];
11781 klass->fields [i].parent = klass;
11782 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11786 /*We can only finish with this klass once it's parent has as well*/
11787 if (gklass->wastypebuilder)
11788 klass->wastypebuilder = TRUE;
11793 ensure_generic_class_runtime_vtable (MonoClass *klass)
11795 MonoClass *gklass = klass->generic_class->container_class;
11797 ensure_runtime_vtable (gklass);
11799 fix_partial_generic_class (klass);
11803 ensure_runtime_vtable (MonoClass *klass)
11805 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11808 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11811 ensure_runtime_vtable (klass->parent);
11814 num = tb->ctors? mono_array_length (tb->ctors): 0;
11815 num += tb->num_methods;
11816 klass->method.count = num;
11817 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11818 num = tb->ctors? mono_array_length (tb->ctors): 0;
11819 for (i = 0; i < num; ++i)
11820 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11821 num = tb->num_methods;
11823 for (i = 0; i < num; ++i)
11824 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11826 if (tb->interfaces) {
11827 klass->interface_count = mono_array_length (tb->interfaces);
11828 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11829 for (i = 0; i < klass->interface_count; ++i) {
11830 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11831 klass->interfaces [i] = mono_class_from_mono_type (iface);
11832 ensure_runtime_vtable (klass->interfaces [i]);
11834 klass->interfaces_inited = 1;
11836 } else if (klass->generic_class){
11837 ensure_generic_class_runtime_vtable (klass);
11840 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11842 for (i = 0; i < klass->method.count; ++i) {
11843 MonoMethod *im = klass->methods [i];
11844 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11845 im->slot = slot_num++;
11848 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11849 mono_class_setup_interface_offsets (klass);
11850 mono_class_setup_interface_id (klass);
11854 * The generic vtable is needed even if image->run is not set since some
11855 * runtime code like ves_icall_Type_GetMethodsByName depends on
11856 * method->slot being defined.
11860 * tb->methods could not be freed since it is used for determining
11861 * overrides during dynamic vtable construction.
11866 mono_reflection_method_get_handle (MonoObject *method)
11868 MonoClass *klass = mono_object_class (method);
11869 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11870 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11871 return sr_method->method;
11873 if (is_sre_method_builder (klass)) {
11874 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11875 return mb->mhandle;
11877 if (is_sre_method_on_tb_inst (klass)) {
11878 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11879 MonoMethod *result;
11880 /*FIXME move this to a proper method and unify with resolve_object*/
11881 if (m->method_args) {
11882 result = mono_reflection_method_on_tb_inst_get_handle (m);
11884 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11885 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11886 MonoMethod *mono_method;
11888 if (is_sre_method_builder (mono_object_class (m->mb)))
11889 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11890 else if (is_sr_mono_method (mono_object_class (m->mb)))
11891 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11893 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)));
11895 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11900 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11905 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11907 MonoReflectionTypeBuilder *tb;
11909 MonoReflectionMethod *m;
11912 *num_overrides = 0;
11914 g_assert (image_is_dynamic (klass->image));
11916 if (!mono_class_get_ref_info (klass))
11919 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11921 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11925 for (i = 0; i < tb->num_methods; ++i) {
11926 MonoReflectionMethodBuilder *mb =
11927 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11928 if (mb->override_methods)
11929 onum += mono_array_length (mb->override_methods);
11934 *overrides = g_new0 (MonoMethod*, onum * 2);
11937 for (i = 0; i < tb->num_methods; ++i) {
11938 MonoReflectionMethodBuilder *mb =
11939 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11940 if (mb->override_methods) {
11941 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11942 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11944 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11945 (*overrides) [onum * 2 + 1] = mb->mhandle;
11947 g_assert (mb->mhandle);
11955 *num_overrides = onum;
11959 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11961 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11962 MonoReflectionFieldBuilder *fb;
11963 MonoClassField *field;
11964 MonoImage *image = klass->image;
11965 const char *p, *p2;
11967 guint32 len, idx, real_size = 0;
11969 klass->field.count = tb->num_fields;
11970 klass->field.first = 0;
11972 mono_error_init (error);
11974 if (tb->class_size) {
11975 if ((tb->packing_size & 0xffffff00) != 0) {
11976 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11977 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11980 klass->packing_size = tb->packing_size;
11981 real_size = klass->instance_size + tb->class_size;
11984 if (!klass->field.count) {
11985 klass->instance_size = MAX (klass->instance_size, real_size);
11989 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11990 mono_class_alloc_ext (klass);
11991 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11993 This is, guess what, a hack.
11994 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11995 On the static path no field class is resolved, only types are built. This is the right thing to do
11997 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11999 klass->size_inited = 1;
12001 for (i = 0; i < klass->field.count; ++i) {
12002 MonoArray *rva_data;
12003 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12004 field = &klass->fields [i];
12005 field->name = mono_string_to_utf8_image (image, fb->name, error);
12006 if (!mono_error_ok (error))
12009 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12010 field->type->attrs = fb->attrs;
12012 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12015 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12016 char *base = mono_array_addr (rva_data, char, 0);
12017 size_t size = mono_array_length (rva_data);
12018 char *data = (char *)mono_image_alloc (klass->image, size);
12019 memcpy (data, base, size);
12020 klass->ext->field_def_values [i].data = data;
12022 if (fb->offset != -1)
12023 field->offset = fb->offset;
12024 field->parent = klass;
12025 fb->handle = field;
12026 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12028 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12029 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12031 if (fb->def_value) {
12032 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12033 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12034 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12035 /* Copy the data from the blob since it might get realloc-ed */
12036 p = assembly->blob.data + idx;
12037 len = mono_metadata_decode_blob_size (p, &p2);
12039 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12040 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12044 klass->instance_size = MAX (klass->instance_size, real_size);
12045 mono_class_layout_fields (klass);
12049 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12051 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12052 MonoReflectionPropertyBuilder *pb;
12053 MonoImage *image = klass->image;
12054 MonoProperty *properties;
12057 mono_error_init (error);
12060 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12062 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12063 klass->ext->property.first = 0;
12065 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12066 klass->ext->properties = properties;
12067 for (i = 0; i < klass->ext->property.count; ++i) {
12068 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12069 properties [i].parent = klass;
12070 properties [i].attrs = pb->attrs;
12071 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12072 if (!mono_error_ok (error))
12074 if (pb->get_method)
12075 properties [i].get = pb->get_method->mhandle;
12076 if (pb->set_method)
12077 properties [i].set = pb->set_method->mhandle;
12079 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12080 if (pb->def_value) {
12082 const char *p, *p2;
12083 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12084 if (!klass->ext->prop_def_values)
12085 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12086 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12087 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12088 /* Copy the data from the blob since it might get realloc-ed */
12089 p = assembly->blob.data + idx;
12090 len = mono_metadata_decode_blob_size (p, &p2);
12092 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12093 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12098 MonoReflectionEvent *
12099 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12101 MonoEvent *event = g_new0 (MonoEvent, 1);
12104 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12106 event->parent = klass;
12107 event->attrs = eb->attrs;
12108 event->name = mono_string_to_utf8 (eb->name);
12109 if (eb->add_method)
12110 event->add = eb->add_method->mhandle;
12111 if (eb->remove_method)
12112 event->remove = eb->remove_method->mhandle;
12113 if (eb->raise_method)
12114 event->raise = eb->raise_method->mhandle;
12116 #ifndef MONO_SMALL_CONFIG
12117 if (eb->other_methods) {
12119 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12120 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12121 MonoReflectionMethodBuilder *mb =
12122 mono_array_get (eb->other_methods,
12123 MonoReflectionMethodBuilder*, j);
12124 event->other [j] = mb->mhandle;
12129 return mono_event_get_object (mono_object_domain (tb), klass, event);
12133 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12135 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12136 MonoReflectionEventBuilder *eb;
12137 MonoImage *image = klass->image;
12141 mono_error_init (error);
12144 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12146 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12147 klass->ext->event.first = 0;
12149 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12150 klass->ext->events = events;
12151 for (i = 0; i < klass->ext->event.count; ++i) {
12152 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12153 events [i].parent = klass;
12154 events [i].attrs = eb->attrs;
12155 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12156 if (!mono_error_ok (error))
12158 if (eb->add_method)
12159 events [i].add = eb->add_method->mhandle;
12160 if (eb->remove_method)
12161 events [i].remove = eb->remove_method->mhandle;
12162 if (eb->raise_method)
12163 events [i].raise = eb->raise_method->mhandle;
12165 #ifndef MONO_SMALL_CONFIG
12166 if (eb->other_methods) {
12168 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12169 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12170 MonoReflectionMethodBuilder *mb =
12171 mono_array_get (eb->other_methods,
12172 MonoReflectionMethodBuilder*, j);
12173 events [i].other [j] = mb->mhandle;
12177 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12182 remove_instantiations_of_and_ensure_contents (gpointer key,
12184 gpointer user_data)
12186 MonoType *type = (MonoType*)key;
12187 MonoClass *klass = (MonoClass*)user_data;
12189 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12190 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12197 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12199 mono_error_init (error);
12205 for (i = 0; i < mono_array_length (arr); ++i) {
12206 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12207 if (!mono_error_ok (error))
12212 MonoReflectionType*
12213 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12217 MonoDomain* domain;
12218 MonoReflectionType* res;
12221 domain = mono_object_domain (tb);
12222 klass = mono_class_from_mono_type (tb->type.type);
12225 * Check for user defined Type subclasses.
12227 RESOLVE_TYPE (tb->parent, &error);
12228 mono_error_raise_exception (&error); /* FIXME don't raise here */
12229 check_array_for_usertypes (tb->interfaces, &error);
12230 mono_error_raise_exception (&error); /*FIXME don't raise here */
12232 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12233 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12235 RESOLVE_TYPE (fb->type, &error);
12236 mono_error_raise_exception (&error); /* FIXME don't raise here */
12237 check_array_for_usertypes (fb->modreq, &error);
12238 mono_error_raise_exception (&error); /*FIXME don't raise here */
12239 check_array_for_usertypes (fb->modopt, &error);
12240 mono_error_raise_exception (&error); /*FIXME don't raise here */
12241 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12242 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12243 mono_error_raise_exception (&error); /* FIXME don't raise here */
12249 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12250 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12252 RESOLVE_TYPE (mb->rtype, &error);
12253 mono_error_raise_exception (&error); /* FIXME don't raise here */
12254 check_array_for_usertypes (mb->return_modreq, &error);
12255 mono_error_raise_exception (&error); /*FIXME don't raise here */
12256 check_array_for_usertypes (mb->return_modopt, &error);
12257 mono_error_raise_exception (&error); /*FIXME don't raise here */
12258 check_array_for_usertypes (mb->parameters, &error);
12259 mono_error_raise_exception (&error); /*FIXME don't raise here */
12260 if (mb->param_modreq)
12261 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12262 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12263 mono_error_raise_exception (&error); /*FIXME don't raise here */
12265 if (mb->param_modopt)
12266 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12267 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12268 mono_error_raise_exception (&error); /*FIXME don't raise here */
12274 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12275 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12277 check_array_for_usertypes (mb->parameters, &error);
12278 mono_error_raise_exception (&error); /*FIXME don't raise here */
12279 if (mb->param_modreq)
12280 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12281 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12282 mono_error_raise_exception (&error); /*FIXME don't raise here */
12284 if (mb->param_modopt)
12285 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12286 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12287 mono_error_raise_exception (&error); /*FIXME don't raise here */
12293 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12296 * we need to lock the domain because the lock will be taken inside
12297 * So, we need to keep the locking order correct.
12299 mono_loader_lock ();
12300 mono_domain_lock (domain);
12301 if (klass->wastypebuilder) {
12302 mono_domain_unlock (domain);
12303 mono_loader_unlock ();
12305 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12306 mono_error_raise_exception (&error); /* FIXME don't raise here */
12311 * Fields to set in klass:
12312 * the various flags: delegate/unicode/contextbound etc.
12314 klass->flags = tb->attrs;
12315 klass->has_cctor = 1;
12316 klass->has_finalize = 1;
12317 klass->has_finalize_inited = 1;
12319 mono_class_setup_parent (klass, klass->parent);
12320 /* fool mono_class_setup_supertypes */
12321 klass->supertypes = NULL;
12322 mono_class_setup_supertypes (klass);
12323 mono_class_setup_mono_type (klass);
12326 if (!((MonoDynamicImage*)klass->image)->run) {
12327 if (klass->generic_container) {
12328 /* FIXME: The code below can't handle generic classes */
12329 klass->wastypebuilder = TRUE;
12330 mono_loader_unlock ();
12331 mono_domain_unlock (domain);
12333 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12334 mono_error_raise_exception (&error); /* FIXME don't raise here */
12341 /* enums are done right away */
12342 if (!klass->enumtype)
12343 ensure_runtime_vtable (klass);
12345 if (tb->subtypes) {
12346 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12347 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12348 mono_class_alloc_ext (klass);
12349 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)));
12353 klass->nested_classes_inited = TRUE;
12355 /* fields and object layout */
12356 if (klass->parent) {
12357 if (!klass->parent->size_inited)
12358 mono_class_init (klass->parent);
12359 klass->instance_size = klass->parent->instance_size;
12360 klass->sizes.class_size = 0;
12361 klass->min_align = klass->parent->min_align;
12362 /* if the type has no fields we won't call the field_setup
12363 * routine which sets up klass->has_references.
12365 klass->has_references |= klass->parent->has_references;
12367 klass->instance_size = sizeof (MonoObject);
12368 klass->min_align = 1;
12371 /* FIXME: handle packing_size and instance_size */
12372 typebuilder_setup_fields (klass, &error);
12373 if (!mono_error_ok (&error))
12375 typebuilder_setup_properties (klass, &error);
12376 if (!mono_error_ok (&error))
12379 typebuilder_setup_events (klass, &error);
12380 if (!mono_error_ok (&error))
12383 klass->wastypebuilder = TRUE;
12386 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12387 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12388 * we want to return normal System.MonoType objects, so clear these out from the cache.
12390 * Together with this we must ensure the contents of all instances to match the created type.
12392 if (domain->type_hash && klass->generic_container)
12393 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12395 mono_domain_unlock (domain);
12396 mono_loader_unlock ();
12398 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12399 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12400 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12403 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12404 mono_error_raise_exception (&error); /* FIXME don't raise here */
12406 g_assert (res != (MonoReflectionType*)tb);
12411 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12412 klass->wastypebuilder = TRUE;
12413 mono_domain_unlock (domain);
12414 mono_loader_unlock ();
12415 mono_error_raise_exception (&error);
12420 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12422 MonoGenericParamFull *param;
12427 image = &gparam->tbuilder->module->dynamic_image->image;
12429 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12431 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12432 g_assert (mono_error_ok (&error));
12433 param->param.num = gparam->index;
12435 if (gparam->mbuilder) {
12436 if (!gparam->mbuilder->generic_container) {
12437 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12438 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12439 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12440 gparam->mbuilder->generic_container->is_method = TRUE;
12442 * Cannot set owner.method, since the MonoMethod is not created yet.
12443 * Set the image field instead, so type_in_image () works.
12445 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12446 gparam->mbuilder->generic_container->owner.image = klass->image;
12448 param->param.owner = gparam->mbuilder->generic_container;
12449 } else if (gparam->tbuilder) {
12450 if (!gparam->tbuilder->generic_container) {
12451 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12452 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12453 gparam->tbuilder->generic_container->owner.klass = klass;
12455 param->param.owner = gparam->tbuilder->generic_container;
12458 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12460 gparam->type.type = &pklass->byval_arg;
12462 mono_class_set_ref_info (pklass, gparam);
12463 mono_image_append_class_to_reflection_info_set (pklass);
12467 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12470 MonoReflectionModuleBuilder *module = sig->module;
12471 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12472 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12477 check_array_for_usertypes (sig->arguments, &error);
12478 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12480 sigbuffer_init (&buf, 32);
12482 sigbuffer_add_value (&buf, 0x07);
12483 sigbuffer_add_value (&buf, na);
12484 if (assembly != NULL){
12485 for (i = 0; i < na; ++i) {
12486 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12487 encode_reflection_type (assembly, type, &buf);
12491 buflen = buf.p - buf.buf;
12492 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12493 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12494 sigbuffer_free (&buf);
12500 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12503 MonoDynamicImage *assembly = sig->module->dynamic_image;
12504 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12509 check_array_for_usertypes (sig->arguments, &error);
12510 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12512 sigbuffer_init (&buf, 32);
12514 sigbuffer_add_value (&buf, 0x06);
12515 for (i = 0; i < na; ++i) {
12516 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12517 encode_reflection_type (assembly, type, &buf);
12520 buflen = buf.p - buf.buf;
12521 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12522 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12523 sigbuffer_free (&buf);
12529 MonoMethod *handle;
12530 MonoDomain *domain;
12531 } DynamicMethodReleaseData;
12534 * The runtime automatically clean up those after finalization.
12536 static MonoReferenceQueue *dynamic_method_queue;
12539 free_dynamic_method (void *dynamic_method)
12541 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12542 MonoDomain *domain = data->domain;
12543 MonoMethod *method = data->handle;
12546 mono_domain_lock (domain);
12547 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12548 g_hash_table_remove (domain->method_to_dyn_method, method);
12549 mono_domain_unlock (domain);
12550 g_assert (dis_link);
12551 mono_gchandle_free (dis_link);
12553 mono_runtime_free_method (domain, method);
12558 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12560 MonoReferenceQueue *queue;
12561 MonoMethod *handle;
12562 DynamicMethodReleaseData *release_data;
12563 ReflectionMethodBuilder rmb;
12564 MonoMethodSignature *sig;
12566 MonoDomain *domain;
12570 if (mono_runtime_is_shutting_down ())
12571 mono_raise_exception (mono_get_exception_invalid_operation (""));
12573 if (!(queue = dynamic_method_queue)) {
12574 mono_loader_lock ();
12575 if (!(queue = dynamic_method_queue))
12576 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12577 mono_loader_unlock ();
12580 sig = dynamic_method_to_signature (mb);
12582 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12585 * Resolve references.
12588 * Every second entry in the refs array is reserved for storing handle_class,
12589 * which is needed by the ldtoken implementation in the JIT.
12591 rmb.nrefs = mb->nrefs;
12592 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12593 for (i = 0; i < mb->nrefs; i += 2) {
12594 MonoClass *handle_class;
12596 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12598 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12599 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12601 * The referenced DynamicMethod should already be created by the managed
12602 * code, except in the case of circular references. In that case, we store
12603 * method in the refs array, and fix it up later when the referenced
12604 * DynamicMethod is created.
12606 if (method->mhandle) {
12607 ref = method->mhandle;
12609 /* FIXME: GC object stored in unmanaged memory */
12612 /* FIXME: GC object stored in unmanaged memory */
12613 method->referenced_by = g_slist_append (method->referenced_by, mb);
12615 handle_class = mono_defaults.methodhandle_class;
12617 MonoException *ex = NULL;
12618 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12620 ex = mono_get_exception_type_load (NULL, NULL);
12621 else if (mono_security_core_clr_enabled ())
12622 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12626 mono_raise_exception (ex);
12631 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12632 rmb.refs [i + 1] = handle_class;
12635 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12637 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12638 release_data = g_new (DynamicMethodReleaseData, 1);
12639 release_data->handle = handle;
12640 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12641 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12642 g_free (release_data);
12644 /* Fix up refs entries pointing at us */
12645 for (l = mb->referenced_by; l; l = l->next) {
12646 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12647 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12650 g_assert (method->mhandle);
12652 data = (gpointer*)wrapper->method_data;
12653 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12654 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12655 data [i + 1] = mb->mhandle;
12658 g_slist_free (mb->referenced_by);
12662 /* ilgen is no longer needed */
12665 domain = mono_domain_get ();
12666 mono_domain_lock (domain);
12667 if (!domain->method_to_dyn_method)
12668 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12669 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12670 mono_domain_unlock (domain);
12673 #endif /* DISABLE_REFLECTION_EMIT */
12677 * mono_reflection_is_valid_dynamic_token:
12679 * Returns TRUE if token is valid.
12683 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12685 return lookup_dyn_token (image, token) != NULL;
12688 MonoMethodSignature *
12689 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12691 MonoMethodSignature *sig;
12692 g_assert (image_is_dynamic (image));
12694 mono_error_init (error);
12696 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12700 return mono_method_signature_checked (method, error);
12703 #ifndef DISABLE_REFLECTION_EMIT
12706 * mono_reflection_lookup_dynamic_token:
12708 * Finish the Builder object pointed to by TOKEN and return the corresponding
12709 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12710 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12713 * LOCKING: Take the loader lock
12716 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12718 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12722 obj = lookup_dyn_token (assembly, token);
12725 g_error ("Could not find required dynamic token 0x%08x", token);
12731 handle_class = &klass;
12732 return resolve_object (image, obj, handle_class, context);
12736 * ensure_complete_type:
12738 * Ensure that KLASS is completed if it is a dynamic type, or references
12742 ensure_complete_type (MonoClass *klass)
12744 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12745 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12747 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12749 // Asserting here could break a lot of code
12750 //g_assert (klass->wastypebuilder);
12753 if (klass->generic_class) {
12754 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12757 for (i = 0; i < inst->type_argc; ++i) {
12758 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12764 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12766 gpointer result = NULL;
12768 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12769 result = mono_string_intern ((MonoString*)obj);
12770 *handle_class = mono_defaults.string_class;
12772 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12773 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12774 MonoClass *mc = mono_class_from_mono_type (type);
12775 if (!mono_class_init (mc))
12776 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12779 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12780 result = mono_class_from_mono_type (inflated);
12781 mono_metadata_free_type (inflated);
12783 result = mono_class_from_mono_type (type);
12785 *handle_class = mono_defaults.typehandle_class;
12787 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12788 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12789 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12790 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12791 result = ((MonoReflectionMethod*)obj)->method;
12794 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12795 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12797 *handle_class = mono_defaults.methodhandle_class;
12799 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12800 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12801 result = mb->mhandle;
12803 /* Type is not yet created */
12804 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12806 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12809 * Hopefully this has been filled in by calling CreateType() on the
12813 * TODO: This won't work if the application finishes another
12814 * TypeBuilder instance instead of this one.
12816 result = mb->mhandle;
12820 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12821 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12823 *handle_class = mono_defaults.methodhandle_class;
12824 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12825 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12827 result = cb->mhandle;
12829 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12831 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12832 result = cb->mhandle;
12836 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12837 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12839 *handle_class = mono_defaults.methodhandle_class;
12840 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12841 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12843 ensure_complete_type (field->parent);
12845 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12846 MonoClass *klass = mono_class_from_mono_type (inflated);
12847 MonoClassField *inflated_field;
12848 gpointer iter = NULL;
12849 mono_metadata_free_type (inflated);
12850 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12851 if (!strcmp (field->name, inflated_field->name))
12854 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12855 result = inflated_field;
12859 *handle_class = mono_defaults.fieldhandle_class;
12861 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12862 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12863 result = fb->handle;
12866 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12868 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12869 result = fb->handle;
12872 if (fb->handle && fb->handle->parent->generic_container) {
12873 MonoClass *klass = fb->handle->parent;
12874 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12875 MonoClass *inflated = mono_class_from_mono_type (type);
12877 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12879 mono_metadata_free_type (type);
12881 *handle_class = mono_defaults.fieldhandle_class;
12882 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12883 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12884 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12887 klass = type->data.klass;
12888 if (klass->wastypebuilder) {
12889 /* Already created */
12893 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12894 result = type->data.klass;
12897 *handle_class = mono_defaults.typehandle_class;
12898 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12899 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12900 MonoMethodSignature *sig;
12903 if (helper->arguments)
12904 nargs = mono_array_length (helper->arguments);
12908 sig = mono_metadata_signature_alloc (image, nargs);
12909 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12910 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12912 if (helper->unmanaged_call_conv) { /* unmanaged */
12913 sig->call_convention = helper->unmanaged_call_conv - 1;
12914 sig->pinvoke = TRUE;
12915 } else if (helper->call_conv & 0x02) {
12916 sig->call_convention = MONO_CALL_VARARG;
12918 sig->call_convention = MONO_CALL_DEFAULT;
12921 sig->param_count = nargs;
12922 /* TODO: Copy type ? */
12923 sig->ret = helper->return_type->type;
12924 for (i = 0; i < nargs; ++i)
12925 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12928 *handle_class = NULL;
12929 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12930 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12931 /* Already created by the managed code */
12932 g_assert (method->mhandle);
12933 result = method->mhandle;
12934 *handle_class = mono_defaults.methodhandle_class;
12935 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12936 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12937 type = mono_class_inflate_generic_type (type, context);
12938 result = mono_class_from_mono_type (type);
12939 *handle_class = mono_defaults.typehandle_class;
12941 mono_metadata_free_type (type);
12942 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12943 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12944 type = mono_class_inflate_generic_type (type, context);
12945 result = mono_class_from_mono_type (type);
12946 *handle_class = mono_defaults.typehandle_class;
12948 mono_metadata_free_type (type);
12949 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12950 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12951 MonoClass *inflated;
12953 MonoClassField *field;
12955 if (is_sre_field_builder (mono_object_class (f->fb)))
12956 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12957 else if (is_sr_mono_field (mono_object_class (f->fb)))
12958 field = ((MonoReflectionField*)f->fb)->field;
12960 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)));
12962 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12963 inflated = mono_class_from_mono_type (type);
12965 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12966 ensure_complete_type (field->parent);
12968 mono_metadata_free_type (type);
12969 *handle_class = mono_defaults.fieldhandle_class;
12970 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12971 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12972 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12973 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12974 MonoMethod *method;
12976 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12977 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12978 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12979 method = ((MonoReflectionMethod *)c->cb)->method;
12981 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)));
12983 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12984 *handle_class = mono_defaults.methodhandle_class;
12985 mono_metadata_free_type (type);
12986 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12987 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12988 if (m->method_args) {
12989 result = mono_reflection_method_on_tb_inst_get_handle (m);
12992 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12993 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12996 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12997 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12998 MonoMethod *method;
13000 if (is_sre_method_builder (mono_object_class (m->mb)))
13001 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13002 else if (is_sr_mono_method (mono_object_class (m->mb)))
13003 method = ((MonoReflectionMethod *)m->mb)->method;
13005 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)));
13007 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13008 mono_metadata_free_type (type);
13010 *handle_class = mono_defaults.methodhandle_class;
13011 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13012 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13015 MonoMethod *method;
13019 mtype = mono_reflection_type_get_handle (m->parent);
13020 klass = mono_class_from_mono_type (mtype);
13022 /* Find the method */
13024 name = mono_string_to_utf8 (m->name);
13026 while ((method = mono_class_get_methods (klass, &iter))) {
13027 if (!strcmp (method->name, name))
13034 // FIXME: Check parameters/return value etc. match
13037 *handle_class = mono_defaults.methodhandle_class;
13038 } else if (is_sre_array (mono_object_get_class(obj)) ||
13039 is_sre_byref (mono_object_get_class(obj)) ||
13040 is_sre_pointer (mono_object_get_class(obj))) {
13041 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13042 MonoType *type = mono_reflection_type_get_handle (ref_type);
13045 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13046 result = mono_class_from_mono_type (inflated);
13047 mono_metadata_free_type (inflated);
13049 result = mono_class_from_mono_type (type);
13051 *handle_class = mono_defaults.typehandle_class;
13053 g_print ("%s\n", obj->vtable->klass->name);
13054 g_assert_not_reached ();
13059 #else /* DISABLE_REFLECTION_EMIT */
13062 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13064 g_assert_not_reached ();
13069 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13071 g_assert_not_reached ();
13075 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13077 g_assert_not_reached ();
13081 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13083 g_assert_not_reached ();
13087 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13089 g_assert_not_reached ();
13093 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13095 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13099 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13101 g_assert_not_reached ();
13105 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13107 g_assert_not_reached ();
13110 MonoReflectionModule *
13111 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13113 g_assert_not_reached ();
13118 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13120 g_assert_not_reached ();
13125 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13127 g_assert_not_reached ();
13132 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13133 gboolean create_open_instance, gboolean register_token)
13135 g_assert_not_reached ();
13140 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13145 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13147 g_assert_not_reached ();
13151 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13154 *num_overrides = 0;
13157 MonoReflectionEvent *
13158 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13160 g_assert_not_reached ();
13164 MonoReflectionType*
13165 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13167 g_assert_not_reached ();
13172 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13174 g_assert_not_reached ();
13178 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13180 g_assert_not_reached ();
13185 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13187 g_assert_not_reached ();
13192 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13197 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13203 mono_reflection_type_get_handle (MonoReflectionType* ref)
13211 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13213 g_assert_not_reached ();
13216 #endif /* DISABLE_REFLECTION_EMIT */
13218 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13219 const static guint32 declsec_flags_map[] = {
13220 0x00000000, /* empty */
13221 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13222 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13223 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13224 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13225 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13226 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13227 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13228 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13229 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13230 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13231 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13232 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13233 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13234 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13235 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13236 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13237 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13238 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13242 * Returns flags that includes all available security action associated to the handle.
13243 * @token: metadata token (either for a class or a method)
13244 * @image: image where resides the metadata.
13247 mono_declsec_get_flags (MonoImage *image, guint32 token)
13249 int index = mono_metadata_declsec_from_index (image, token);
13250 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13251 guint32 result = 0;
13255 /* HasSecurity can be present for other, not specially encoded, attributes,
13256 e.g. SuppressUnmanagedCodeSecurityAttribute */
13260 for (i = index; i < t->rows; i++) {
13261 guint32 cols [MONO_DECL_SECURITY_SIZE];
13263 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13264 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13267 action = cols [MONO_DECL_SECURITY_ACTION];
13268 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13269 result |= declsec_flags_map [action];
13271 g_assert_not_reached ();
13278 * Get the security actions (in the form of flags) associated with the specified method.
13280 * @method: The method for which we want the declarative security flags.
13281 * Return the declarative security flags for the method (only).
13283 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13284 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13287 mono_declsec_flags_from_method (MonoMethod *method)
13289 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13290 /* FIXME: No cache (for the moment) */
13291 guint32 idx = mono_method_get_index (method);
13292 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13293 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13294 return mono_declsec_get_flags (method->klass->image, idx);
13300 * Get the security actions (in the form of flags) associated with the specified class.
13302 * @klass: The class for which we want the declarative security flags.
13303 * Return the declarative security flags for the class.
13305 * Note: We cache the flags inside the MonoClass structure as this will get
13306 * called very often (at least for each method).
13309 mono_declsec_flags_from_class (MonoClass *klass)
13311 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13312 if (!klass->ext || !klass->ext->declsec_flags) {
13315 idx = mono_metadata_token_index (klass->type_token);
13316 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13317 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13318 mono_loader_lock ();
13319 mono_class_alloc_ext (klass);
13320 mono_loader_unlock ();
13321 /* we cache the flags on classes */
13322 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13324 return klass->ext->declsec_flags;
13330 * Get the security actions (in the form of flags) associated with the specified assembly.
13332 * @assembly: The assembly for which we want the declarative security flags.
13333 * Return the declarative security flags for the assembly.
13336 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13338 guint32 idx = 1; /* there is only one assembly */
13339 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13340 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13341 return mono_declsec_get_flags (assembly->image, idx);
13346 * Fill actions for the specific index (which may either be an encoded class token or
13347 * an encoded method token) from the metadata image.
13348 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13351 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13352 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13354 MonoBoolean result = FALSE;
13356 guint32 cols [MONO_DECL_SECURITY_SIZE];
13357 int index = mono_metadata_declsec_from_index (image, token);
13360 t = &image->tables [MONO_TABLE_DECLSECURITY];
13361 for (i = index; i < t->rows; i++) {
13362 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13364 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13367 /* if present only replace (class) permissions with method permissions */
13368 /* if empty accept either class or method permissions */
13369 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13370 if (!actions->demand.blob) {
13371 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13372 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13373 actions->demand.blob = (char*) (blob + 2);
13374 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13377 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13378 if (!actions->noncasdemand.blob) {
13379 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13380 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13381 actions->noncasdemand.blob = (char*) (blob + 2);
13382 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13385 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13386 if (!actions->demandchoice.blob) {
13387 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13388 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13389 actions->demandchoice.blob = (char*) (blob + 2);
13390 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13400 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13401 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13403 guint32 idx = mono_metadata_token_index (klass->type_token);
13404 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13405 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13406 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13410 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13411 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13413 guint32 idx = mono_method_get_index (method);
13414 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13415 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13416 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13420 * Collect all actions (that requires to generate code in mini) assigned for
13421 * the specified method.
13422 * Note: Don't use the content of actions if the function return FALSE.
13425 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13427 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13428 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13429 MonoBoolean result = FALSE;
13432 /* quick exit if no declarative security is present in the metadata */
13433 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13436 /* we want the original as the wrapper is "free" of the security informations */
13437 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13438 method = mono_marshal_method_from_wrapper (method);
13443 /* First we look for method-level attributes */
13444 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13445 mono_class_init (method->klass);
13446 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13448 result = mono_declsec_get_method_demands_params (method, demands,
13449 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13452 /* Here we use (or create) the class declarative cache to look for demands */
13453 flags = mono_declsec_flags_from_class (method->klass);
13454 if (flags & mask) {
13456 mono_class_init (method->klass);
13457 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13459 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13460 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13463 /* The boolean return value is used as a shortcut in case nothing needs to
13464 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13470 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13472 * Note: Don't use the content of actions if the function return FALSE.
13475 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13477 MonoBoolean result = FALSE;
13480 /* quick exit if no declarative security is present in the metadata */
13481 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13484 /* we want the original as the wrapper is "free" of the security informations */
13485 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13486 method = mono_marshal_method_from_wrapper (method);
13491 /* results are independant - zeroize both */
13492 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13493 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13495 /* First we look for method-level attributes */
13496 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13497 mono_class_init (method->klass);
13499 result = mono_declsec_get_method_demands_params (method, cmethod,
13500 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13503 /* Here we use (or create) the class declarative cache to look for demands */
13504 flags = mono_declsec_flags_from_class (method->klass);
13505 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13506 mono_class_init (method->klass);
13508 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13509 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13516 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13518 * @klass The inherited class - this is the class that provides the security check (attributes)
13520 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13522 * Note: Don't use the content of actions if the function return FALSE.
13525 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13527 MonoBoolean result = FALSE;
13530 /* quick exit if no declarative security is present in the metadata */
13531 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13534 /* Here we use (or create) the class declarative cache to look for demands */
13535 flags = mono_declsec_flags_from_class (klass);
13536 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13537 mono_class_init (klass);
13538 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13540 result |= mono_declsec_get_class_demands_params (klass, demands,
13541 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13548 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13550 * Note: Don't use the content of actions if the function return FALSE.
13553 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13555 /* quick exit if no declarative security is present in the metadata */
13556 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13559 /* we want the original as the wrapper is "free" of the security informations */
13560 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13561 method = mono_marshal_method_from_wrapper (method);
13566 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13567 mono_class_init (method->klass);
13568 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13570 return mono_declsec_get_method_demands_params (method, demands,
13571 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13578 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13580 guint32 cols [MONO_DECL_SECURITY_SIZE];
13584 int index = mono_metadata_declsec_from_index (image, token);
13588 t = &image->tables [MONO_TABLE_DECLSECURITY];
13589 for (i = index; i < t->rows; i++) {
13590 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13592 /* shortcut - index are ordered */
13593 if (token != cols [MONO_DECL_SECURITY_PARENT])
13596 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13597 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13598 entry->blob = (char*) (metadata + 2);
13599 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13608 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13610 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13611 guint32 idx = mono_method_get_index (method);
13612 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13613 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13614 return get_declsec_action (method->klass->image, idx, action, entry);
13620 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13623 guint32 flags = mono_declsec_flags_from_class (klass);
13624 if (declsec_flags_map [action] & flags) {
13625 guint32 idx = mono_metadata_token_index (klass->type_token);
13626 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13627 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13628 return get_declsec_action (klass->image, idx, action, entry);
13634 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13636 guint32 idx = 1; /* there is only one assembly */
13637 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13638 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13640 return get_declsec_action (assembly->image, idx, action, entry);
13644 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13647 MonoObject *res, *exc;
13649 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13650 static MonoMethod *method = NULL;
13652 if (!System_Reflection_Emit_TypeBuilder) {
13653 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13654 g_assert (System_Reflection_Emit_TypeBuilder);
13656 if (method == NULL) {
13657 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13662 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13663 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13665 g_assert (mono_class_get_ref_info (klass));
13666 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13668 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13669 mono_error_raise_exception (&error); /* FIXME don't raise here */
13671 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13673 if (exc || !mono_error_ok (&error)) {
13674 mono_error_cleanup (&error);
13677 return *(MonoBoolean*)mono_object_unbox (res);
13681 * mono_reflection_type_get_type:
13682 * @reftype: the System.Type object
13684 * Returns the MonoType* associated with the C# System.Type object @reftype.
13687 mono_reflection_type_get_type (MonoReflectionType *reftype)
13689 g_assert (reftype);
13691 return mono_reflection_type_get_handle (reftype);
13695 * mono_reflection_assembly_get_assembly:
13696 * @refassembly: the System.Reflection.Assembly object
13698 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13701 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13703 g_assert (refassembly);
13705 return refassembly->assembly;