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);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, 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 (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1150 MONO_REQ_GC_UNSAFE_MODE;
1155 gint32 max_stack, i;
1156 gint32 num_locals = 0;
1157 gint32 num_exception = 0;
1160 char fat_header [12];
1162 guint16 short_value;
1163 guint32 local_sig = 0;
1164 guint32 header_size = 12;
1167 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1168 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1172 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1174 code = mb->ilgen->code;
1175 code_size = mb->ilgen->code_len;
1176 max_stack = mb->ilgen->max_stack;
1177 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1178 if (mb->ilgen->ex_handlers)
1179 num_exception = method_count_clauses (mb->ilgen);
1183 char *name = mono_string_to_utf8 (mb->name);
1184 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1185 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1188 mono_raise_exception (exception);
1191 code_size = mono_array_length (code);
1192 max_stack = 8; /* we probably need to run a verifier on the code... */
1195 stream_data_align (&assembly->code);
1197 /* check for exceptions, maxstack, locals */
1198 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1200 if (code_size < 64 && !(code_size & 1)) {
1201 flags = (code_size << 2) | 0x2;
1202 } else if (code_size < 32 && (code_size & 1)) {
1203 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1207 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1208 /* add to the fixup todo list */
1209 if (mb->ilgen && mb->ilgen->num_token_fixups)
1210 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1211 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1212 return assembly->text_rva + idx;
1216 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1218 * FIXME: need to set also the header size in fat_flags.
1219 * (and more sects and init locals flags)
1223 fat_flags |= METHOD_HEADER_MORE_SECTS;
1224 if (mb->init_locals)
1225 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1226 fat_header [0] = fat_flags;
1227 fat_header [1] = (header_size / 4 ) << 4;
1228 short_value = GUINT16_TO_LE (max_stack);
1229 memcpy (fat_header + 2, &short_value, 2);
1230 int_value = GUINT32_TO_LE (code_size);
1231 memcpy (fat_header + 4, &int_value, 4);
1232 int_value = GUINT32_TO_LE (local_sig);
1233 memcpy (fat_header + 8, &int_value, 4);
1234 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1235 /* add to the fixup todo list */
1236 if (mb->ilgen && mb->ilgen->num_token_fixups)
1237 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1239 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1240 if (num_exception) {
1241 unsigned char sheader [4];
1242 MonoILExceptionInfo * ex_info;
1243 MonoILExceptionBlock * ex_block;
1246 stream_data_align (&assembly->code);
1247 /* always use fat format for now */
1248 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1249 num_exception *= 6 * sizeof (guint32);
1250 num_exception += 4; /* include the size of the header */
1251 sheader [1] = num_exception & 0xff;
1252 sheader [2] = (num_exception >> 8) & 0xff;
1253 sheader [3] = (num_exception >> 16) & 0xff;
1254 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1255 /* fat header, so we are already aligned */
1257 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1258 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1259 if (ex_info->handlers) {
1260 int finally_start = ex_info->start + ex_info->len;
1261 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1263 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1265 val = GUINT32_TO_LE (ex_block->type);
1266 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1268 val = GUINT32_TO_LE (ex_info->start);
1269 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1270 /* need fault, too, probably */
1271 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1272 val = GUINT32_TO_LE (finally_start - ex_info->start);
1274 val = GUINT32_TO_LE (ex_info->len);
1275 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276 /* handler offset */
1277 val = GUINT32_TO_LE (ex_block->start);
1278 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1280 val = GUINT32_TO_LE (ex_block->len);
1281 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1282 finally_start = ex_block->start + ex_block->len;
1283 if (ex_block->extype) {
1284 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1286 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1287 val = ex_block->filter_offset;
1291 val = GUINT32_TO_LE (val);
1292 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293 /*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",
1294 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);*/
1297 g_error ("No clauses for ex info block %d", i);
1301 return assembly->text_rva + idx;
1305 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1307 MONO_REQ_GC_NEUTRAL_MODE;
1310 MonoDynamicTable *table;
1313 table = &assembly->tables [table_idx];
1315 g_assert (col < table->columns);
1317 values = table->values + table->columns;
1318 for (i = 1; i <= table->rows; ++i) {
1319 if (values [col] == token)
1321 values += table->columns;
1327 * LOCKING: Acquires the loader lock.
1329 static MonoCustomAttrInfo*
1330 lookup_custom_attr (MonoImage *image, gpointer member)
1332 MONO_REQ_GC_NEUTRAL_MODE;
1334 MonoCustomAttrInfo* res;
1336 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1341 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1347 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1349 MONO_REQ_GC_UNSAFE_MODE;
1351 /* FIXME: Need to do more checks */
1352 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1353 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1355 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1362 static MonoCustomAttrInfo*
1363 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1365 MONO_REQ_GC_UNSAFE_MODE;
1367 int i, index, count, not_visible;
1368 MonoCustomAttrInfo *ainfo;
1369 MonoReflectionCustomAttr *cattr;
1373 /* FIXME: check in assembly the Run flag is set */
1375 count = mono_array_length (cattrs);
1377 /* Skip nonpublic attributes since MS.NET seems to do the same */
1378 /* FIXME: This needs to be done more globally */
1380 for (i = 0; i < count; ++i) {
1381 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1382 if (!custom_attr_visible (image, cattr))
1385 count -= not_visible;
1387 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1389 ainfo->image = image;
1390 ainfo->num_attrs = count;
1391 ainfo->cached = alloc_img != NULL;
1393 for (i = 0; i < count; ++i) {
1394 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1395 if (custom_attr_visible (image, cattr)) {
1396 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1397 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1398 ainfo->attrs [index].ctor = cattr->ctor->method;
1399 ainfo->attrs [index].data = saved;
1400 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1408 #ifndef DISABLE_REFLECTION_EMIT
1410 * LOCKING: Acquires the loader lock.
1413 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1415 MONO_REQ_GC_UNSAFE_MODE;
1417 MonoCustomAttrInfo *ainfo, *tmp;
1419 if (!cattrs || !mono_array_length (cattrs))
1422 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1424 mono_loader_lock ();
1425 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1427 mono_custom_attrs_free (tmp);
1428 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1429 mono_loader_unlock ();
1435 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1437 MONO_REQ_GC_NEUTRAL_MODE;
1444 * idx is the table index of the object
1445 * type is one of MONO_CUSTOM_ATTR_*
1448 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1450 MONO_REQ_GC_UNSAFE_MODE;
1452 MonoDynamicTable *table;
1453 MonoReflectionCustomAttr *cattr;
1455 guint32 count, i, token;
1457 char *p = blob_size;
1459 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1462 count = mono_array_length (cattrs);
1463 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1464 table->rows += count;
1465 alloc_table (table, table->rows);
1466 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1467 idx <<= MONO_CUSTOM_ATTR_BITS;
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1472 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1473 type = mono_metadata_token_index (token);
1474 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1475 switch (mono_metadata_token_table (token)) {
1476 case MONO_TABLE_METHOD:
1477 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1479 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1480 * method, not the one returned by mono_image_create_token ().
1482 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1484 case MONO_TABLE_MEMBERREF:
1485 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1488 g_warning ("got wrong token in custom attr");
1491 values [MONO_CUSTOM_ATTR_TYPE] = type;
1493 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1494 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1495 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1496 values += MONO_CUSTOM_ATTR_SIZE;
1502 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoDynamicTable *table;
1508 guint32 count, i, idx;
1509 MonoReflectionPermissionSet *perm;
1514 count = mono_array_length (permissions);
1515 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1516 table->rows += count;
1517 alloc_table (table, table->rows);
1519 for (i = 0; i < mono_array_length (permissions); ++i) {
1520 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1522 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1524 idx = mono_metadata_token_index (parent_token);
1525 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1526 switch (mono_metadata_token_table (parent_token)) {
1527 case MONO_TABLE_TYPEDEF:
1528 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1530 case MONO_TABLE_METHOD:
1531 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1533 case MONO_TABLE_ASSEMBLY:
1534 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1537 g_assert_not_reached ();
1540 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1541 values [MONO_DECL_SECURITY_PARENT] = idx;
1542 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1549 * Fill in the MethodDef and ParamDef tables for a method.
1550 * This is used for both normal methods and constructors.
1553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1555 MONO_REQ_GC_UNSAFE_MODE;
1557 MonoDynamicTable *table;
1561 /* room in this table is already allocated */
1562 table = &assembly->tables [MONO_TABLE_METHOD];
1563 *mb->table_idx = table->next_idx ++;
1564 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1565 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1566 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1567 values [MONO_METHOD_FLAGS] = mb->attrs;
1568 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1569 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1570 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1572 table = &assembly->tables [MONO_TABLE_PARAM];
1573 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1575 mono_image_add_decl_security (assembly,
1576 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1579 MonoDynamicTable *mtable;
1582 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1583 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1586 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1587 if (mono_array_get (mb->pinfo, gpointer, i))
1590 table->rows += count;
1591 alloc_table (table, table->rows);
1592 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1593 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1594 MonoReflectionParamBuilder *pb;
1595 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1596 values [MONO_PARAM_FLAGS] = pb->attrs;
1597 values [MONO_PARAM_SEQUENCE] = i;
1598 if (pb->name != NULL) {
1599 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1601 values [MONO_PARAM_NAME] = 0;
1603 values += MONO_PARAM_SIZE;
1604 if (pb->marshal_info) {
1606 alloc_table (mtable, mtable->rows);
1607 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1608 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1609 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1611 pb->table_idx = table->next_idx++;
1612 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1613 guint32 field_type = 0;
1614 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1616 alloc_table (mtable, mtable->rows);
1617 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1618 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1619 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1620 mvalues [MONO_CONSTANT_TYPE] = field_type;
1621 mvalues [MONO_CONSTANT_PADDING] = 0;
1628 #ifndef DISABLE_REFLECTION_EMIT
1630 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1633 MONO_REQ_GC_UNSAFE_MODE;
1635 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1637 rmb->ilgen = mb->ilgen;
1638 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1639 mono_error_raise_exception (&error); /* FIXME don't raise here */
1640 rmb->parameters = mb->parameters;
1641 rmb->generic_params = mb->generic_params;
1642 rmb->generic_container = mb->generic_container;
1643 rmb->opt_types = NULL;
1644 rmb->pinfo = mb->pinfo;
1645 rmb->attrs = mb->attrs;
1646 rmb->iattrs = mb->iattrs;
1647 rmb->call_conv = mb->call_conv;
1648 rmb->code = mb->code;
1649 rmb->type = mb->type;
1650 rmb->name = mb->name;
1651 rmb->table_idx = &mb->table_idx;
1652 rmb->init_locals = mb->init_locals;
1653 rmb->skip_visibility = FALSE;
1654 rmb->return_modreq = mb->return_modreq;
1655 rmb->return_modopt = mb->return_modopt;
1656 rmb->param_modreq = mb->param_modreq;
1657 rmb->param_modopt = mb->param_modopt;
1658 rmb->permissions = mb->permissions;
1659 rmb->mhandle = mb->mhandle;
1664 rmb->charset = mb->charset;
1665 rmb->extra_flags = mb->extra_flags;
1666 rmb->native_cc = mb->native_cc;
1667 rmb->dllentry = mb->dllentry;
1673 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1675 MONO_REQ_GC_UNSAFE_MODE;
1678 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1680 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682 rmb->ilgen = mb->ilgen;
1683 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1684 mono_error_raise_exception (&error); /* FIXME don't raise here */
1685 rmb->parameters = mb->parameters;
1686 rmb->generic_params = NULL;
1687 rmb->generic_container = NULL;
1688 rmb->opt_types = NULL;
1689 rmb->pinfo = mb->pinfo;
1690 rmb->attrs = mb->attrs;
1691 rmb->iattrs = mb->iattrs;
1692 rmb->call_conv = mb->call_conv;
1694 rmb->type = mb->type;
1695 rmb->name = mono_string_new (mono_domain_get (), name);
1696 rmb->table_idx = &mb->table_idx;
1697 rmb->init_locals = mb->init_locals;
1698 rmb->skip_visibility = FALSE;
1699 rmb->return_modreq = NULL;
1700 rmb->return_modopt = NULL;
1701 rmb->param_modreq = mb->param_modreq;
1702 rmb->param_modopt = mb->param_modopt;
1703 rmb->permissions = mb->permissions;
1704 rmb->mhandle = mb->mhandle;
1710 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1712 MONO_REQ_GC_UNSAFE_MODE;
1714 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1716 rmb->ilgen = mb->ilgen;
1717 rmb->rtype = mb->rtype;
1718 rmb->parameters = mb->parameters;
1719 rmb->generic_params = NULL;
1720 rmb->generic_container = NULL;
1721 rmb->opt_types = NULL;
1723 rmb->attrs = mb->attrs;
1725 rmb->call_conv = mb->call_conv;
1727 rmb->type = (MonoObject *) mb->owner;
1728 rmb->name = mb->name;
1729 rmb->table_idx = NULL;
1730 rmb->init_locals = mb->init_locals;
1731 rmb->skip_visibility = mb->skip_visibility;
1732 rmb->return_modreq = NULL;
1733 rmb->return_modopt = NULL;
1734 rmb->param_modreq = NULL;
1735 rmb->param_modopt = NULL;
1736 rmb->permissions = NULL;
1737 rmb->mhandle = mb->mhandle;
1744 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1746 MONO_REQ_GC_UNSAFE_MODE;
1748 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1749 MonoDynamicTable *table;
1752 MonoReflectionMethod *m;
1755 if (!mb->override_methods)
1758 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1759 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1761 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1763 alloc_table (table, table->rows);
1764 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1765 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1766 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1768 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1769 switch (mono_metadata_token_table (tok)) {
1770 case MONO_TABLE_MEMBERREF:
1771 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1773 case MONO_TABLE_METHOD:
1774 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1777 g_assert_not_reached ();
1779 values [MONO_METHODIMPL_DECLARATION] = tok;
1783 #ifndef DISABLE_REFLECTION_EMIT
1785 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1787 MONO_REQ_GC_UNSAFE_MODE;
1789 MonoDynamicTable *table;
1791 ReflectionMethodBuilder rmb;
1794 reflection_methodbuilder_from_method_builder (&rmb, mb);
1796 mono_image_basic_method (&rmb, assembly);
1797 mb->table_idx = *rmb.table_idx;
1799 if (mb->dll) { /* It's a P/Invoke method */
1801 /* map CharSet values to on-disk values */
1802 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1803 int extra_flags = mb->extra_flags;
1804 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1806 alloc_table (table, table->rows);
1807 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1809 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1810 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1812 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1814 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1815 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1816 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1817 table = &assembly->tables [MONO_TABLE_MODULEREF];
1819 alloc_table (table, table->rows);
1820 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1821 values [MONO_IMPLMAP_SCOPE] = table->rows;
1825 if (mb->generic_params) {
1826 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1827 table->rows += mono_array_length (mb->generic_params);
1828 alloc_table (table, table->rows);
1829 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1830 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1832 mono_image_get_generic_param_info (
1833 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1840 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1842 MONO_REQ_GC_UNSAFE_MODE;
1844 ReflectionMethodBuilder rmb;
1846 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1848 mono_image_basic_method (&rmb, assembly);
1849 mb->table_idx = *rmb.table_idx;
1854 type_get_fully_qualified_name (MonoType *type)
1856 MONO_REQ_GC_NEUTRAL_MODE;
1858 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1862 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1864 MONO_REQ_GC_UNSAFE_MODE;
1869 klass = mono_class_from_mono_type (type);
1871 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872 ta = klass->image->assembly;
1873 if (assembly_is_dynamic (ta) || (ta == ass)) {
1874 if (klass->generic_class || klass->generic_container)
1875 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1876 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1878 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1881 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1884 #ifndef DISABLE_REFLECTION_EMIT
1885 /*field_image is the image to which the eventual custom mods have been encoded against*/
1887 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1889 MONO_REQ_GC_NEUTRAL_MODE;
1892 guint32 idx, i, token;
1894 if (!assembly->save)
1897 sigbuffer_init (&buf, 32);
1899 sigbuffer_add_value (&buf, 0x06);
1900 /* encode custom attributes before the type */
1901 if (type->num_mods) {
1902 for (i = 0; i < type->num_mods; ++i) {
1905 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1906 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1908 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1910 token = type->modifiers [i].token;
1913 if (type->modifiers [i].required)
1914 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1916 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1918 sigbuffer_add_value (&buf, token);
1921 encode_type (assembly, type, &buf);
1922 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1923 sigbuffer_free (&buf);
1929 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1931 MONO_REQ_GC_UNSAFE_MODE;
1935 guint32 typespec = 0;
1939 init_type_builder_generics (fb->type);
1941 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1942 klass = mono_class_from_mono_type (type);
1944 sigbuffer_init (&buf, 32);
1946 sigbuffer_add_value (&buf, 0x06);
1947 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1948 /* encode custom attributes before the type */
1950 if (klass->generic_container)
1951 typespec = create_typespec (assembly, type);
1954 MonoGenericClass *gclass;
1955 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1956 encode_generic_class (assembly, gclass, &buf);
1958 encode_type (assembly, type, &buf);
1960 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961 sigbuffer_free (&buf);
1966 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1968 MONO_REQ_GC_UNSAFE_MODE;
1970 char blob_size [64];
1971 char *b = blob_size;
1974 guint32 idx = 0, len = 0, dummy = 0;
1976 buf = (char *)g_malloc (64);
1978 *ret_type = MONO_TYPE_CLASS;
1980 box_val = (char*)&dummy;
1982 box_val = ((char*)val) + sizeof (MonoObject);
1983 *ret_type = val->vtable->klass->byval_arg.type;
1986 switch (*ret_type) {
1987 case MONO_TYPE_BOOLEAN:
1992 case MONO_TYPE_CHAR:
2009 case MONO_TYPE_VALUETYPE: {
2010 MonoClass *klass = val->vtable->klass;
2012 if (klass->enumtype) {
2013 *ret_type = mono_class_enum_basetype (klass)->type;
2015 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2018 g_error ("we can't encode valuetypes, we should have never reached this line");
2021 case MONO_TYPE_CLASS:
2023 case MONO_TYPE_STRING: {
2024 MonoString *str = (MonoString*)val;
2025 /* there is no signature */
2026 len = str->length * 2;
2027 mono_metadata_encode_value (len, b, &b);
2028 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2030 char *swapped = g_malloc (2 * mono_string_length (str));
2031 const char *p = (const char*)mono_string_chars (str);
2033 swap_with_size (swapped, p, 2, mono_string_length (str));
2034 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2038 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2044 case MONO_TYPE_GENERICINST:
2045 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2048 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2051 /* there is no signature */
2052 mono_metadata_encode_value (len, b, &b);
2053 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2054 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2055 swap_with_size (blob_size, box_val, len, 1);
2056 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2058 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2066 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2068 MONO_REQ_GC_UNSAFE_MODE;
2074 sigbuffer_init (&buf, 32);
2076 sigbuffer_add_value (&buf, minfo->type);
2078 switch (minfo->type) {
2079 case MONO_NATIVE_BYVALTSTR:
2080 case MONO_NATIVE_BYVALARRAY:
2081 sigbuffer_add_value (&buf, minfo->count);
2083 case MONO_NATIVE_LPARRAY:
2084 if (minfo->eltype || minfo->has_size) {
2085 sigbuffer_add_value (&buf, minfo->eltype);
2086 if (minfo->has_size) {
2087 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2088 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2090 /* LAMESPEC: ElemMult is undocumented */
2091 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2095 case MONO_NATIVE_SAFEARRAY:
2097 sigbuffer_add_value (&buf, minfo->eltype);
2099 case MONO_NATIVE_CUSTOM:
2101 str = mono_string_to_utf8 (minfo->guid);
2103 sigbuffer_add_value (&buf, len);
2104 sigbuffer_add_mem (&buf, str, len);
2107 sigbuffer_add_value (&buf, 0);
2109 /* native type name */
2110 sigbuffer_add_value (&buf, 0);
2111 /* custom marshaler type name */
2112 if (minfo->marshaltype || minfo->marshaltyperef) {
2113 if (minfo->marshaltyperef)
2114 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2116 str = mono_string_to_utf8 (minfo->marshaltype);
2118 sigbuffer_add_value (&buf, len);
2119 sigbuffer_add_mem (&buf, str, len);
2122 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2123 sigbuffer_add_value (&buf, 0);
2125 if (minfo->mcookie) {
2126 str = mono_string_to_utf8 (minfo->mcookie);
2128 sigbuffer_add_value (&buf, len);
2129 sigbuffer_add_mem (&buf, str, len);
2132 sigbuffer_add_value (&buf, 0);
2138 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2139 sigbuffer_free (&buf);
2144 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2146 MONO_REQ_GC_UNSAFE_MODE;
2148 MonoDynamicTable *table;
2151 /* maybe this fixup should be done in the C# code */
2152 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2153 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2154 table = &assembly->tables [MONO_TABLE_FIELD];
2155 fb->table_idx = table->next_idx ++;
2156 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2157 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2158 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2159 values [MONO_FIELD_FLAGS] = fb->attrs;
2160 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2162 if (fb->offset != -1) {
2163 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2165 alloc_table (table, table->rows);
2166 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2167 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2168 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2170 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2171 MonoTypeEnum field_type = (MonoTypeEnum)0;
2172 table = &assembly->tables [MONO_TABLE_CONSTANT];
2174 alloc_table (table, table->rows);
2175 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2176 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2177 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2178 values [MONO_CONSTANT_TYPE] = field_type;
2179 values [MONO_CONSTANT_PADDING] = 0;
2181 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2183 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2185 alloc_table (table, table->rows);
2186 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2187 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2189 * We store it in the code section because it's simpler for now.
2192 if (mono_array_length (fb->rva_data) >= 10)
2193 stream_data_align (&assembly->code);
2194 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2196 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2197 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2199 if (fb->marshal_info) {
2200 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2202 alloc_table (table, table->rows);
2203 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2204 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2205 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2210 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2212 MONO_REQ_GC_UNSAFE_MODE;
2215 guint32 nparams = 0;
2216 MonoReflectionMethodBuilder *mb = fb->get_method;
2217 MonoReflectionMethodBuilder *smb = fb->set_method;
2220 if (mb && mb->parameters)
2221 nparams = mono_array_length (mb->parameters);
2222 if (!mb && smb && smb->parameters)
2223 nparams = mono_array_length (smb->parameters) - 1;
2224 sigbuffer_init (&buf, 32);
2225 if (fb->call_conv & 0x20)
2226 sigbuffer_add_byte (&buf, 0x28);
2228 sigbuffer_add_byte (&buf, 0x08);
2229 sigbuffer_add_value (&buf, nparams);
2231 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2232 for (i = 0; i < nparams; ++i) {
2233 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2234 encode_reflection_type (assembly, pt, &buf);
2236 } else if (smb && smb->parameters) {
2237 /* the property type is the last param */
2238 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2239 for (i = 0; i < nparams; ++i) {
2240 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2241 encode_reflection_type (assembly, pt, &buf);
2244 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2247 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2248 sigbuffer_free (&buf);
2253 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2255 MONO_REQ_GC_UNSAFE_MODE;
2257 MonoDynamicTable *table;
2259 guint num_methods = 0;
2263 * we need to set things in the following tables:
2264 * PROPERTYMAP (info already filled in _get_type_info ())
2265 * PROPERTY (rows already preallocated in _get_type_info ())
2266 * METHOD (method info already done with the generic method code)
2270 table = &assembly->tables [MONO_TABLE_PROPERTY];
2271 pb->table_idx = table->next_idx ++;
2272 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2273 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2274 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2275 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2277 /* FIXME: we still don't handle 'other' methods */
2278 if (pb->get_method) num_methods ++;
2279 if (pb->set_method) num_methods ++;
2281 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2282 table->rows += num_methods;
2283 alloc_table (table, table->rows);
2285 if (pb->get_method) {
2286 semaidx = table->next_idx ++;
2287 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2289 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2290 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2292 if (pb->set_method) {
2293 semaidx = table->next_idx ++;
2294 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2295 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2296 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2297 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2299 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2300 MonoTypeEnum field_type = (MonoTypeEnum)0;
2301 table = &assembly->tables [MONO_TABLE_CONSTANT];
2303 alloc_table (table, table->rows);
2304 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2305 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2306 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2307 values [MONO_CONSTANT_TYPE] = field_type;
2308 values [MONO_CONSTANT_PADDING] = 0;
2313 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2315 MONO_REQ_GC_UNSAFE_MODE;
2317 MonoDynamicTable *table;
2319 guint num_methods = 0;
2323 * we need to set things in the following tables:
2324 * EVENTMAP (info already filled in _get_type_info ())
2325 * EVENT (rows already preallocated in _get_type_info ())
2326 * METHOD (method info already done with the generic method code)
2329 table = &assembly->tables [MONO_TABLE_EVENT];
2330 eb->table_idx = table->next_idx ++;
2331 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2332 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2333 values [MONO_EVENT_FLAGS] = eb->attrs;
2334 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2337 * FIXME: we still don't handle 'other' methods
2339 if (eb->add_method) num_methods ++;
2340 if (eb->remove_method) num_methods ++;
2341 if (eb->raise_method) num_methods ++;
2343 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2344 table->rows += num_methods;
2345 alloc_table (table, table->rows);
2347 if (eb->add_method) {
2348 semaidx = table->next_idx ++;
2349 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2351 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2352 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2354 if (eb->remove_method) {
2355 semaidx = table->next_idx ++;
2356 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2358 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2359 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2361 if (eb->raise_method) {
2362 semaidx = table->next_idx ++;
2363 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2364 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2365 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2366 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2371 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2373 MONO_REQ_GC_UNSAFE_MODE;
2375 MonoDynamicTable *table;
2376 guint32 num_constraints, i;
2380 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2381 num_constraints = gparam->iface_constraints ?
2382 mono_array_length (gparam->iface_constraints) : 0;
2383 table->rows += num_constraints;
2384 if (gparam->base_type)
2386 alloc_table (table, table->rows);
2388 if (gparam->base_type) {
2389 table_idx = table->next_idx ++;
2390 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2392 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2393 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2394 assembly, mono_reflection_type_get_handle (gparam->base_type));
2397 for (i = 0; i < num_constraints; i++) {
2398 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2399 gparam->iface_constraints, gpointer, i);
2401 table_idx = table->next_idx ++;
2402 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2404 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2405 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2406 assembly, mono_reflection_type_get_handle (constraint));
2411 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2413 MONO_REQ_GC_UNSAFE_MODE;
2415 GenericParamTableEntry *entry;
2418 * The GenericParam table must be sorted according to the `owner' field.
2419 * We need to do this sorting prior to writing the GenericParamConstraint
2420 * table, since we have to use the final GenericParam table indices there
2421 * and they must also be sorted.
2424 entry = g_new0 (GenericParamTableEntry, 1);
2425 entry->owner = owner;
2426 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2427 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2428 entry->gparam = gparam;
2430 g_ptr_array_add (assembly->gen_params, entry);
2434 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2436 MONO_REQ_GC_UNSAFE_MODE;
2438 MonoDynamicTable *table;
2439 MonoGenericParam *param;
2443 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2444 table_idx = table->next_idx ++;
2445 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2447 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2449 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2450 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2451 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2452 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2454 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2456 encode_constraints (entry->gparam, table_idx, assembly);
2460 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2462 MONO_REQ_GC_UNSAFE_MODE;
2464 MonoDynamicTable *table;
2467 guint32 cols [MONO_ASSEMBLY_SIZE];
2471 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2474 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2475 table = &assembly->tables [MONO_TABLE_MODULEREF];
2476 token = table->next_idx ++;
2478 alloc_table (table, table->rows);
2479 values = table->values + token * MONO_MODULEREF_SIZE;
2480 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2482 token <<= MONO_RESOLUTION_SCOPE_BITS;
2483 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2484 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2489 if (assembly_is_dynamic (image->assembly))
2491 memset (cols, 0, sizeof (cols));
2493 /* image->assembly->image is the manifest module */
2494 image = image->assembly->image;
2495 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2498 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2499 token = table->next_idx ++;
2501 alloc_table (table, table->rows);
2502 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2503 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2504 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2505 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2506 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2507 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2508 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2509 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2510 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2512 if (strcmp ("", image->assembly->aname.culture)) {
2513 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2514 image->assembly->aname.culture);
2517 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2518 guchar pubtoken [9];
2520 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2521 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2523 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2525 token <<= MONO_RESOLUTION_SCOPE_BITS;
2526 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2527 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2532 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2534 MONO_REQ_GC_NEUTRAL_MODE;
2536 MonoDynamicTable *table;
2541 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2544 sigbuffer_init (&buf, 32);
2545 switch (type->type) {
2546 case MONO_TYPE_FNPTR:
2548 case MONO_TYPE_SZARRAY:
2549 case MONO_TYPE_ARRAY:
2551 case MONO_TYPE_MVAR:
2552 case MONO_TYPE_GENERICINST:
2553 encode_type (assembly, type, &buf);
2555 case MONO_TYPE_CLASS:
2556 case MONO_TYPE_VALUETYPE: {
2557 MonoClass *k = mono_class_from_mono_type (type);
2558 if (!k || !k->generic_container) {
2559 sigbuffer_free (&buf);
2562 encode_type (assembly, type, &buf);
2566 sigbuffer_free (&buf);
2570 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571 if (assembly->save) {
2572 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573 alloc_table (table, table->rows + 1);
2574 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575 values [MONO_TYPESPEC_SIGNATURE] = token;
2577 sigbuffer_free (&buf);
2579 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2586 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2588 MONO_REQ_GC_UNSAFE_MODE;
2590 MonoDynamicTable *table;
2592 guint32 token, scope, enclosing;
2595 /* if the type requires a typespec, we must try that first*/
2596 if (try_typespec && (token = create_typespec (assembly, type)))
2598 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2601 klass = mono_class_from_mono_type (type);
2603 klass = mono_class_from_mono_type (type);
2606 * If it's in the same module and not a generic type parameter:
2608 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2609 (type->type != MONO_TYPE_MVAR)) {
2610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2611 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2612 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2616 if (klass->nested_in) {
2617 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2618 /* get the typeref idx of the enclosing type */
2619 enclosing >>= MONO_TYPEDEFORREF_BITS;
2620 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2622 scope = resolution_scope_from_image (assembly, klass->image);
2624 table = &assembly->tables [MONO_TABLE_TYPEREF];
2625 if (assembly->save) {
2626 alloc_table (table, table->rows + 1);
2627 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2628 values [MONO_TYPEREF_SCOPE] = scope;
2629 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2630 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2632 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2633 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2635 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2640 * Despite the name, we handle also TypeSpec (with the above helper).
2643 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2645 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2648 #ifndef DISABLE_REFLECTION_EMIT
2650 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2652 MONO_REQ_GC_NEUTRAL_MODE;
2654 MonoDynamicTable *table;
2656 guint32 token, pclass;
2658 switch (parent & MONO_TYPEDEFORREF_MASK) {
2659 case MONO_TYPEDEFORREF_TYPEREF:
2660 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2662 case MONO_TYPEDEFORREF_TYPESPEC:
2663 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2665 case MONO_TYPEDEFORREF_TYPEDEF:
2666 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2669 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2672 /* extract the index */
2673 parent >>= MONO_TYPEDEFORREF_BITS;
2675 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2677 if (assembly->save) {
2678 alloc_table (table, table->rows + 1);
2679 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2680 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2681 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2682 values [MONO_MEMBERREF_SIGNATURE] = sig;
2685 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2692 * Insert a memberef row into the metadata: the token that point to the memberref
2693 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2694 * mono_image_get_fieldref_token()).
2695 * The sig param is an index to an already built signature.
2698 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2700 MONO_REQ_GC_NEUTRAL_MODE;
2702 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2703 return mono_image_add_memberef_row (assembly, parent, name, sig);
2708 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2710 MONO_REQ_GC_NEUTRAL_MODE;
2713 MonoMethodSignature *sig;
2715 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2717 if (create_typespec) {
2718 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2723 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2724 if (token && !create_typespec)
2727 g_assert (!method->is_inflated);
2730 * A methodref signature can't contain an unmanaged calling convention.
2732 sig = mono_metadata_signature_dup (mono_method_signature (method));
2733 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2734 sig->call_convention = MONO_CALL_DEFAULT;
2735 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2736 method->name, method_encode_signature (assembly, sig));
2738 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2741 if (create_typespec) {
2742 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2743 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2744 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2746 if (assembly->save) {
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2751 values [MONO_METHODSPEC_METHOD] = token;
2752 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2755 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2757 /*methodspec and memberef tokens are diferent, */
2758 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2765 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2767 guint32 token, parent, sig;
2768 ReflectionMethodBuilder rmb;
2770 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2772 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2776 name = mono_string_to_utf8 (method->name);
2777 reflection_methodbuilder_from_method_builder (&rmb, method);
2780 * A methodref signature can't contain an unmanaged calling convention.
2781 * Since some flags are encoded as part of call_conv, we need to check against it.
2783 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2784 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2786 sig = method_builder_encode_signature (assembly, &rmb);
2788 if (tb->generic_params)
2789 parent = create_generic_typespec (assembly, tb);
2791 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2793 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2796 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2801 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2802 const gchar *name, guint32 sig)
2804 MonoDynamicTable *table;
2808 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2810 if (assembly->save) {
2811 alloc_table (table, table->rows + 1);
2812 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2813 values [MONO_MEMBERREF_CLASS] = original;
2814 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2815 values [MONO_MEMBERREF_SIGNATURE] = sig;
2818 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2825 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2829 guint32 nparams = mono_array_length (mb->generic_params);
2832 if (!assembly->save)
2835 sigbuffer_init (&buf, 32);
2837 sigbuffer_add_value (&buf, 0xa);
2838 sigbuffer_add_value (&buf, nparams);
2840 for (i = 0; i < nparams; i++) {
2841 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2842 sigbuffer_add_value (&buf, i);
2845 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2846 sigbuffer_free (&buf);
2851 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2853 MonoDynamicTable *table;
2855 guint32 token, mtoken = 0;
2857 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2861 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2863 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2864 switch (mono_metadata_token_table (mtoken)) {
2865 case MONO_TABLE_MEMBERREF:
2866 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2868 case MONO_TABLE_METHOD:
2869 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2872 g_assert_not_reached ();
2875 if (assembly->save) {
2876 alloc_table (table, table->rows + 1);
2877 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2878 values [MONO_METHODSPEC_METHOD] = mtoken;
2879 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2882 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2885 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2890 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2894 if (mb->generic_params && create_methodspec)
2895 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2897 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2901 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2902 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2907 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2909 guint32 token, parent, sig;
2910 ReflectionMethodBuilder rmb;
2912 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2914 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2918 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2920 if (tb->generic_params)
2921 parent = create_generic_typespec (assembly, tb);
2923 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2925 name = mono_string_to_utf8 (rmb.name);
2926 sig = method_builder_encode_signature (assembly, &rmb);
2928 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2931 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2937 is_field_on_inst (MonoClassField *field)
2939 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2943 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2946 get_field_on_inst_generic_type (MonoClassField *field)
2948 MonoClass *klass, *gtd;
2949 MonoDynamicGenericClass *dgclass;
2952 g_assert (is_field_on_inst (field));
2954 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2956 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2957 field_index = field - dgclass->fields;
2958 return dgclass->field_generic_types [field_index];
2961 klass = field->parent;
2962 gtd = klass->generic_class->container_class;
2964 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2965 field_index = field - klass->fields;
2966 return gtd->fields [field_index].type;
2969 g_assert_not_reached ();
2973 #ifndef DISABLE_REFLECTION_EMIT
2975 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2981 g_assert (field->parent);
2983 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2987 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2988 int index = field - field->parent->fields;
2989 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2991 if (is_field_on_inst (field))
2992 type = get_field_on_inst_generic_type (field);
2994 type = mono_field_get_type (field);
2996 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2997 mono_field_get_name (field),
2998 fieldref_encode_signature (assembly, field->parent->image, type));
2999 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3004 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3008 MonoGenericClass *gclass;
3012 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3015 if (is_sre_field_builder (mono_object_class (f->fb))) {
3016 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3017 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3018 klass = mono_class_from_mono_type (type);
3019 gclass = type->data.generic_class;
3020 g_assert (gclass->is_dynamic);
3022 name = mono_string_to_utf8 (fb->name);
3023 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3024 field_encode_signature (assembly, fb));
3026 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3028 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3030 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3031 klass = mono_class_from_mono_type (type);
3033 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3034 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3036 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3037 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3040 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3045 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3049 MonoGenericClass *gclass;
3052 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3054 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3058 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3059 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3060 ReflectionMethodBuilder rmb;
3063 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3064 klass = mono_class_from_mono_type (type);
3066 gclass = type->data.generic_class;
3067 g_assert (gclass->is_dynamic);
3069 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3071 name = mono_string_to_utf8 (rmb.name);
3073 sig = method_builder_encode_signature (assembly, &rmb);
3075 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3077 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3078 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3080 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3081 klass = mono_class_from_mono_type (type);
3083 sig = method_encode_signature (assembly, mono_method_signature (mm));
3084 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3086 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3087 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3091 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3096 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3100 MonoGenericContext tmp_context;
3101 MonoType **type_argv;
3102 MonoGenericInst *ginst;
3103 MonoMethod *method, *inflated;
3106 init_type_builder_generics ((MonoObject*)m->inst);
3108 method = inflate_method (m->inst, (MonoObject*)m->mb);
3110 klass = method->klass;
3112 if (m->method_args == NULL)
3115 if (method->is_inflated)
3116 method = ((MonoMethodInflated *) method)->declaring;
3118 count = mono_array_length (m->method_args);
3120 type_argv = g_new0 (MonoType *, count);
3121 for (i = 0; i < count; i++) {
3122 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3123 type_argv [i] = mono_reflection_type_get_handle (garg);
3125 ginst = mono_metadata_get_generic_inst (count, type_argv);
3128 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3129 tmp_context.method_inst = ginst;
3131 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3132 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3137 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3139 guint32 sig, token = 0;
3143 if (m->method_args) {
3144 MonoMethod *inflated;
3146 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3147 if (create_methodspec)
3148 token = mono_image_get_methodspec_token (assembly, inflated);
3150 token = mono_image_get_inflated_method_token (assembly, inflated);
3154 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3158 if (is_sre_method_builder (mono_object_class (m->mb))) {
3159 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3160 MonoGenericClass *gclass;
3161 ReflectionMethodBuilder rmb;
3164 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3165 klass = mono_class_from_mono_type (type);
3166 gclass = type->data.generic_class;
3167 g_assert (gclass->is_dynamic);
3169 reflection_methodbuilder_from_method_builder (&rmb, mb);
3171 name = mono_string_to_utf8 (rmb.name);
3173 sig = method_builder_encode_signature (assembly, &rmb);
3175 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3177 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3178 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3180 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3181 klass = mono_class_from_mono_type (type);
3183 sig = method_encode_signature (assembly, mono_method_signature (mm));
3184 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3186 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3187 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3190 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3195 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3199 guint32 nparams = context->method_inst->type_argc;
3202 if (!assembly->save)
3205 sigbuffer_init (&buf, 32);
3207 * FIXME: vararg, explicit_this, differenc call_conv values...
3209 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3210 sigbuffer_add_value (&buf, nparams);
3212 for (i = 0; i < nparams; i++)
3213 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3215 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3216 sigbuffer_free (&buf);
3221 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3223 MonoDynamicTable *table;
3225 guint32 token, mtoken = 0, sig;
3226 MonoMethodInflated *imethod;
3227 MonoMethod *declaring;
3229 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3231 g_assert (method->is_inflated);
3232 imethod = (MonoMethodInflated *) method;
3233 declaring = imethod->declaring;
3235 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3236 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3238 if (!mono_method_signature (declaring)->generic_param_count)
3241 switch (mono_metadata_token_table (mtoken)) {
3242 case MONO_TABLE_MEMBERREF:
3243 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3245 case MONO_TABLE_METHOD:
3246 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3249 g_assert_not_reached ();
3252 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3254 if (assembly->save) {
3255 alloc_table (table, table->rows + 1);
3256 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3257 values [MONO_METHODSPEC_METHOD] = mtoken;
3258 values [MONO_METHODSPEC_SIGNATURE] = sig;
3261 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3268 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3270 MonoMethodInflated *imethod;
3273 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3277 g_assert (method->is_inflated);
3278 imethod = (MonoMethodInflated *) method;
3280 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3281 token = method_encode_methodspec (assembly, method);
3283 guint32 sig = method_encode_signature (
3284 assembly, mono_method_signature (imethod->declaring));
3285 token = mono_image_get_memberref_token (
3286 assembly, &method->klass->byval_arg, method->name, sig);
3289 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3294 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3296 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3299 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3300 token = mono_image_get_memberref_token (
3301 assembly, &m->klass->byval_arg, m->name, sig);
3307 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3309 MonoDynamicTable *table;
3318 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3319 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3320 * Because of this, we must not insert it into the `typeref' hash table.
3322 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3323 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3327 sigbuffer_init (&buf, 32);
3329 g_assert (tb->generic_params);
3330 klass = mono_class_from_mono_type (type);
3332 if (tb->generic_container)
3333 mono_reflection_create_generic_class (tb);
3335 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3336 g_assert (klass->generic_container);
3337 sigbuffer_add_value (&buf, klass->byval_arg.type);
3338 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3340 count = mono_array_length (tb->generic_params);
3341 sigbuffer_add_value (&buf, count);
3342 for (i = 0; i < count; i++) {
3343 MonoReflectionGenericParam *gparam;
3345 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3347 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3350 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3352 if (assembly->save) {
3353 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3354 alloc_table (table, table->rows + 1);
3355 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3356 values [MONO_TYPESPEC_SIGNATURE] = token;
3358 sigbuffer_free (&buf);
3360 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3361 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3367 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3370 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3372 int i, count, len, pos;
3377 count += mono_array_length (modreq);
3379 count += mono_array_length (modopt);
3382 return mono_metadata_type_dup (NULL, type);
3384 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3385 t = (MonoType *)g_malloc (len);
3386 memcpy (t, type, MONO_SIZEOF_TYPE);
3388 t->num_mods = count;
3391 for (i = 0; i < mono_array_length (modreq); ++i) {
3392 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3393 t->modifiers [pos].required = 1;
3394 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3399 for (i = 0; i < mono_array_length (modopt); ++i) {
3400 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3401 t->modifiers [pos].required = 0;
3402 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3411 init_type_builder_generics (MonoObject *type)
3413 MonoReflectionTypeBuilder *tb;
3415 if (!is_sre_type_builder(mono_object_class (type)))
3417 tb = (MonoReflectionTypeBuilder *)type;
3419 if (tb && tb->generic_container)
3420 mono_reflection_create_generic_class (tb);
3424 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3426 MonoDynamicTable *table;
3427 MonoType *custom = NULL, *type;
3429 guint32 token, pclass, parent, sig;
3432 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3436 /* FIXME: is this call necessary? */
3437 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3438 name = mono_string_to_utf8 (fb->name);
3440 /*FIXME this is one more layer of ugliness due how types are created.*/
3441 init_type_builder_generics (fb->type);
3443 /* fb->type does not include the custom modifiers */
3444 /* FIXME: We should do this in one place when a fieldbuilder is created */
3445 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3446 if (fb->modreq || fb->modopt)
3447 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3449 sig = fieldref_encode_signature (assembly, NULL, type);
3452 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3453 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3455 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3456 parent >>= MONO_TYPEDEFORREF_BITS;
3458 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3460 if (assembly->save) {
3461 alloc_table (table, table->rows + 1);
3462 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3463 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3464 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3465 values [MONO_MEMBERREF_SIGNATURE] = sig;
3468 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3470 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3476 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3482 if (!assembly->save)
3485 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3486 g_assert (helper->type == 2);
3488 if (helper->arguments)
3489 nargs = mono_array_length (helper->arguments);
3493 sigbuffer_init (&buf, 32);
3495 /* Encode calling convention */
3496 /* Change Any to Standard */
3497 if ((helper->call_conv & 0x03) == 0x03)
3498 helper->call_conv = 0x01;
3499 /* explicit_this implies has_this */
3500 if (helper->call_conv & 0x40)
3501 helper->call_conv &= 0x20;
3503 if (helper->call_conv == 0) { /* Unmanaged */
3504 idx = helper->unmanaged_call_conv - 1;
3507 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3508 if (helper->call_conv & 0x02) /* varargs */
3512 sigbuffer_add_byte (&buf, idx);
3513 sigbuffer_add_value (&buf, nargs);
3514 encode_reflection_type (assembly, helper->return_type, &buf);
3515 for (i = 0; i < nargs; ++i) {
3516 MonoArray *modreqs = NULL;
3517 MonoArray *modopts = NULL;
3518 MonoReflectionType *pt;
3520 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3521 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3522 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3523 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3525 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3526 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3527 encode_reflection_type (assembly, pt, &buf);
3529 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3530 sigbuffer_free (&buf);
3536 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3539 MonoDynamicTable *table;
3542 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3543 idx = table->next_idx ++;
3545 alloc_table (table, table->rows);
3546 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3548 values [MONO_STAND_ALONE_SIGNATURE] =
3549 mono_reflection_encode_sighelper (assembly, helper);
3555 reflection_cc_to_file (int call_conv) {
3556 switch (call_conv & 0x3) {
3558 case 1: return MONO_CALL_DEFAULT;
3559 case 2: return MONO_CALL_VARARG;
3561 g_assert_not_reached ();
3565 #endif /* !DISABLE_REFLECTION_EMIT */
3569 MonoMethodSignature *sig;
3574 #ifndef DISABLE_REFLECTION_EMIT
3576 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3581 MonoMethodSignature *sig;
3585 name = mono_string_to_utf8 (m->name);
3586 nparams = mono_array_length (m->parameters);
3587 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3589 sig->sentinelpos = -1;
3590 sig->call_convention = reflection_cc_to_file (m->call_conv);
3591 sig->param_count = nparams;
3592 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3593 mtype = mono_reflection_type_get_handle (m->parent);
3594 for (i = 0; i < nparams; ++i)
3595 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3597 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3598 am = (ArrayMethod *)tmp->data;
3599 if (strcmp (name, am->name) == 0 &&
3600 mono_metadata_type_equal (am->parent, mtype) &&
3601 mono_metadata_signature_equal (am->sig, sig)) {
3604 m->table_idx = am->token & 0xffffff;
3608 am = g_new0 (ArrayMethod, 1);
3612 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3613 method_encode_signature (assembly, sig));
3614 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3615 m->table_idx = am->token & 0xffffff;
3620 * Insert into the metadata tables all the info about the TypeBuilder tb.
3621 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3624 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3626 MonoDynamicTable *table;
3628 int i, is_object = 0, is_system = 0;
3631 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3632 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3633 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3634 n = mono_string_to_utf8 (tb->name);
3635 if (strcmp (n, "Object") == 0)
3637 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3639 n = mono_string_to_utf8 (tb->nspace);
3640 if (strcmp (n, "System") == 0)
3642 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3644 if (tb->parent && !(is_system && is_object) &&
3645 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3646 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3648 values [MONO_TYPEDEF_EXTENDS] = 0;
3650 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3651 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3654 * if we have explicitlayout or sequentiallayouts, output data in the
3655 * ClassLayout table.
3657 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3658 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3659 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3661 alloc_table (table, table->rows);
3662 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3663 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3664 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3665 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3668 /* handle interfaces */
3669 if (tb->interfaces) {
3670 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3672 table->rows += mono_array_length (tb->interfaces);
3673 alloc_table (table, table->rows);
3674 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3675 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3676 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3677 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3678 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3679 values += MONO_INTERFACEIMPL_SIZE;
3685 table = &assembly->tables [MONO_TABLE_FIELD];
3686 table->rows += tb->num_fields;
3687 alloc_table (table, table->rows);
3688 for (i = 0; i < tb->num_fields; ++i)
3689 mono_image_get_field_info (
3690 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3693 /* handle constructors */
3695 table = &assembly->tables [MONO_TABLE_METHOD];
3696 table->rows += mono_array_length (tb->ctors);
3697 alloc_table (table, table->rows);
3698 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3699 mono_image_get_ctor_info (domain,
3700 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3703 /* handle methods */
3705 table = &assembly->tables [MONO_TABLE_METHOD];
3706 table->rows += tb->num_methods;
3707 alloc_table (table, table->rows);
3708 for (i = 0; i < tb->num_methods; ++i)
3709 mono_image_get_method_info (
3710 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3713 /* Do the same with properties etc.. */
3714 if (tb->events && mono_array_length (tb->events)) {
3715 table = &assembly->tables [MONO_TABLE_EVENT];
3716 table->rows += mono_array_length (tb->events);
3717 alloc_table (table, table->rows);
3718 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3720 alloc_table (table, table->rows);
3721 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3722 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3723 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3724 for (i = 0; i < mono_array_length (tb->events); ++i)
3725 mono_image_get_event_info (
3726 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3728 if (tb->properties && mono_array_length (tb->properties)) {
3729 table = &assembly->tables [MONO_TABLE_PROPERTY];
3730 table->rows += mono_array_length (tb->properties);
3731 alloc_table (table, table->rows);
3732 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3734 alloc_table (table, table->rows);
3735 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3736 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3737 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3738 for (i = 0; i < mono_array_length (tb->properties); ++i)
3739 mono_image_get_property_info (
3740 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3743 /* handle generic parameters */
3744 if (tb->generic_params) {
3745 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3746 table->rows += mono_array_length (tb->generic_params);
3747 alloc_table (table, table->rows);
3748 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3749 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3751 mono_image_get_generic_param_info (
3752 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3756 mono_image_add_decl_security (assembly,
3757 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3760 MonoDynamicTable *ntable;
3762 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3763 ntable->rows += mono_array_length (tb->subtypes);
3764 alloc_table (ntable, ntable->rows);
3765 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3767 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3768 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3770 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3771 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3772 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3773 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3774 mono_string_to_utf8 (tb->name), tb->table_idx,
3775 ntable->next_idx, ntable->rows);*/
3776 values += MONO_NESTED_CLASS_SIZE;
3784 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3788 mono_ptr_array_append (*types, type);
3790 if (!type->subtypes)
3793 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3794 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3795 collect_types (types, subtype);
3800 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3802 if ((*type1)->table_idx < (*type2)->table_idx)
3805 if ((*type1)->table_idx > (*type2)->table_idx)
3812 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3817 for (i = 0; i < mono_array_length (pinfo); ++i) {
3818 MonoReflectionParamBuilder *pb;
3819 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3822 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3827 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3830 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3832 for (i = 0; i < tb->num_fields; ++i) {
3833 MonoReflectionFieldBuilder* fb;
3834 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3835 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3839 for (i = 0; i < mono_array_length (tb->events); ++i) {
3840 MonoReflectionEventBuilder* eb;
3841 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3842 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3845 if (tb->properties) {
3846 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3847 MonoReflectionPropertyBuilder* pb;
3848 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3849 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3853 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3854 MonoReflectionCtorBuilder* cb;
3855 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3856 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3857 params_add_cattrs (assembly, cb->pinfo);
3862 for (i = 0; i < tb->num_methods; ++i) {
3863 MonoReflectionMethodBuilder* mb;
3864 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3865 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3866 params_add_cattrs (assembly, mb->pinfo);
3871 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3872 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3877 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3881 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3883 if (moduleb->global_methods) {
3884 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3885 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3886 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3887 params_add_cattrs (assembly, mb->pinfo);
3891 if (moduleb->global_fields) {
3892 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3893 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3894 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3898 if (moduleb->types) {
3899 for (i = 0; i < moduleb->num_types; ++i)
3900 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3905 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3907 MonoDynamicTable *table;
3911 char *b = blob_size;
3914 table = &assembly->tables [MONO_TABLE_FILE];
3916 alloc_table (table, table->rows);
3917 values = table->values + table->next_idx * MONO_FILE_SIZE;
3918 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3919 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3920 if (image_is_dynamic (module->image)) {
3921 /* This depends on the fact that the main module is emitted last */
3922 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3923 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3926 path = g_strdup (module->image->name);
3928 mono_sha1_get_digest_from_file (path, hash);
3931 mono_metadata_encode_value (20, b, &b);
3932 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3933 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3940 MonoDynamicTable *table;
3943 table = &assembly->tables [MONO_TABLE_MODULE];
3944 mb->table_idx = table->next_idx ++;
3945 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3946 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3949 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3950 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3951 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3952 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3956 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3957 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3959 MonoDynamicTable *table;
3963 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3964 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3967 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3969 alloc_table (table, table->rows);
3970 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3972 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3973 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3974 if (klass->nested_in)
3975 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3977 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3978 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3979 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3981 res = table->next_idx;
3985 /* Emit nested types */
3986 if (klass->ext && klass->ext->nested_classes) {
3989 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3990 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3997 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3998 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4003 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4005 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4007 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4008 parent_index, assembly);
4012 * We need to do this ourselves since klass->nested_classes is not set up.
4015 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4016 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4021 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4022 guint32 module_index, MonoDynamicImage *assembly)
4024 MonoImage *image = module->image;
4028 t = &image->tables [MONO_TABLE_TYPEDEF];
4030 for (i = 0; i < t->rows; ++i) {
4032 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4033 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4035 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4036 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4041 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4043 MonoDynamicTable *table;
4045 guint32 scope, scope_idx, impl, current_idx;
4046 gboolean forwarder = TRUE;
4047 gpointer iter = NULL;
4050 if (klass->nested_in) {
4051 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4054 scope = resolution_scope_from_image (assembly, klass->image);
4055 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4056 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4057 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4060 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4063 alloc_table (table, table->rows);
4064 current_idx = table->next_idx;
4065 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4067 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4068 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4069 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4070 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4071 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4075 while ((nested = mono_class_get_nested_types (klass, &iter)))
4076 add_exported_type (assemblyb, assembly, nested, current_idx);
4080 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4085 if (!assemblyb->type_forwarders)
4088 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4089 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4094 type = mono_reflection_type_get_handle (t);
4097 klass = mono_class_from_mono_type (type);
4099 add_exported_type (assemblyb, assembly, klass, 0);
4103 #define align_pointer(base,p)\
4105 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4107 (p) += 4 - (__diff & 3);\
4111 compare_constants (const void *a, const void *b)
4113 const guint32 *a_values = (const guint32 *)a;
4114 const guint32 *b_values = (const guint32 *)b;
4115 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4119 compare_semantics (const void *a, const void *b)
4121 const guint32 *a_values = (const guint32 *)a;
4122 const guint32 *b_values = (const guint32 *)b;
4123 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4126 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4130 compare_custom_attrs (const void *a, const void *b)
4132 const guint32 *a_values = (const guint32 *)a;
4133 const guint32 *b_values = (const guint32 *)b;
4135 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4139 compare_field_marshal (const void *a, const void *b)
4141 const guint32 *a_values = (const guint32 *)a;
4142 const guint32 *b_values = (const guint32 *)b;
4144 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4148 compare_nested (const void *a, const void *b)
4150 const guint32 *a_values = (const guint32 *)a;
4151 const guint32 *b_values = (const guint32 *)b;
4153 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4157 compare_genericparam (const void *a, const void *b)
4159 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4160 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4162 if ((*b_entry)->owner == (*a_entry)->owner)
4164 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4165 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4167 return (*a_entry)->owner - (*b_entry)->owner;
4171 compare_declsecurity_attrs (const void *a, const void *b)
4173 const guint32 *a_values = (const guint32 *)a;
4174 const guint32 *b_values = (const guint32 *)b;
4176 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4180 compare_interface_impl (const void *a, const void *b)
4182 const guint32 *a_values = (const guint32 *)a;
4183 const guint32 *b_values = (const guint32 *)b;
4185 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4189 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4193 pad_heap (MonoDynamicStream *sh)
4195 if (sh->index & 3) {
4196 int sz = 4 - (sh->index & 3);
4197 memset (sh->data + sh->index, 0, sz);
4204 MonoDynamicStream *stream;
4208 * build_compressed_metadata() fills in the blob of data that represents the
4209 * raw metadata as it will be saved in the PE file. The five streams are output
4210 * and the metadata tables are comnpressed from the guint32 array representation,
4211 * to the compressed on-disk format.
4214 build_compressed_metadata (MonoDynamicImage *assembly)
4216 MonoDynamicTable *table;
4218 guint64 valid_mask = 0;
4219 guint64 sorted_mask;
4220 guint32 heapt_size = 0;
4221 guint32 meta_size = 256; /* allow for header and other stuff */
4222 guint32 table_offset;
4223 guint32 ntables = 0;
4229 struct StreamDesc stream_desc [5];
4231 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4232 for (i = 0; i < assembly->gen_params->len; i++){
4233 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4234 write_generic_param_entry (assembly, entry);
4237 stream_desc [0].name = "#~";
4238 stream_desc [0].stream = &assembly->tstream;
4239 stream_desc [1].name = "#Strings";
4240 stream_desc [1].stream = &assembly->sheap;
4241 stream_desc [2].name = "#US";
4242 stream_desc [2].stream = &assembly->us;
4243 stream_desc [3].name = "#Blob";
4244 stream_desc [3].stream = &assembly->blob;
4245 stream_desc [4].name = "#GUID";
4246 stream_desc [4].stream = &assembly->guid;
4248 /* tables that are sorted */
4249 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4250 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4251 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4252 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4253 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4254 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4255 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4257 /* Compute table sizes */
4258 /* the MonoImage has already been created in mono_image_basic_init() */
4259 meta = &assembly->image;
4261 /* sizes should be multiple of 4 */
4262 pad_heap (&assembly->blob);
4263 pad_heap (&assembly->guid);
4264 pad_heap (&assembly->sheap);
4265 pad_heap (&assembly->us);
4267 /* Setup the info used by compute_sizes () */
4268 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4269 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4270 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4272 meta_size += assembly->blob.index;
4273 meta_size += assembly->guid.index;
4274 meta_size += assembly->sheap.index;
4275 meta_size += assembly->us.index;
4277 for (i=0; i < MONO_TABLE_NUM; ++i)
4278 meta->tables [i].rows = assembly->tables [i].rows;
4280 for (i = 0; i < MONO_TABLE_NUM; i++){
4281 if (meta->tables [i].rows == 0)
4283 valid_mask |= (guint64)1 << i;
4285 meta->tables [i].row_size = mono_metadata_compute_size (
4286 meta, i, &meta->tables [i].size_bitfield);
4287 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4289 heapt_size += 24; /* #~ header size */
4290 heapt_size += ntables * 4;
4291 /* make multiple of 4 */
4294 meta_size += heapt_size;
4295 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4296 p = (unsigned char*)meta->raw_metadata;
4297 /* the metadata signature */
4298 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4299 /* version numbers and 4 bytes reserved */
4300 int16val = (guint16*)p;
4301 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4302 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4304 /* version string */
4305 int32val = (guint32*)p;
4306 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4308 memcpy (p, meta->version, strlen (meta->version));
4309 p += GUINT32_FROM_LE (*int32val);
4310 align_pointer (meta->raw_metadata, p);
4311 int16val = (guint16*)p;
4312 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4313 *int16val = GUINT16_TO_LE (5); /* number of streams */
4317 * write the stream info.
4319 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4320 table_offset += 3; table_offset &= ~3;
4322 assembly->tstream.index = heapt_size;
4323 for (i = 0; i < 5; ++i) {
4324 int32val = (guint32*)p;
4325 stream_desc [i].stream->offset = table_offset;
4326 *int32val++ = GUINT32_TO_LE (table_offset);
4327 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4328 table_offset += GUINT32_FROM_LE (*int32val);
4329 table_offset += 3; table_offset &= ~3;
4331 strcpy ((char*)p, stream_desc [i].name);
4332 p += strlen (stream_desc [i].name) + 1;
4333 align_pointer (meta->raw_metadata, p);
4336 * now copy the data, the table stream header and contents goes first.
4338 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4339 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4340 int32val = (guint32*)p;
4341 *int32val = GUINT32_TO_LE (0); /* reserved */
4344 *p++ = 2; /* version */
4347 if (meta->idx_string_wide)
4349 if (meta->idx_guid_wide)
4351 if (meta->idx_blob_wide)
4354 *p++ = 1; /* reserved */
4355 int64val = (guint64*)p;
4356 *int64val++ = GUINT64_TO_LE (valid_mask);
4357 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4359 int32val = (guint32*)p;
4360 for (i = 0; i < MONO_TABLE_NUM; i++){
4361 if (meta->tables [i].rows == 0)
4363 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4365 p = (unsigned char*)int32val;
4367 /* sort the tables that still need sorting */
4368 table = &assembly->tables [MONO_TABLE_CONSTANT];
4370 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4371 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4373 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4374 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4376 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4377 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4379 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4380 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4382 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4383 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4384 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4386 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4387 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4389 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4391 /* compress the tables */
4392 for (i = 0; i < MONO_TABLE_NUM; i++){
4395 guint32 bitfield = meta->tables [i].size_bitfield;
4396 if (!meta->tables [i].rows)
4398 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4399 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4400 meta->tables [i].base = (char*)p;
4401 for (row = 1; row <= meta->tables [i].rows; ++row) {
4402 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4403 for (col = 0; col < assembly->tables [i].columns; ++col) {
4404 switch (mono_metadata_table_size (bitfield, col)) {
4406 *p++ = values [col];
4409 *p++ = values [col] & 0xff;
4410 *p++ = (values [col] >> 8) & 0xff;
4413 *p++ = values [col] & 0xff;
4414 *p++ = (values [col] >> 8) & 0xff;
4415 *p++ = (values [col] >> 16) & 0xff;
4416 *p++ = (values [col] >> 24) & 0xff;
4419 g_assert_not_reached ();
4423 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4426 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4427 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4428 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4429 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4430 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4432 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4436 * Some tables in metadata need to be sorted according to some criteria, but
4437 * when methods and fields are first created with reflection, they may be assigned a token
4438 * that doesn't correspond to the final token they will get assigned after the sorting.
4439 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4440 * with the reflection objects that represent them. Once all the tables are set up, the
4441 * reflection objects will contains the correct table index. fixup_method() will fixup the
4442 * tokens for the method with ILGenerator @ilgen.
4445 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4447 guint32 code_idx = GPOINTER_TO_UINT (value);
4448 MonoReflectionILTokenInfo *iltoken;
4449 MonoReflectionFieldBuilder *field;
4450 MonoReflectionCtorBuilder *ctor;
4451 MonoReflectionMethodBuilder *method;
4452 MonoReflectionTypeBuilder *tb;
4453 MonoReflectionArrayMethod *am;
4455 unsigned char *target;
4457 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4458 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4459 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4460 switch (target [3]) {
4461 case MONO_TABLE_FIELD:
4462 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4463 field = (MonoReflectionFieldBuilder *)iltoken->member;
4464 idx = field->table_idx;
4465 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4466 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4467 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4469 g_assert_not_reached ();
4472 case MONO_TABLE_METHOD:
4473 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4474 method = (MonoReflectionMethodBuilder *)iltoken->member;
4475 idx = method->table_idx;
4476 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4477 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4478 idx = ctor->table_idx;
4479 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4480 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4481 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4482 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4484 g_assert_not_reached ();
4487 case MONO_TABLE_TYPEDEF:
4488 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4489 g_assert_not_reached ();
4490 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4491 idx = tb->table_idx;
4493 case MONO_TABLE_MEMBERREF:
4494 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4495 am = (MonoReflectionArrayMethod*)iltoken->member;
4496 idx = am->table_idx;
4497 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4498 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4499 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4500 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4501 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4502 g_assert (m->klass->generic_class || m->klass->generic_container);
4504 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4506 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4507 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4508 g_assert (is_field_on_inst (f));
4510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4511 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4513 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4517 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4520 g_assert_not_reached ();
4523 case MONO_TABLE_METHODSPEC:
4524 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4525 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4526 g_assert (mono_method_signature (m)->generic_param_count);
4528 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4530 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4533 g_assert_not_reached ();
4537 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4539 target [0] = idx & 0xff;
4540 target [1] = (idx >> 8) & 0xff;
4541 target [2] = (idx >> 16) & 0xff;
4548 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4549 * value is not known when the table is emitted.
4552 fixup_cattrs (MonoDynamicImage *assembly)
4554 MonoDynamicTable *table;
4556 guint32 type, i, idx, token;
4559 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4561 for (i = 0; i < table->rows; ++i) {
4562 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4564 type = values [MONO_CUSTOM_ATTR_TYPE];
4565 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4566 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4567 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4568 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4571 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4572 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4573 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4575 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4576 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4577 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4578 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4585 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4587 MonoDynamicTable *table;
4590 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4592 alloc_table (table, table->rows);
4593 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4594 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4595 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4596 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4597 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4602 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4604 MonoDynamicTable *table;
4608 char *b = blob_size;
4610 guint32 idx, offset;
4612 if (rsrc->filename) {
4613 name = mono_string_to_utf8 (rsrc->filename);
4614 sname = g_path_get_basename (name);
4616 table = &assembly->tables [MONO_TABLE_FILE];
4618 alloc_table (table, table->rows);
4619 values = table->values + table->next_idx * MONO_FILE_SIZE;
4620 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4621 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4624 mono_sha1_get_digest_from_file (name, hash);
4625 mono_metadata_encode_value (20, b, &b);
4626 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4627 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4629 idx = table->next_idx++;
4631 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4637 data = mono_array_addr (rsrc->data, char, 0);
4638 len = mono_array_length (rsrc->data);
4644 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4645 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4646 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4647 mono_image_add_stream_data (&assembly->resources, data, len);
4651 * The entry should be emitted into the MANIFESTRESOURCE table of
4652 * the main module, but that needs to reference the FILE table
4653 * which isn't emitted yet.
4660 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4664 set_version_from_string (MonoString *version, guint32 *values)
4666 gchar *ver, *p, *str;
4669 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4670 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4671 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4672 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4675 ver = str = mono_string_to_utf8 (version);
4676 for (i = 0; i < 4; ++i) {
4677 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4683 /* handle Revision and Build */
4693 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4697 char *b = blob_size;
4702 len = mono_array_length (pkey);
4703 mono_metadata_encode_value (len, b, &b);
4704 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4705 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4707 assembly->public_key = (guint8 *)g_malloc (len);
4708 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4709 assembly->public_key_len = len;
4711 /* Special case: check for ECMA key (16 bytes) */
4712 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4713 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4714 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4715 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4716 /* minimum key size (in 2.0) is 384 bits */
4717 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4719 /* FIXME - verifier */
4720 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4721 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4723 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4729 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4731 MonoDynamicTable *table;
4732 MonoDynamicImage *assembly;
4733 MonoReflectionAssemblyBuilder *assemblyb;
4737 guint32 module_index;
4739 assemblyb = moduleb->assemblyb;
4740 assembly = moduleb->dynamic_image;
4741 domain = mono_object_domain (assemblyb);
4743 /* Emit ASSEMBLY table */
4744 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4745 alloc_table (table, 1);
4746 values = table->values + MONO_ASSEMBLY_SIZE;
4747 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4748 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4749 if (assemblyb->culture) {
4750 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4752 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4754 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4755 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4756 set_version_from_string (assemblyb->version, values);
4758 /* Emit FILE + EXPORTED_TYPE table */
4760 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4762 MonoReflectionModuleBuilder *file_module =
4763 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4764 if (file_module != moduleb) {
4765 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4767 if (file_module->types) {
4768 for (j = 0; j < file_module->num_types; ++j) {
4769 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4775 if (assemblyb->loaded_modules) {
4776 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4777 MonoReflectionModule *file_module =
4778 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4779 mono_image_fill_file_table (domain, file_module, assembly);
4781 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4784 if (assemblyb->type_forwarders)
4785 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4787 /* Emit MANIFESTRESOURCE table */
4789 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4791 MonoReflectionModuleBuilder *file_module =
4792 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4793 /* The table for the main module is emitted later */
4794 if (file_module != moduleb) {
4796 if (file_module->resources) {
4797 int len = mono_array_length (file_module->resources);
4798 for (j = 0; j < len; ++j) {
4799 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4800 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4807 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4810 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4811 * for the modulebuilder @moduleb.
4812 * At the end of the process, method and field tokens are fixed up and the
4813 * on-disk compressed metadata representation is created.
4816 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4818 MonoDynamicTable *table;
4819 MonoDynamicImage *assembly;
4820 MonoReflectionAssemblyBuilder *assemblyb;
4826 assemblyb = moduleb->assemblyb;
4827 assembly = moduleb->dynamic_image;
4828 domain = mono_object_domain (assemblyb);
4830 if (assembly->text_rva)
4833 assembly->text_rva = START_TEXT_RVA;
4835 if (moduleb->is_main) {
4836 mono_image_emit_manifest (moduleb);
4839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840 table->rows = 1; /* .<Module> */
4842 alloc_table (table, table->rows);
4844 * Set the first entry.
4846 values = table->values + table->columns;
4847 values [MONO_TYPEDEF_FLAGS] = 0;
4848 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4849 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4850 values [MONO_TYPEDEF_EXTENDS] = 0;
4851 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4852 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4855 * handle global methods
4856 * FIXME: test what to do when global methods are defined in multiple modules.
4858 if (moduleb->global_methods) {
4859 table = &assembly->tables [MONO_TABLE_METHOD];
4860 table->rows += mono_array_length (moduleb->global_methods);
4861 alloc_table (table, table->rows);
4862 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4863 mono_image_get_method_info (
4864 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4866 if (moduleb->global_fields) {
4867 table = &assembly->tables [MONO_TABLE_FIELD];
4868 table->rows += mono_array_length (moduleb->global_fields);
4869 alloc_table (table, table->rows);
4870 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4871 mono_image_get_field_info (
4872 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4875 table = &assembly->tables [MONO_TABLE_MODULE];
4876 alloc_table (table, 1);
4877 mono_image_fill_module_table (domain, moduleb, assembly);
4879 /* Collect all types into a list sorted by their table_idx */
4880 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4883 for (i = 0; i < moduleb->num_types; ++i) {
4884 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4885 collect_types (&types, type);
4888 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4889 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4890 table->rows += mono_ptr_array_size (types);
4891 alloc_table (table, table->rows);
4894 * Emit type names + namespaces at one place inside the string heap,
4895 * so load_class_names () needs to touch fewer pages.
4897 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4898 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4899 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4901 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4902 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4903 string_heap_insert_mstring (&assembly->sheap, tb->name);
4906 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4907 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4908 mono_image_get_type_info (domain, type, assembly);
4912 * table->rows is already set above and in mono_image_fill_module_table.
4914 /* add all the custom attributes at the end, once all the indexes are stable */
4915 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4917 /* CAS assembly permissions */
4918 if (assemblyb->permissions_minimum)
4919 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4920 if (assemblyb->permissions_optional)
4921 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4922 if (assemblyb->permissions_refused)
4923 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4925 module_add_cattrs (assembly, moduleb);
4928 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4930 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4931 * the final tokens and don't need another fixup pass. */
4933 if (moduleb->global_methods) {
4934 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4935 MonoReflectionMethodBuilder *mb = mono_array_get (
4936 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4937 mono_image_add_methodimpl (assembly, mb);
4941 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4942 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4943 if (type->methods) {
4944 for (j = 0; j < type->num_methods; ++j) {
4945 MonoReflectionMethodBuilder *mb = mono_array_get (
4946 type->methods, MonoReflectionMethodBuilder*, j);
4948 mono_image_add_methodimpl (assembly, mb);
4953 mono_ptr_array_destroy (types);
4955 fixup_cattrs (assembly);
4958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4961 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4963 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4970 guint32 import_lookup_table;
4974 guint32 import_address_table_rva;
4982 #ifndef DISABLE_REFLECTION_EMIT
4985 * mono_image_insert_string:
4986 * @module: module builder object
4989 * Insert @str into the user string stream of @module.
4992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4994 MonoDynamicImage *assembly;
4999 if (!module->dynamic_image)
5000 mono_image_module_basic_init (module);
5002 assembly = module->dynamic_image;
5004 if (assembly->save) {
5005 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5006 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5009 char *swapped = g_malloc (2 * mono_string_length (str));
5010 const char *p = (const char*)mono_string_chars (str);
5012 swap_with_size (swapped, p, 2, mono_string_length (str));
5013 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5017 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5019 mono_image_add_stream_data (&assembly->us, "", 1);
5021 idx = assembly->us.index ++;
5024 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5026 return MONO_TOKEN_STRING | idx;
5030 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5034 MonoMethodSignature *sig;
5036 klass = obj->vtable->klass;
5037 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5038 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5039 MonoMethodSignature *old;
5040 guint32 sig_token, parent;
5043 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5045 nargs = mono_array_length (opt_param_types);
5046 old = mono_method_signature (method);
5047 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5049 sig->hasthis = old->hasthis;
5050 sig->explicit_this = old->explicit_this;
5051 sig->call_convention = old->call_convention;
5052 sig->generic_param_count = old->generic_param_count;
5053 sig->param_count = old->param_count + nargs;
5054 sig->sentinelpos = old->param_count;
5055 sig->ret = old->ret;
5057 for (i = 0; i < old->param_count; i++)
5058 sig->params [i] = old->params [i];
5060 for (i = 0; i < nargs; i++) {
5061 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5062 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5065 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5066 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5067 parent >>= MONO_TYPEDEFORREF_BITS;
5069 parent <<= MONO_MEMBERREF_PARENT_BITS;
5070 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5072 sig_token = method_encode_signature (assembly, sig);
5073 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5074 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5075 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5076 ReflectionMethodBuilder rmb;
5077 guint32 parent, sig_token;
5078 int nopt_args, nparams, ngparams, i;
5081 reflection_methodbuilder_from_method_builder (&rmb, mb);
5082 rmb.opt_types = opt_param_types;
5083 nopt_args = mono_array_length (opt_param_types);
5085 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5086 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5087 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5089 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5090 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5091 sig->call_convention = rmb.call_conv;
5092 sig->generic_param_count = ngparams;
5093 sig->param_count = nparams + nopt_args;
5094 sig->sentinelpos = nparams;
5095 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5097 for (i = 0; i < nparams; i++) {
5098 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5099 sig->params [i] = mono_reflection_type_get_handle (rt);
5102 for (i = 0; i < nopt_args; i++) {
5103 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5104 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5107 sig_token = method_builder_encode_signature (assembly, &rmb);
5109 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5110 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5112 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5113 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5115 name = mono_string_to_utf8 (rmb.name);
5116 token = mono_image_get_varargs_method_token (
5117 assembly, parent, name, sig_token);
5120 g_error ("requested method token for %s\n", klass->name);
5123 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5124 register_dyn_token (assembly, token, obj);
5129 * mono_image_create_token:
5130 * @assembly: a dynamic assembly
5132 * @register_token: Whenever to register the token in the assembly->tokens hash.
5134 * Get a token to insert in the IL code stream for the given MemberInfo.
5135 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5136 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5140 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5141 gboolean create_open_instance, gboolean register_token)
5146 klass = obj->vtable->klass;
5148 /* Check for user defined reflection objects */
5149 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5150 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5151 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5153 if (strcmp (klass->name, "MethodBuilder") == 0) {
5154 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5155 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5157 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5158 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5160 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5161 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5162 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5163 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5164 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5166 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5167 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5169 token = mono_image_get_ctorbuilder_token (assembly, mb);
5170 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5171 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5172 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5173 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5174 if (tb->generic_params) {
5175 token = mono_image_get_generic_field_token (assembly, fb);
5177 if (tb->module->dynamic_image == assembly) {
5178 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5180 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5183 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5185 if (create_open_instance && tb->generic_params) {
5187 init_type_builder_generics (obj);
5188 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5190 token = mono_metadata_token_from_dor (token);
5191 } else if (tb->module->dynamic_image == assembly) {
5192 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5195 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5196 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5198 } else if (strcmp (klass->name, "MonoType") == 0) {
5199 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5200 MonoClass *mc = mono_class_from_mono_type (type);
5201 token = mono_metadata_token_from_dor (
5202 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5203 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5204 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5205 token = mono_metadata_token_from_dor (
5206 mono_image_typedef_or_ref (assembly, type));
5207 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5208 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5209 token = mono_metadata_token_from_dor (
5210 mono_image_typedef_or_ref (assembly, type));
5211 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5212 strcmp (klass->name, "MonoMethod") == 0 ||
5213 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5214 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5215 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5216 if (m->method->is_inflated) {
5217 if (create_open_instance)
5218 token = mono_image_get_methodspec_token (assembly, m->method);
5220 token = mono_image_get_inflated_method_token (assembly, m->method);
5221 } else if ((m->method->klass->image == &assembly->image) &&
5222 !m->method->klass->generic_class) {
5223 static guint32 method_table_idx = 0xffffff;
5224 if (m->method->klass->wastypebuilder) {
5225 /* we use the same token as the one that was assigned
5226 * to the Methodbuilder.
5227 * FIXME: do the equivalent for Fields.
5229 token = m->method->token;
5232 * Each token should have a unique index, but the indexes are
5233 * assigned by managed code, so we don't know about them. An
5234 * easy solution is to count backwards...
5236 method_table_idx --;
5237 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5240 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5242 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5243 } else if (strcmp (klass->name, "MonoField") == 0) {
5244 MonoReflectionField *f = (MonoReflectionField *)obj;
5245 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5246 static guint32 field_table_idx = 0xffffff;
5248 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5250 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5252 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5253 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5254 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5255 token = mono_image_get_array_token (assembly, m);
5256 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5257 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5258 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5259 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5260 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5261 token = mono_metadata_token_from_dor (
5262 mono_image_typedef_or_ref (assembly, type));
5263 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5264 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5265 token = mono_image_get_field_on_inst_token (assembly, f);
5266 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5267 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5268 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5269 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5270 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5271 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5272 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5273 MonoReflectionType *type = (MonoReflectionType *)obj;
5274 token = mono_metadata_token_from_dor (
5275 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5277 g_error ("requested token for %s\n", klass->name);
5281 mono_image_register_token (assembly, token, obj);
5287 * mono_image_register_token:
5289 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5290 * the Module.ResolveXXXToken () methods to work.
5293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5297 dynamic_image_lock (assembly);
5298 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5300 /* There could be multiple MethodInfo objects with the same token */
5301 //g_assert (prev == obj);
5303 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5305 dynamic_image_unlock (assembly);
5308 static MonoDynamicImage*
5309 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5311 static const guchar entrycode [16] = {0xff, 0x25, 0};
5312 MonoDynamicImage *image;
5315 const char *version;
5317 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5318 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5320 version = mono_get_runtime_info ()->runtime_version;
5323 /* The MonoGHashTable's need GC tracking */
5324 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5326 image = g_new0 (MonoDynamicImage, 1);
5329 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5331 /*g_print ("created image %p\n", image);*/
5332 /* keep in sync with image.c */
5333 image->image.name = assembly_name;
5334 image->image.assembly_name = image->image.name; /* they may be different */
5335 image->image.module_name = module_name;
5336 image->image.version = g_strdup (version);
5337 image->image.md_version_major = 1;
5338 image->image.md_version_minor = 1;
5339 image->image.dynamic = TRUE;
5341 image->image.references = g_new0 (MonoAssembly*, 1);
5342 image->image.references [0] = NULL;
5344 mono_image_init (&image->image);
5346 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");
5347 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5348 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5349 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5350 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5351 image->handleref = g_hash_table_new (NULL, NULL);
5352 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");
5353 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5354 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");
5355 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");
5356 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5357 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5358 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5359 image->gen_params = g_ptr_array_new ();
5360 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5362 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5363 string_heap_init (&image->sheap);
5364 mono_image_add_stream_data (&image->us, "", 1);
5365 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5366 /* import tables... */
5367 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5368 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5369 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5370 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5371 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5372 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5373 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5374 stream_data_align (&image->code);
5376 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5378 for (i=0; i < MONO_TABLE_NUM; ++i) {
5379 image->tables [i].next_idx = 1;
5380 image->tables [i].columns = table_sizes [i];
5383 image->image.assembly = (MonoAssembly*)assembly;
5384 image->run = assembly->run;
5385 image->save = assembly->save;
5386 image->pe_kind = 0x1; /* ILOnly */
5387 image->machine = 0x14c; /* I386 */
5389 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5391 dynamic_images_lock ();
5393 if (!dynamic_images)
5394 dynamic_images = g_ptr_array_new ();
5396 g_ptr_array_add (dynamic_images, image);
5398 dynamic_images_unlock ();
5405 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5411 release_hashtable (MonoGHashTable **hash)
5414 mono_g_hash_table_destroy (*hash);
5420 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5422 release_hashtable (&image->token_fixups);
5423 release_hashtable (&image->handleref_managed);
5424 release_hashtable (&image->tokens);
5425 release_hashtable (&image->remapped_tokens);
5426 release_hashtable (&image->generic_def_objects);
5427 release_hashtable (&image->methodspec);
5430 // Free dynamic image pass one: Free resources but not image itself
5432 mono_dynamic_image_free (MonoDynamicImage *image)
5434 MonoDynamicImage *di = image;
5439 mono_g_hash_table_destroy (di->methodspec);
5441 g_hash_table_destroy (di->typespec);
5443 g_hash_table_destroy (di->typeref);
5445 g_hash_table_destroy (di->handleref);
5446 if (di->handleref_managed)
5447 mono_g_hash_table_destroy (di->handleref_managed);
5449 mono_g_hash_table_destroy (di->tokens);
5450 if (di->remapped_tokens)
5451 mono_g_hash_table_destroy (di->remapped_tokens);
5452 if (di->generic_def_objects)
5453 mono_g_hash_table_destroy (di->generic_def_objects);
5454 if (di->blob_cache) {
5455 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5456 g_hash_table_destroy (di->blob_cache);
5458 if (di->standalonesig_cache)
5459 g_hash_table_destroy (di->standalonesig_cache);
5460 for (list = di->array_methods; list; list = list->next) {
5461 ArrayMethod *am = (ArrayMethod *)list->data;
5466 g_list_free (di->array_methods);
5467 if (di->gen_params) {
5468 for (i = 0; i < di->gen_params->len; i++) {
5469 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5470 mono_gc_deregister_root ((char*) &entry->gparam);
5473 g_ptr_array_free (di->gen_params, TRUE);
5475 if (di->token_fixups)
5476 mono_g_hash_table_destroy (di->token_fixups);
5477 if (di->method_to_table_idx)
5478 g_hash_table_destroy (di->method_to_table_idx);
5479 if (di->field_to_table_idx)
5480 g_hash_table_destroy (di->field_to_table_idx);
5481 if (di->method_aux_hash)
5482 g_hash_table_destroy (di->method_aux_hash);
5483 if (di->vararg_aux_hash)
5484 g_hash_table_destroy (di->vararg_aux_hash);
5485 g_free (di->strong_name);
5486 g_free (di->win32_res);
5488 g_free (di->public_key);
5490 /*g_print ("string heap destroy for image %p\n", di);*/
5491 mono_dynamic_stream_reset (&di->sheap);
5492 mono_dynamic_stream_reset (&di->code);
5493 mono_dynamic_stream_reset (&di->resources);
5494 mono_dynamic_stream_reset (&di->us);
5495 mono_dynamic_stream_reset (&di->blob);
5496 mono_dynamic_stream_reset (&di->tstream);
5497 mono_dynamic_stream_reset (&di->guid);
5498 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5499 g_free (di->tables [i].values);
5502 dynamic_images_lock ();
5505 g_ptr_array_remove (dynamic_images, di);
5507 dynamic_images_unlock ();
5510 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5512 mono_dynamic_image_free_image (MonoDynamicImage *image)
5514 /* See create_dynamic_mono_image () */
5516 /* Allocated using GC_MALLOC */
5522 #ifndef DISABLE_REFLECTION_EMIT
5525 * mono_image_basic_init:
5526 * @assembly: an assembly builder object
5528 * Create the MonoImage that represents the assembly builder and setup some
5529 * of the helper hash table and the basic metadata streams.
5532 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5534 MonoDynamicAssembly *assembly;
5535 MonoDynamicImage *image;
5536 MonoDomain *domain = mono_object_domain (assemblyb);
5538 if (assemblyb->dynamic_assembly)
5542 /* assembly->assembly.image might be GC allocated */
5543 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5545 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5548 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5550 assembly->assembly.ref_count = 1;
5551 assembly->assembly.dynamic = TRUE;
5552 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5553 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5554 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5555 if (assemblyb->culture)
5556 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5558 assembly->assembly.aname.culture = g_strdup ("");
5560 if (assemblyb->version) {
5561 char *vstr = mono_string_to_utf8 (assemblyb->version);
5562 char **version = g_strsplit (vstr, ".", 4);
5563 char **parts = version;
5564 assembly->assembly.aname.major = atoi (*parts++);
5565 assembly->assembly.aname.minor = atoi (*parts++);
5566 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5567 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5569 g_strfreev (version);
5572 assembly->assembly.aname.major = 0;
5573 assembly->assembly.aname.minor = 0;
5574 assembly->assembly.aname.build = 0;
5575 assembly->assembly.aname.revision = 0;
5578 assembly->run = assemblyb->access != 2;
5579 assembly->save = assemblyb->access != 1;
5580 assembly->domain = domain;
5582 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5583 image->initial_image = TRUE;
5584 assembly->assembly.aname.name = image->image.name;
5585 assembly->assembly.image = &image->image;
5586 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5587 /* -1 to correct for the trailing NULL byte */
5588 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5589 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5591 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5594 mono_domain_assemblies_lock (domain);
5595 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5596 mono_domain_assemblies_unlock (domain);
5598 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5600 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5602 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5605 #endif /* !DISABLE_REFLECTION_EMIT */
5607 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5610 calc_section_size (MonoDynamicImage *assembly)
5614 /* alignment constraints */
5615 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5616 g_assert ((assembly->code.index % 4) == 0);
5617 assembly->meta_size += 3;
5618 assembly->meta_size &= ~3;
5619 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5620 g_assert ((assembly->resources.index % 4) == 0);
5622 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5623 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5626 if (assembly->win32_res) {
5627 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5629 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5630 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5634 assembly->sections [MONO_SECTION_RELOC].size = 12;
5635 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5645 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5649 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5651 ResTreeNode *t1 = (ResTreeNode*)a;
5652 ResTreeNode *t2 = (ResTreeNode*)b;
5654 return t1->id - t2->id;
5658 * resource_tree_create:
5660 * Organize the resources into a resource tree.
5662 static ResTreeNode *
5663 resource_tree_create (MonoArray *win32_resources)
5665 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5669 tree = g_new0 (ResTreeNode, 1);
5671 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5672 MonoReflectionWin32Resource *win32_res =
5673 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5677 /* FIXME: BUG: this stores managed references in unmanaged memory */
5678 lang_node = g_new0 (ResTreeNode, 1);
5679 lang_node->id = win32_res->lang_id;
5680 lang_node->win32_res = win32_res;
5682 /* Create type node if neccesary */
5684 for (l = tree->children; l; l = l->next)
5685 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5686 type_node = (ResTreeNode*)l->data;
5691 type_node = g_new0 (ResTreeNode, 1);
5692 type_node->id = win32_res->res_type;
5695 * The resource types have to be sorted otherwise
5696 * Windows Explorer can't display the version information.
5698 tree->children = g_slist_insert_sorted (tree->children,
5699 type_node, resource_tree_compare_by_id);
5702 /* Create res node if neccesary */
5704 for (l = type_node->children; l; l = l->next)
5705 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5706 res_node = (ResTreeNode*)l->data;
5711 res_node = g_new0 (ResTreeNode, 1);
5712 res_node->id = win32_res->res_id;
5713 type_node->children = g_slist_append (type_node->children, res_node);
5716 res_node->children = g_slist_append (res_node->children, lang_node);
5723 * resource_tree_encode:
5725 * Encode the resource tree into the format used in the PE file.
5728 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5731 MonoPEResourceDir dir;
5732 MonoPEResourceDirEntry dir_entry;
5733 MonoPEResourceDataEntry data_entry;
5735 guint32 res_id_entries;
5738 * For the format of the resource directory, see the article
5739 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5743 memset (&dir, 0, sizeof (dir));
5744 memset (&dir_entry, 0, sizeof (dir_entry));
5745 memset (&data_entry, 0, sizeof (data_entry));
5747 g_assert (sizeof (dir) == 16);
5748 g_assert (sizeof (dir_entry) == 8);
5749 g_assert (sizeof (data_entry) == 16);
5751 node->offset = p - begin;
5753 /* IMAGE_RESOURCE_DIRECTORY */
5754 res_id_entries = g_slist_length (node->children);
5755 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5757 memcpy (p, &dir, sizeof (dir));
5760 /* Reserve space for entries */
5762 p += sizeof (dir_entry) * res_id_entries;
5764 /* Write children */
5765 for (l = node->children; l; l = l->next) {
5766 ResTreeNode *child = (ResTreeNode*)l->data;
5768 if (child->win32_res) {
5771 child->offset = p - begin;
5773 /* IMAGE_RESOURCE_DATA_ENTRY */
5774 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5775 size = mono_array_length (child->win32_res->res_data);
5776 data_entry.rde_size = GUINT32_TO_LE (size);
5778 memcpy (p, &data_entry, sizeof (data_entry));
5779 p += sizeof (data_entry);
5781 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5784 resource_tree_encode (child, begin, p, &p);
5788 /* IMAGE_RESOURCE_ENTRY */
5789 for (l = node->children; l; l = l->next) {
5790 ResTreeNode *child = (ResTreeNode*)l->data;
5792 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5793 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5795 memcpy (entries, &dir_entry, sizeof (dir_entry));
5796 entries += sizeof (dir_entry);
5803 resource_tree_free (ResTreeNode * node)
5806 for (list = node->children; list; list = list->next)
5807 resource_tree_free ((ResTreeNode*)list->data);
5808 g_slist_free(node->children);
5813 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5818 MonoReflectionWin32Resource *win32_res;
5821 if (!assemblyb->win32_resources)
5825 * Resources are stored in a three level tree inside the PE file.
5826 * - level one contains a node for each type of resource
5827 * - level two contains a node for each resource
5828 * - level three contains a node for each instance of a resource for a
5829 * specific language.
5832 tree = resource_tree_create (assemblyb->win32_resources);
5834 /* Estimate the size of the encoded tree */
5836 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5837 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5838 size += mono_array_length (win32_res->res_data);
5840 /* Directory structure */
5841 size += mono_array_length (assemblyb->win32_resources) * 256;
5842 p = buf = (char *)g_malloc (size);
5844 resource_tree_encode (tree, p, p, &p);
5846 g_assert (p - buf <= size);
5848 assembly->win32_res = (char *)g_malloc (p - buf);
5849 assembly->win32_res_size = p - buf;
5850 memcpy (assembly->win32_res, buf, p - buf);
5853 resource_tree_free (tree);
5857 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5859 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5862 p += sizeof (MonoPEResourceDir);
5863 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5864 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5865 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5866 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5867 fixup_resource_directory (res_section, child, rva);
5869 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5870 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5873 p += sizeof (MonoPEResourceDirEntry);
5878 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5881 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5882 g_error ("WriteFile returned %d\n", GetLastError ());
5886 * mono_image_create_pefile:
5887 * @mb: a module builder object
5889 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5890 * assembly->pefile where it can be easily retrieved later in chunks.
5893 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5895 MonoMSDOSHeader *msdos;
5896 MonoDotNetHeader *header;
5897 MonoSectionTable *section;
5898 MonoCLIHeader *cli_header;
5899 guint32 size, image_size, virtual_base, text_offset;
5900 guint32 header_start, section_start, file_offset, virtual_offset;
5901 MonoDynamicImage *assembly;
5902 MonoReflectionAssemblyBuilder *assemblyb;
5903 MonoDynamicStream pefile_stream = {0};
5904 MonoDynamicStream *pefile = &pefile_stream;
5906 guint32 *rva, value;
5908 static const unsigned char msheader[] = {
5909 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5910 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5913 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5914 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5915 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5916 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5919 assemblyb = mb->assemblyb;
5921 mono_image_basic_init (assemblyb);
5922 assembly = mb->dynamic_image;
5924 assembly->pe_kind = assemblyb->pe_kind;
5925 assembly->machine = assemblyb->machine;
5926 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5927 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5929 mono_image_build_metadata (mb);
5931 if (mb->is_main && assemblyb->resources) {
5932 int len = mono_array_length (assemblyb->resources);
5933 for (i = 0; i < len; ++i)
5934 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5937 if (mb->resources) {
5938 int len = mono_array_length (mb->resources);
5939 for (i = 0; i < len; ++i)
5940 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5943 build_compressed_metadata (assembly);
5946 assembly_add_win32_resources (assembly, assemblyb);
5948 nsections = calc_section_size (assembly);
5950 /* The DOS header and stub */
5951 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5952 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5954 /* the dotnet header */
5955 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5957 /* the section tables */
5958 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5960 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5961 virtual_offset = VIRT_ALIGN;
5964 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5965 if (!assembly->sections [i].size)
5968 file_offset += FILE_ALIGN - 1;
5969 file_offset &= ~(FILE_ALIGN - 1);
5970 virtual_offset += VIRT_ALIGN - 1;
5971 virtual_offset &= ~(VIRT_ALIGN - 1);
5973 assembly->sections [i].offset = file_offset;
5974 assembly->sections [i].rva = virtual_offset;
5976 file_offset += assembly->sections [i].size;
5977 virtual_offset += assembly->sections [i].size;
5978 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5981 file_offset += FILE_ALIGN - 1;
5982 file_offset &= ~(FILE_ALIGN - 1);
5984 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5986 /* back-patch info */
5987 msdos = (MonoMSDOSHeader*)pefile->data;
5988 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5990 header = (MonoDotNetHeader*)(pefile->data + header_start);
5991 header->pesig [0] = 'P';
5992 header->pesig [1] = 'E';
5994 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5995 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5996 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5997 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5998 if (assemblyb->pekind == 1) {
6000 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6003 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6006 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6008 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6009 header->pe.pe_major = 6;
6010 header->pe.pe_minor = 0;
6011 size = assembly->sections [MONO_SECTION_TEXT].size;
6012 size += FILE_ALIGN - 1;
6013 size &= ~(FILE_ALIGN - 1);
6014 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6015 size = assembly->sections [MONO_SECTION_RSRC].size;
6016 size += FILE_ALIGN - 1;
6017 size &= ~(FILE_ALIGN - 1);
6018 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6019 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6020 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6021 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6022 /* pe_rva_entry_point always at the beginning of the text section */
6023 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6025 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6026 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6027 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6028 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6029 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6030 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6031 size = section_start;
6032 size += FILE_ALIGN - 1;
6033 size &= ~(FILE_ALIGN - 1);
6034 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6036 size += VIRT_ALIGN - 1;
6037 size &= ~(VIRT_ALIGN - 1);
6038 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6041 // Translate the PEFileKind value to the value expected by the Windows loader
6047 // PEFileKinds.Dll == 1
6048 // PEFileKinds.ConsoleApplication == 2
6049 // PEFileKinds.WindowApplication == 3
6052 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6053 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6055 if (assemblyb->pekind == 3)
6060 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6062 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6063 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6064 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6065 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6066 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6067 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6069 /* fill data directory entries */
6071 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6072 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6074 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6075 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6077 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6078 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6079 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6080 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6081 /* patch entrypoint name */
6082 if (assemblyb->pekind == 1)
6083 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6085 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6086 /* patch imported function RVA name */
6087 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6088 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6090 /* the import table */
6091 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6092 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6093 /* patch imported dll RVA name and other entries in the dir */
6094 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6095 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6096 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6097 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6098 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6099 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6101 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6102 value = (assembly->text_rva + assembly->imp_names_offset);
6103 *p++ = (value) & 0xff;
6104 *p++ = (value >> 8) & (0xff);
6105 *p++ = (value >> 16) & (0xff);
6106 *p++ = (value >> 24) & (0xff);
6108 /* the CLI header info */
6109 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6110 cli_header->ch_size = GUINT32_FROM_LE (72);
6111 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6112 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6113 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6114 if (assemblyb->entry_point) {
6115 guint32 table_idx = 0;
6116 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6117 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6118 table_idx = methodb->table_idx;
6120 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6122 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6124 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6126 /* The embedded managed resources */
6127 text_offset = assembly->text_rva + assembly->code.index;
6128 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6129 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6130 text_offset += assembly->resources.index;
6131 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6132 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6133 text_offset += assembly->meta_size;
6134 if (assembly->strong_name_size) {
6135 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6136 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6137 text_offset += assembly->strong_name_size;
6140 /* write the section tables and section content */
6141 section = (MonoSectionTable*)(pefile->data + section_start);
6142 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6143 static const char section_names [][7] = {
6144 ".text", ".rsrc", ".reloc"
6146 if (!assembly->sections [i].size)
6148 strcpy (section->st_name, section_names [i]);
6149 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6150 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6151 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6152 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6153 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6154 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6155 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6159 checked_write_file (file, pefile->data, pefile->index);
6161 mono_dynamic_stream_reset (pefile);
6163 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6164 if (!assembly->sections [i].size)
6167 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6168 g_error ("SetFilePointer returned %d\n", GetLastError ());
6171 case MONO_SECTION_TEXT:
6172 /* patch entry point */
6173 p = (guchar*)(assembly->code.data + 2);
6174 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6175 *p++ = (value) & 0xff;
6176 *p++ = (value >> 8) & 0xff;
6177 *p++ = (value >> 16) & 0xff;
6178 *p++ = (value >> 24) & 0xff;
6180 checked_write_file (file, assembly->code.data, assembly->code.index);
6181 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6182 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6183 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6186 g_free (assembly->image.raw_metadata);
6188 case MONO_SECTION_RELOC: {
6192 guint16 type_and_offset;
6196 g_assert (sizeof (reloc) == 12);
6198 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6199 reloc.block_size = GUINT32_FROM_LE (12);
6202 * the entrypoint is always at the start of the text section
6203 * 3 is IMAGE_REL_BASED_HIGHLOW
6204 * 2 is patch_size_rva - text_rva
6206 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6209 checked_write_file (file, &reloc, sizeof (reloc));
6213 case MONO_SECTION_RSRC:
6214 if (assembly->win32_res) {
6216 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6217 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6218 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6222 g_assert_not_reached ();
6226 /* check that the file is properly padded */
6227 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6228 g_error ("SetFilePointer returned %d\n", GetLastError ());
6229 if (! SetEndOfFile (file))
6230 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6232 mono_dynamic_stream_reset (&assembly->code);
6233 mono_dynamic_stream_reset (&assembly->us);
6234 mono_dynamic_stream_reset (&assembly->blob);
6235 mono_dynamic_stream_reset (&assembly->guid);
6236 mono_dynamic_stream_reset (&assembly->sheap);
6238 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6239 g_hash_table_destroy (assembly->blob_cache);
6240 assembly->blob_cache = NULL;
6243 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6246 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6248 g_assert_not_reached ();
6251 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6253 #ifndef DISABLE_REFLECTION_EMIT
6255 MonoReflectionModule *
6256 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6260 MonoImageOpenStatus status;
6261 MonoDynamicAssembly *assembly;
6262 guint32 module_count;
6263 MonoImage **new_modules;
6264 gboolean *new_modules_loaded;
6266 name = mono_string_to_utf8 (fileName);
6268 image = mono_image_open (name, &status);
6271 if (status == MONO_IMAGE_ERROR_ERRNO)
6272 exc = mono_get_exception_file_not_found (fileName);
6274 exc = mono_get_exception_bad_image_format (name);
6276 mono_raise_exception (exc);
6281 assembly = ab->dynamic_assembly;
6282 image->assembly = (MonoAssembly*)assembly;
6284 module_count = image->assembly->image->module_count;
6285 new_modules = g_new0 (MonoImage *, module_count + 1);
6286 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6288 if (image->assembly->image->modules)
6289 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6290 if (image->assembly->image->modules_loaded)
6291 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6292 new_modules [module_count] = image;
6293 new_modules_loaded [module_count] = TRUE;
6294 mono_image_addref (image);
6296 g_free (image->assembly->image->modules);
6297 image->assembly->image->modules = new_modules;
6298 image->assembly->image->modules_loaded = new_modules_loaded;
6299 image->assembly->image->module_count ++;
6301 mono_assembly_load_references (image, &status);
6303 mono_image_close (image);
6304 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6307 return mono_module_get_object (mono_domain_get (), image);
6310 #endif /* DISABLE_REFLECTION_EMIT */
6313 * We need to return always the same object for MethodInfo, FieldInfo etc..
6314 * but we need to consider the reflected type.
6315 * type uses a different hash, since it uses custom hash/equal functions.
6320 MonoClass *refclass;
6324 reflected_equal (gconstpointer a, gconstpointer b) {
6325 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6326 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6328 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6332 reflected_hash (gconstpointer a) {
6333 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6334 return mono_aligned_addr_hash (ea->item);
6337 #define CHECK_OBJECT(t,p,k) \
6343 mono_domain_lock (domain); \
6344 if (!domain->refobject_hash) \
6345 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"); \
6346 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6347 mono_domain_unlock (domain); \
6350 mono_domain_unlock (domain); \
6353 #ifdef HAVE_BOEHM_GC
6354 /* ReflectedEntry doesn't need to be GC tracked */
6355 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6356 #define FREE_REFENTRY(entry) g_free ((entry))
6357 #define REFENTRY_REQUIRES_CLEANUP
6359 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6361 #define FREE_REFENTRY(entry)
6364 #define CACHE_OBJECT(t,p,o,k) \
6367 ReflectedEntry pe; \
6369 pe.refclass = (k); \
6370 mono_domain_lock (domain); \
6371 if (!domain->refobject_hash) \
6372 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"); \
6373 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6375 ReflectedEntry *e = ALLOC_REFENTRY; \
6377 e->refclass = (k); \
6378 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6381 mono_domain_unlock (domain); \
6386 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6388 mono_domain_lock (domain);
6389 if (domain->refobject_hash) {
6391 gpointer orig_pe, orig_value;
6394 pe.refclass = klass;
6395 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6396 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6397 FREE_REFENTRY (orig_pe);
6400 mono_domain_unlock (domain);
6403 #ifdef REFENTRY_REQUIRES_CLEANUP
6405 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6407 FREE_REFENTRY (key);
6412 mono_reflection_cleanup_domain (MonoDomain *domain)
6414 if (domain->refobject_hash) {
6415 /*let's avoid scanning the whole hashtable if not needed*/
6416 #ifdef REFENTRY_REQUIRES_CLEANUP
6417 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6419 mono_g_hash_table_destroy (domain->refobject_hash);
6420 domain->refobject_hash = NULL;
6424 #ifndef DISABLE_REFLECTION_EMIT
6426 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6428 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6432 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6434 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6438 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6440 MonoDynamicImage *image = moduleb->dynamic_image;
6441 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6445 MonoImage **new_modules;
6447 char *name, *fqname;
6449 * FIXME: we already created an image in mono_image_basic_init (), but
6450 * we don't know which module it belongs to, since that is only
6451 * determined at assembly save time.
6453 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6454 name = mono_string_to_utf8 (ab->name);
6455 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6456 if (!mono_error_ok (&error)) {
6458 mono_error_raise_exception (&error);
6460 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6462 moduleb->module.image = &image->image;
6463 moduleb->dynamic_image = image;
6464 register_module (mono_object_domain (moduleb), moduleb, image);
6466 /* register the module with the assembly */
6467 ass = ab->dynamic_assembly->assembly.image;
6468 module_count = ass->module_count;
6469 new_modules = g_new0 (MonoImage *, module_count + 1);
6472 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6473 new_modules [module_count] = &image->image;
6474 mono_image_addref (&image->image);
6476 g_free (ass->modules);
6477 ass->modules = new_modules;
6478 ass->module_count ++;
6483 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6485 MonoDynamicImage *image = moduleb->dynamic_image;
6487 g_assert (type->type);
6488 image->wrappers_type = mono_class_from_mono_type (type->type);
6494 * mono_assembly_get_object:
6495 * @domain: an app domain
6496 * @assembly: an assembly
6498 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6500 MonoReflectionAssembly*
6501 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6503 static MonoClass *assembly_type;
6504 MonoReflectionAssembly *res;
6506 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6507 if (!assembly_type) {
6508 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6510 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6512 assembly_type = klass;
6514 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6515 res->assembly = assembly;
6517 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6522 MonoReflectionModule*
6523 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6525 static MonoClass *module_type;
6526 MonoReflectionModule *res;
6529 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6531 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6533 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6535 module_type = klass;
6537 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6540 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6542 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6543 basename = g_path_get_basename (image->name);
6544 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6545 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6549 if (image->assembly->image == image) {
6550 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6554 if (image->assembly->image->modules) {
6555 for (i = 0; i < image->assembly->image->module_count; i++) {
6556 if (image->assembly->image->modules [i] == image)
6557 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6559 g_assert (res->token);
6563 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6566 MonoReflectionModule*
6567 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6569 static MonoClass *module_type;
6570 MonoReflectionModule *res;
6571 MonoTableInfo *table;
6572 guint32 cols [MONO_FILE_SIZE];
6574 guint32 i, name_idx;
6578 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6580 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6582 module_type = klass;
6584 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6586 table = &image->tables [MONO_TABLE_FILE];
6587 g_assert (table_index < table->rows);
6588 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6591 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6592 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6594 /* Check whenever the row has a corresponding row in the moduleref table */
6595 table = &image->tables [MONO_TABLE_MODULEREF];
6596 for (i = 0; i < table->rows; ++i) {
6597 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6598 val = mono_metadata_string_heap (image, name_idx);
6599 if (strcmp (val, name) == 0)
6600 res->image = image->modules [i];
6603 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6604 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6605 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6606 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6607 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6613 verify_safe_for_managed_space (MonoType *type)
6615 switch (type->type) {
6617 case MONO_TYPE_ARRAY:
6618 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6620 return verify_safe_for_managed_space (type->data.type);
6621 case MONO_TYPE_SZARRAY:
6622 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6623 case MONO_TYPE_GENERICINST: {
6624 MonoGenericInst *inst = type->data.generic_class->inst;
6628 for (i = 0; i < inst->type_argc; ++i)
6629 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6635 case MONO_TYPE_MVAR:
6643 mono_type_normalize (MonoType *type)
6646 MonoGenericClass *gclass;
6647 MonoGenericInst *ginst;
6649 MonoGenericContainer *gcontainer;
6650 MonoType **argv = NULL;
6651 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6653 if (type->type != MONO_TYPE_GENERICINST)
6656 gclass = type->data.generic_class;
6657 ginst = gclass->context.class_inst;
6658 if (!ginst->is_open)
6661 gtd = gclass->container_class;
6662 gcontainer = gtd->generic_container;
6663 argv = g_newa (MonoType*, ginst->type_argc);
6665 for (i = 0; i < ginst->type_argc; ++i) {
6666 MonoType *t = ginst->type_argv [i], *norm;
6667 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6668 is_denorm_gtd = FALSE;
6669 norm = mono_type_normalize (t);
6672 requires_rebind = TRUE;
6676 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6678 if (requires_rebind) {
6679 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6680 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6686 * mono_type_get_object:
6687 * @domain: an app domain
6690 * Return an System.MonoType object representing the type @type.
6693 mono_type_get_object (MonoDomain *domain, MonoType *type)
6696 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6697 mono_error_raise_exception (&error);
6703 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6705 MonoType *norm_type;
6706 MonoReflectionType *res;
6709 mono_error_init (error);
6711 klass = mono_class_from_mono_type (type);
6713 /*we must avoid using @type as it might have come
6714 * from a mono_metadata_type_dup and the caller
6715 * expects that is can be freed.
6716 * Using the right type from
6718 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6720 /* void is very common */
6721 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6722 return (MonoReflectionType*)domain->typeof_void;
6725 * If the vtable of the given class was already created, we can use
6726 * the MonoType from there and avoid all locking and hash table lookups.
6728 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6729 * that the resulting object is different.
6731 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6732 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6733 if (vtable && vtable->type)
6734 return (MonoReflectionType *)vtable->type;
6737 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6738 mono_domain_lock (domain);
6739 if (!domain->type_hash)
6740 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6741 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6742 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6743 mono_domain_unlock (domain);
6744 mono_loader_unlock ();
6748 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6749 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6750 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6751 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6752 * artifact of how generics are encoded and should be transparent to managed code so we
6753 * need to weed out this diference when retrieving managed System.Type objects.
6755 norm_type = mono_type_normalize (type);
6756 if (norm_type != type) {
6757 res = mono_type_get_object_checked (domain, norm_type, error);
6758 if (!mono_error_ok (error))
6760 mono_g_hash_table_insert (domain->type_hash, type, res);
6761 mono_domain_unlock (domain);
6762 mono_loader_unlock ();
6766 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6767 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6770 if (!verify_safe_for_managed_space (type)) {
6771 mono_domain_unlock (domain);
6772 mono_loader_unlock ();
6773 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6776 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6777 gboolean is_type_done = TRUE;
6778 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6779 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6780 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6782 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6783 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6785 if (gparam->owner && gparam->owner->is_method) {
6786 MonoMethod *method = gparam->owner->owner.method;
6787 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6788 is_type_done = FALSE;
6789 } else if (gparam->owner && !gparam->owner->is_method) {
6790 MonoClass *klass = gparam->owner->owner.klass;
6791 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6792 is_type_done = FALSE;
6796 /* g_assert_not_reached (); */
6797 /* should this be considered an error condition? */
6798 if (is_type_done && !type->byref) {
6799 mono_domain_unlock (domain);
6800 mono_loader_unlock ();
6801 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6804 /* This is stored in vtables/JITted code so it has to be pinned */
6805 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6806 if (!mono_error_ok (error))
6810 mono_g_hash_table_insert (domain->type_hash, type, res);
6812 if (type->type == MONO_TYPE_VOID)
6813 domain->typeof_void = (MonoObject*)res;
6815 mono_domain_unlock (domain);
6816 mono_loader_unlock ();
6821 * mono_method_get_object:
6822 * @domain: an app domain
6824 * @refclass: the reflected type (can be NULL)
6826 * Return an System.Reflection.MonoMethod object representing the method @method.
6828 MonoReflectionMethod*
6829 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6832 * We use the same C representation for methods and constructors, but the type
6833 * name in C# is different.
6835 static MonoClass *System_Reflection_MonoMethod = NULL;
6836 static MonoClass *System_Reflection_MonoCMethod = NULL;
6837 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6838 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6840 MonoReflectionType *rt;
6842 MonoReflectionMethod *ret;
6844 if (method->is_inflated) {
6845 MonoReflectionGenericMethod *gret;
6848 refclass = method->klass;
6849 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6850 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6851 if (!System_Reflection_MonoGenericCMethod)
6852 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6853 klass = System_Reflection_MonoGenericCMethod;
6855 if (!System_Reflection_MonoGenericMethod)
6856 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6857 klass = System_Reflection_MonoGenericMethod;
6859 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6860 gret->method.method = method;
6862 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6864 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6865 mono_error_raise_exception (&error); /* FIXME don't raise here */
6867 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6869 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6873 refclass = method->klass;
6875 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6876 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6877 if (!System_Reflection_MonoCMethod)
6878 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6879 klass = System_Reflection_MonoCMethod;
6882 if (!System_Reflection_MonoMethod)
6883 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6884 klass = System_Reflection_MonoMethod;
6886 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6887 ret->method = method;
6889 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6890 mono_error_raise_exception (&error); /* FIXME don't raise here */;
6892 MONO_OBJECT_SETREF (ret, reftype, rt);
6894 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6898 * mono_method_clear_object:
6900 * Clear the cached reflection objects for the dynamic method METHOD.
6903 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6906 g_assert (method_is_dynamic (method));
6908 klass = method->klass;
6910 clear_cached_object (domain, method, klass);
6911 klass = klass->parent;
6913 /* Added by mono_param_get_objects () */
6914 clear_cached_object (domain, &(method->signature), NULL);
6915 klass = method->klass;
6917 clear_cached_object (domain, &(method->signature), klass);
6918 klass = klass->parent;
6923 * mono_field_get_object:
6924 * @domain: an app domain
6928 * Return an System.Reflection.MonoField object representing the field @field
6931 MonoReflectionField*
6932 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6935 MonoReflectionField *result;
6936 result = mono_field_get_object_checked (domain, klass, field, &error);
6937 mono_error_raise_exception (&error);
6942 * mono_field_get_object_checked:
6943 * @domain: an app domain
6946 * @error: set on error
6948 * Return an System.Reflection.MonoField object representing the field @field
6949 * in class @klass. On error, returns NULL and sets @error.
6951 MonoReflectionField*
6952 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
6954 MonoReflectionType *rt;
6955 MonoReflectionField *res;
6956 static MonoClass *monofield_klass;
6958 mono_error_init (error);
6960 CHECK_OBJECT (MonoReflectionField *, field, klass);
6961 if (!monofield_klass)
6962 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6963 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6966 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6968 if (is_field_on_inst (field)) {
6969 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6971 rt = mono_type_get_object_checked (domain, field->type, error);
6972 if (!mono_error_ok (error))
6975 MONO_OBJECT_SETREF (res, type, rt);
6978 rt = mono_type_get_object_checked (domain, field->type, error);
6979 if (!mono_error_ok (error))
6982 MONO_OBJECT_SETREF (res, type, rt);
6984 res->attrs = mono_field_get_flags (field);
6986 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6990 * mono_property_get_object:
6991 * @domain: an app domain
6993 * @property: a property
6995 * Return an System.Reflection.MonoProperty object representing the property @property
6998 MonoReflectionProperty*
6999 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7001 MonoReflectionProperty *res;
7002 static MonoClass *monoproperty_klass;
7004 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7005 if (!monoproperty_klass)
7006 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7007 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
7009 res->property = property;
7010 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7014 * mono_event_get_object:
7015 * @domain: an app domain
7019 * Return an System.Reflection.MonoEvent object representing the event @event
7022 MonoReflectionEvent*
7023 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7025 MonoReflectionEvent *res;
7026 MonoReflectionMonoEvent *mono_event;
7027 static MonoClass *monoevent_klass;
7029 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7030 if (!monoevent_klass)
7031 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7032 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
7033 mono_event->klass = klass;
7034 mono_event->event = event;
7035 res = (MonoReflectionEvent*)mono_event;
7036 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7040 * mono_get_reflection_missing_object:
7041 * @domain: Domain where the object lives
7043 * Returns the System.Reflection.Missing.Value singleton object
7044 * (of type System.Reflection.Missing).
7046 * Used as the value for ParameterInfo.DefaultValue when Optional
7050 mono_get_reflection_missing_object (MonoDomain *domain)
7053 static MonoClassField *missing_value_field = NULL;
7055 if (!missing_value_field) {
7056 MonoClass *missing_klass;
7057 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7058 mono_class_init (missing_klass);
7059 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7060 g_assert (missing_value_field);
7062 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7068 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7071 *dbnull = mono_get_dbnull_object (domain);
7076 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7078 if (!*reflection_missing)
7079 *reflection_missing = mono_get_reflection_missing_object (domain);
7080 return *reflection_missing;
7084 * mono_param_get_objects:
7085 * @domain: an app domain
7088 * Return an System.Reflection.ParameterInfo array object representing the parameters
7089 * in the method @method.
7092 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7094 static MonoClass *System_Reflection_ParameterInfo;
7095 static MonoClass *System_Reflection_ParameterInfo_array;
7097 MonoArray *res = NULL;
7098 MonoReflectionMethod *member = NULL;
7099 MonoReflectionParameter *param = NULL;
7100 char **names, **blobs = NULL;
7101 guint32 *types = NULL;
7102 MonoType *type = NULL;
7103 MonoObject *dbnull = NULL;
7104 MonoObject *missing = NULL;
7105 MonoMarshalSpec **mspecs;
7106 MonoMethodSignature *sig;
7107 MonoVTable *pinfo_vtable;
7108 MonoReflectionType *rt;
7111 if (!System_Reflection_ParameterInfo_array) {
7114 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7116 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7118 mono_memory_barrier ();
7119 System_Reflection_ParameterInfo = klass;
7122 klass = mono_array_class_get (klass, 1);
7123 mono_memory_barrier ();
7124 System_Reflection_ParameterInfo_array = klass;
7127 sig = mono_method_signature_checked (method, &error);
7128 if (!mono_error_ok (&error))
7129 mono_error_raise_exception (&error);
7131 if (!sig->param_count) {
7132 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7133 mono_error_raise_exception (&error); /* FIXME don't raise here */
7138 /* Note: the cache is based on the address of the signature into the method
7139 * since we already cache MethodInfos with the method as keys.
7141 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7143 member = mono_method_get_object (domain, method, refclass);
7144 names = g_new (char *, sig->param_count);
7145 mono_method_get_param_names (method, (const char **) names);
7147 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7148 mono_method_get_marshal_info (method, mspecs);
7150 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7151 mono_error_raise_exception (&error); /* FIXME don't raise here */
7153 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7154 for (i = 0; i < sig->param_count; ++i) {
7155 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7156 mono_error_raise_exception (&error); /* FIXME don't raise here */
7158 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7159 mono_error_raise_exception (&error); /* FIXME don't raise here */
7161 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7163 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7165 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7167 param->PositionImpl = i;
7168 param->AttrsImpl = sig->params [i]->attrs;
7170 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7171 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7172 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7174 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7178 blobs = g_new0 (char *, sig->param_count);
7179 types = g_new0 (guint32, sig->param_count);
7180 get_default_param_value_blobs (method, blobs, types);
7183 /* Build MonoType for the type from the Constant Table */
7185 type = g_new0 (MonoType, 1);
7186 type->type = (MonoTypeEnum)types [i];
7187 type->data.klass = NULL;
7188 if (types [i] == MONO_TYPE_CLASS)
7189 type->data.klass = mono_defaults.object_class;
7190 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7191 /* For enums, types [i] contains the base type */
7193 type->type = MONO_TYPE_VALUETYPE;
7194 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7196 type->data.klass = mono_class_from_mono_type (type);
7198 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7200 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7201 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7202 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7203 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7205 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7211 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7213 mono_array_setref (res, i, param);
7220 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7222 mono_metadata_free_marshal_spec (mspecs [i]);
7225 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7229 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7231 return mono_param_get_objects_internal (domain, method, NULL);
7235 * mono_method_body_get_object:
7236 * @domain: an app domain
7239 * Return an System.Reflection.MethodBody object representing the method @method.
7241 MonoReflectionMethodBody*
7242 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7244 static MonoClass *System_Reflection_MethodBody = NULL;
7245 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7246 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7248 MonoReflectionMethodBody *ret;
7249 MonoMethodHeader *header;
7251 MonoReflectionType *rt;
7252 guint32 method_rva, local_var_sig_token;
7254 unsigned char format, flags;
7257 /* for compatibility with .net */
7258 if (method_is_dynamic (method))
7259 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7261 if (!System_Reflection_MethodBody)
7262 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7263 if (!System_Reflection_LocalVariableInfo)
7264 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7265 if (!System_Reflection_ExceptionHandlingClause)
7266 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7268 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7270 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7271 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7272 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7273 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7274 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7277 image = method->klass->image;
7278 header = mono_method_get_header (method);
7280 if (!image_is_dynamic (image)) {
7281 /* Obtain local vars signature token */
7282 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7283 ptr = mono_image_rva_map (image, method_rva);
7284 flags = *(const unsigned char *) ptr;
7285 format = flags & METHOD_HEADER_FORMAT_MASK;
7287 case METHOD_HEADER_TINY_FORMAT:
7288 local_var_sig_token = 0;
7290 case METHOD_HEADER_FAT_FORMAT:
7294 local_var_sig_token = read32 (ptr);
7297 g_assert_not_reached ();
7300 local_var_sig_token = 0; //FIXME
7302 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7304 ret->init_locals = header->init_locals;
7305 ret->max_stack = header->max_stack;
7306 ret->local_var_sig_token = local_var_sig_token;
7307 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7308 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7311 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7312 for (i = 0; i < header->num_locals; ++i) {
7313 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7315 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7316 mono_error_raise_exception (&error); /* FIXME don't raise here */
7318 MONO_OBJECT_SETREF (info, local_type, rt);
7320 info->is_pinned = header->locals [i]->pinned;
7321 info->local_index = i;
7322 mono_array_setref (ret->locals, i, info);
7326 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7327 for (i = 0; i < header->num_clauses; ++i) {
7328 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7329 MonoExceptionClause *clause = &header->clauses [i];
7331 info->flags = clause->flags;
7332 info->try_offset = clause->try_offset;
7333 info->try_length = clause->try_len;
7334 info->handler_offset = clause->handler_offset;
7335 info->handler_length = clause->handler_len;
7336 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7337 info->filter_offset = clause->data.filter_offset;
7338 else if (clause->data.catch_class) {
7339 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7340 mono_error_raise_exception (&error); /* FIXME don't raise here */
7342 MONO_OBJECT_SETREF (info, catch_type, rt);
7345 mono_array_setref (ret->clauses, i, info);
7348 mono_metadata_free_mh (header);
7349 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7354 * mono_get_dbnull_object:
7355 * @domain: Domain where the object lives
7357 * Returns the System.DBNull.Value singleton object
7359 * Used as the value for ParameterInfo.DefaultValue
7362 mono_get_dbnull_object (MonoDomain *domain)
7365 static MonoClassField *dbnull_value_field = NULL;
7367 if (!dbnull_value_field) {
7368 MonoClass *dbnull_klass;
7369 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7370 mono_class_init (dbnull_klass);
7371 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7372 g_assert (dbnull_value_field);
7374 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7380 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7382 guint32 param_index, i, lastp, crow = 0;
7383 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7386 MonoClass *klass = method->klass;
7387 MonoImage *image = klass->image;
7388 MonoMethodSignature *methodsig = mono_method_signature (method);
7390 MonoTableInfo *constt;
7391 MonoTableInfo *methodt;
7392 MonoTableInfo *paramt;
7394 if (!methodsig->param_count)
7397 mono_class_init (klass);
7399 if (image_is_dynamic (klass->image)) {
7400 MonoReflectionMethodAux *aux;
7401 if (method->is_inflated)
7402 method = ((MonoMethodInflated*)method)->declaring;
7403 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7404 if (aux && aux->param_defaults) {
7405 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7406 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7411 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7412 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7413 constt = &image->tables [MONO_TABLE_CONSTANT];
7415 idx = mono_method_get_index (method) - 1;
7416 g_assert (idx != -1);
7418 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7419 if (idx + 1 < methodt->rows)
7420 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7422 lastp = paramt->rows + 1;
7424 for (i = param_index; i < lastp; ++i) {
7427 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7428 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7430 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7433 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7438 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7439 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7440 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7447 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7452 MonoType *basetype = type;
7457 klass = mono_class_from_mono_type (type);
7458 if (klass->valuetype) {
7459 object = mono_object_new (domain, klass);
7460 retval = ((gchar *) object + sizeof (MonoObject));
7461 if (klass->enumtype)
7462 basetype = mono_class_enum_basetype (klass);
7467 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7474 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7477 gboolean quoted = FALSE;
7479 memset (assembly, 0, sizeof (MonoAssemblyName));
7480 assembly->culture = "";
7481 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7488 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7499 /* Remove trailing whitespace */
7501 while (*s && g_ascii_isspace (*s))
7504 while (g_ascii_isspace (*p))
7507 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7509 assembly->major = strtoul (p, &s, 10);
7510 if (s == p || *s != '.')
7513 assembly->minor = strtoul (p, &s, 10);
7514 if (s == p || *s != '.')
7517 assembly->build = strtoul (p, &s, 10);
7518 if (s == p || *s != '.')
7521 assembly->revision = strtoul (p, &s, 10);
7525 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7527 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7528 assembly->culture = "";
7531 assembly->culture = p;
7532 while (*p && *p != ',') {
7536 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7538 if (strncmp (p, "null", 4) == 0) {
7543 while (*p && *p != ',') {
7546 len = (p - start + 1);
7547 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7548 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7549 g_strlcpy ((char*)assembly->public_key_token, start, len);
7552 while (*p && *p != ',')
7556 while (g_ascii_isspace (*p) || *p == ',') {
7570 * mono_reflection_parse_type:
7573 * Parse a type name as accepted by the GetType () method and output the info
7574 * extracted in the info structure.
7575 * the name param will be mangled, so, make a copy before passing it to this function.
7576 * The fields in info will be valid until the memory pointed to by name is valid.
7578 * See also mono_type_get_name () below.
7580 * Returns: 0 on parse error.
7583 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7584 MonoTypeNameParse *info)
7586 char *start, *p, *w, *last_point, *startn;
7587 int in_modifiers = 0;
7588 int isbyref = 0, rank = 0, isptr = 0;
7590 start = p = w = name;
7592 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7593 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7594 info->name = info->name_space = NULL;
7595 info->nested = NULL;
7596 info->modifiers = NULL;
7597 info->type_arguments = NULL;
7599 /* last_point separates the namespace from the name */
7602 while (*p == ' ') p++, start++, w++, name++;
7607 *p = 0; /* NULL terminate the name */
7609 info->nested = g_list_append (info->nested, startn);
7610 /* we have parsed the nesting namespace + name */
7614 info->name_space = start;
7616 info->name = last_point + 1;
7618 info->name_space = (char *)"";
7646 info->name_space = start;
7648 info->name = last_point + 1;
7650 info->name_space = (char *)"";
7657 if (isbyref) /* only one level allowed by the spec */
7661 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7665 if (isbyref) /* pointer to ref not okay */
7667 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7672 if (isbyref) /* array of ref and generic ref are not okay */
7674 //Decide if it's an array of a generic argument list
7679 if (*p == ',' || *p == '*' || *p == ']') { //array
7687 else if (*p == '*') /* '*' means unknown lower bound */
7688 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7695 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7697 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7700 info->type_arguments = g_ptr_array_new ();
7702 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7703 gboolean fqname = FALSE;
7705 g_ptr_array_add (info->type_arguments, subinfo);
7707 while (*p == ' ') p++;
7713 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7716 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7717 if (fqname && (*p != ']')) {
7725 while (*p && (*p != ']'))
7733 if (g_ascii_isspace (*aname)) {
7740 !assembly_name_to_aname (&subinfo->assembly, aname))
7742 } else if (fqname && (*p == ']')) {
7764 if (g_ascii_isspace (*p)) {
7771 return 0; /* missing assembly name */
7772 if (!assembly_name_to_aname (&info->assembly, p))
7778 if (info->assembly.name)
7781 // *w = 0; /* terminate class name */
7783 if (!info->name || !*info->name)
7787 /* add other consistency checks */
7793 * mono_identifier_unescape_type_name_chars:
7794 * @identifier: the display name of a mono type
7797 * The name in internal form, that is without escaping backslashes.
7799 * The string is modified in place!
7802 mono_identifier_unescape_type_name_chars(char* identifier)
7807 for (w = r = identifier; *r != 0; r++)
7825 mono_identifier_unescape_info (MonoTypeNameParse* info);
7828 unescape_each_type_argument(void* data, void* user_data)
7830 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7831 mono_identifier_unescape_info (info);
7835 unescape_each_nested_name (void* data, void* user_data)
7837 char* nested_name = (char*) data;
7838 mono_identifier_unescape_type_name_chars(nested_name);
7842 * mono_identifier_unescape_info:
7844 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7848 * Destructively updates the info by unescaping the identifiers that
7849 * comprise the type namespace, name, nested types (if any) and
7850 * generic type arguments (if any).
7852 * The resulting info has the names in internal form.
7856 mono_identifier_unescape_info (MonoTypeNameParse *info)
7860 mono_identifier_unescape_type_name_chars(info->name_space);
7861 mono_identifier_unescape_type_name_chars(info->name);
7862 // but don't escape info->assembly
7863 if (info->type_arguments)
7864 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7866 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7870 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7872 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7874 mono_identifier_unescape_info (info);
7880 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7882 gboolean type_resolve = FALSE;
7884 MonoImage *rootimage = image;
7886 if (info->assembly.name) {
7887 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7888 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7890 * This could happen in the AOT compiler case when the search hook is not
7893 assembly = image->assembly;
7895 /* then we must load the assembly ourselve - see #60439 */
7896 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7900 image = assembly->image;
7901 } else if (!image) {
7902 image = mono_defaults.corlib;
7905 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7906 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7907 image = mono_defaults.corlib;
7908 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7915 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7921 gboolean bounded = FALSE;
7924 image = mono_defaults.corlib;
7927 rootimage = mono_defaults.corlib;
7931 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7932 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7934 klass = mono_class_from_name (image, info->name_space, info->name);
7938 for (mod = info->nested; mod; mod = mod->next) {
7939 gpointer iter = NULL;
7943 mono_class_init (parent);
7945 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7947 char *nested_name, *nested_nspace;
7948 gboolean match = TRUE;
7950 lastp = strrchr ((const char *)mod->data, '.');
7952 /* Nested classes can have namespaces */
7955 nested_name = g_strdup (lastp + 1);
7956 nspace_len = lastp - (char*)mod->data;
7957 nested_nspace = (char *)g_malloc (nspace_len + 1);
7958 memcpy (nested_nspace, mod->data, nspace_len);
7959 nested_nspace [nspace_len] = '\0';
7962 nested_name = (char *)mod->data;
7963 nested_nspace = NULL;
7966 if (nested_nspace) {
7968 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7971 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7977 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7980 if (strcmp (klass->name, nested_name) != 0)
7985 g_free (nested_name);
7986 g_free (nested_nspace);
7998 if (info->type_arguments) {
7999 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8000 MonoReflectionType *the_type;
8004 for (i = 0; i < info->type_arguments->len; i++) {
8005 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8007 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8008 if (!type_args [i]) {
8014 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8015 mono_error_raise_exception (&error); /* FIXME don't raise here */
8017 instance = mono_reflection_bind_generic_parameters (
8018 the_type, info->type_arguments->len, type_args);
8024 klass = mono_class_from_mono_type (instance);
8027 for (mod = info->modifiers; mod; mod = mod->next) {
8028 modval = GPOINTER_TO_UINT (mod->data);
8029 if (!modval) { /* byref: must be last modifier */
8030 return &klass->this_arg;
8031 } else if (modval == -1) {
8032 klass = mono_ptr_class_get (&klass->byval_arg);
8033 } else if (modval == -2) {
8035 } else { /* array rank */
8036 klass = mono_bounded_array_class_get (klass, modval, bounded);
8040 return &klass->byval_arg;
8044 * mono_reflection_get_type:
8045 * @image: a metadata context
8046 * @info: type description structure
8047 * @ignorecase: flag for case-insensitive string compares
8048 * @type_resolve: whenever type resolve was already tried
8050 * Build a MonoType from the type description in @info.
8055 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8056 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8060 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8062 MonoReflectionAssemblyBuilder *abuilder;
8066 g_assert (assembly_is_dynamic (assembly));
8067 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8069 /* Enumerate all modules */
8072 if (abuilder->modules) {
8073 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8074 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8075 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8081 if (!type && abuilder->loaded_modules) {
8082 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8083 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8084 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8094 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8097 MonoReflectionAssembly *assembly;
8101 if (image && image_is_dynamic (image))
8102 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8104 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8107 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8114 *type_resolve = TRUE;
8117 /* Reconstruct the type name */
8118 fullName = g_string_new ("");
8119 if (info->name_space && (info->name_space [0] != '\0'))
8120 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8122 g_string_printf (fullName, "%s", info->name);
8123 for (mod = info->nested; mod; mod = mod->next)
8124 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8126 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8128 if (assembly_is_dynamic (assembly->assembly))
8129 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8131 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8134 g_string_free (fullName, TRUE);
8139 mono_reflection_free_type_info (MonoTypeNameParse *info)
8141 g_list_free (info->modifiers);
8142 g_list_free (info->nested);
8144 if (info->type_arguments) {
8147 for (i = 0; i < info->type_arguments->len; i++) {
8148 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8150 mono_reflection_free_type_info (subinfo);
8151 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8155 g_ptr_array_free (info->type_arguments, TRUE);
8160 * mono_reflection_type_from_name:
8162 * @image: a metadata context (can be NULL).
8164 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8165 * it defaults to get the type from @image or, if @image is NULL or loading
8166 * from it fails, uses corlib.
8170 mono_reflection_type_from_name (char *name, MonoImage *image)
8172 MonoType *type = NULL;
8173 MonoTypeNameParse info;
8176 /* Make a copy since parse_type modifies its argument */
8177 tmp = g_strdup (name);
8179 /*g_print ("requested type %s\n", str);*/
8180 if (mono_reflection_parse_type (tmp, &info)) {
8181 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8185 mono_reflection_free_type_info (&info);
8190 * mono_reflection_get_token:
8192 * Return the metadata token of OBJ which should be an object
8193 * representing a metadata element.
8196 mono_reflection_get_token (MonoObject *obj)
8201 klass = obj->vtable->klass;
8203 if (strcmp (klass->name, "MethodBuilder") == 0) {
8204 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8206 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8207 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8208 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8210 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8211 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8212 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8214 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8215 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8216 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8217 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8218 } else if (strcmp (klass->name, "MonoType") == 0) {
8219 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8220 MonoClass *mc = mono_class_from_mono_type (type);
8221 if (!mono_class_init (mc))
8222 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8224 token = mc->type_token;
8225 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8226 strcmp (klass->name, "MonoMethod") == 0 ||
8227 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8228 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8229 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8230 if (m->method->is_inflated) {
8231 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8232 return inflated->declaring->token;
8234 token = m->method->token;
8236 } else if (strcmp (klass->name, "MonoField") == 0) {
8237 MonoReflectionField *f = (MonoReflectionField*)obj;
8239 if (is_field_on_inst (f->field)) {
8240 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8242 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8243 int field_index = f->field - dgclass->fields;
8246 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8247 obj = dgclass->field_objects [field_index];
8248 return mono_reflection_get_token (obj);
8251 token = mono_class_get_field_token (f->field);
8252 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8253 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8255 token = mono_class_get_property_token (p->property);
8256 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8257 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8259 token = mono_class_get_event_token (p->event);
8260 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8261 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8262 MonoClass *member_class = mono_object_class (p->MemberImpl);
8263 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8265 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8266 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8267 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8270 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8271 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8273 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8274 MonoException *ex = mono_get_exception_not_implemented (msg);
8276 mono_raise_exception (ex);
8283 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8287 int slen = mono_metadata_decode_value (p, &p);
8289 mono_error_init (error);
8291 n = (char *)g_memdup (p, slen + 1);
8293 t = mono_reflection_type_from_name (n, image);
8295 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8296 /* We don't free n, it's consumed by mono_error */
8297 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8303 return mono_class_from_mono_type (t);
8307 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8309 int slen, type = t->type;
8310 MonoClass *tklass = t->data.klass;
8312 mono_error_init (error);
8318 case MONO_TYPE_BOOLEAN: {
8319 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8324 case MONO_TYPE_CHAR:
8326 case MONO_TYPE_I2: {
8327 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8332 #if SIZEOF_VOID_P == 4
8338 case MONO_TYPE_I4: {
8339 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8344 #if SIZEOF_VOID_P == 8
8345 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8349 case MONO_TYPE_I8: {
8350 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8355 case MONO_TYPE_R8: {
8356 double *val = (double *)g_malloc (sizeof (double));
8361 case MONO_TYPE_VALUETYPE:
8362 if (t->data.klass->enumtype) {
8363 type = mono_class_enum_basetype (t->data.klass)->type;
8366 MonoClass *k = t->data.klass;
8368 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8369 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8375 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8378 case MONO_TYPE_STRING:
8379 if (*p == (char)0xFF) {
8383 slen = mono_metadata_decode_value (p, &p);
8385 return mono_string_new_len (mono_domain_get (), p, slen);
8386 case MONO_TYPE_CLASS: {
8387 MonoReflectionType *rt;
8390 if (*p == (char)0xFF) {
8395 slen = mono_metadata_decode_value (p, &p);
8396 n = (char *)g_memdup (p, slen + 1);
8398 t = mono_reflection_type_from_name (n, image);
8400 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8401 /* We don't free n, it's consumed by mono_error */
8402 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8408 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8409 if (!mono_error_ok (error))
8414 case MONO_TYPE_OBJECT: {
8417 MonoClass *subc = NULL;
8422 } else if (subt == 0x0E) {
8423 type = MONO_TYPE_STRING;
8425 } else if (subt == 0x1D) {
8426 MonoType simple_type = {{0}};
8430 type = MONO_TYPE_SZARRAY;
8431 if (etype == 0x50) {
8432 tklass = mono_defaults.systemtype_class;
8433 } else if (etype == 0x55) {
8434 tklass = load_cattr_enum_type (image, p, &p, error);
8435 if (!mono_error_ok (error))
8439 /* See Partition II, Appendix B3 */
8440 etype = MONO_TYPE_OBJECT;
8441 simple_type.type = (MonoTypeEnum)etype;
8442 tklass = mono_class_from_mono_type (&simple_type);
8445 } else if (subt == 0x55) {
8448 slen = mono_metadata_decode_value (p, &p);
8449 n = (char *)g_memdup (p, slen + 1);
8451 t = mono_reflection_type_from_name (n, image);
8453 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8454 /* We don't free n, it's consumed by mono_error */
8455 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8460 subc = mono_class_from_mono_type (t);
8461 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8462 MonoType simple_type = {{0}};
8463 simple_type.type = (MonoTypeEnum)subt;
8464 subc = mono_class_from_mono_type (&simple_type);
8466 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8468 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8470 if (mono_error_ok (error)) {
8471 obj = mono_object_new (mono_domain_get (), subc);
8472 g_assert (!subc->has_references);
8473 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8479 case MONO_TYPE_SZARRAY: {
8481 guint32 i, alen, basetype;
8484 if (alen == 0xffffffff) {
8488 arr = mono_array_new (mono_domain_get(), tklass, alen);
8489 basetype = tklass->byval_arg.type;
8490 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8491 basetype = mono_class_enum_basetype (tklass)->type;
8496 case MONO_TYPE_BOOLEAN:
8497 for (i = 0; i < alen; i++) {
8498 MonoBoolean val = *p++;
8499 mono_array_set (arr, MonoBoolean, i, val);
8502 case MONO_TYPE_CHAR:
8505 for (i = 0; i < alen; i++) {
8506 guint16 val = read16 (p);
8507 mono_array_set (arr, guint16, i, val);
8514 for (i = 0; i < alen; i++) {
8515 guint32 val = read32 (p);
8516 mono_array_set (arr, guint32, i, val);
8521 for (i = 0; i < alen; i++) {
8524 mono_array_set (arr, double, i, val);
8530 for (i = 0; i < alen; i++) {
8531 guint64 val = read64 (p);
8532 mono_array_set (arr, guint64, i, val);
8536 case MONO_TYPE_CLASS:
8537 case MONO_TYPE_OBJECT:
8538 case MONO_TYPE_STRING:
8539 case MONO_TYPE_SZARRAY:
8540 for (i = 0; i < alen; i++) {
8541 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8542 if (!mono_error_ok (error))
8544 mono_array_setref (arr, i, item);
8548 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8554 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8560 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8562 static MonoClass *klass;
8563 static MonoMethod *ctor;
8566 void *params [2], *unboxed;
8569 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8571 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8573 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8574 mono_error_raise_exception (&error); /* FIXME don't raise here */
8577 retval = mono_object_new (mono_domain_get (), klass);
8578 unboxed = mono_object_unbox (retval);
8579 mono_runtime_invoke (ctor, unboxed, params, NULL);
8585 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8587 static MonoClass *klass;
8588 static MonoMethod *ctor;
8590 void *unboxed, *params [2];
8593 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8595 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8598 params [1] = typedarg;
8599 retval = mono_object_new (mono_domain_get (), klass);
8600 unboxed = mono_object_unbox (retval);
8601 mono_runtime_invoke (ctor, unboxed, params, NULL);
8607 type_is_reference (MonoType *type)
8609 switch (type->type) {
8610 case MONO_TYPE_BOOLEAN:
8611 case MONO_TYPE_CHAR:
8624 case MONO_TYPE_VALUETYPE:
8632 free_param_data (MonoMethodSignature *sig, void **params) {
8634 for (i = 0; i < sig->param_count; ++i) {
8635 if (!type_is_reference (sig->params [i]))
8636 g_free (params [i]);
8641 * Find the field index in the metadata FieldDef table.
8644 find_field_index (MonoClass *klass, MonoClassField *field) {
8647 for (i = 0; i < klass->field.count; ++i) {
8648 if (field == &klass->fields [i])
8649 return klass->field.first + 1 + i;
8655 * Find the property index in the metadata Property table.
8658 find_property_index (MonoClass *klass, MonoProperty *property) {
8661 for (i = 0; i < klass->ext->property.count; ++i) {
8662 if (property == &klass->ext->properties [i])
8663 return klass->ext->property.first + 1 + i;
8669 * Find the event index in the metadata Event table.
8672 find_event_index (MonoClass *klass, MonoEvent *event) {
8675 for (i = 0; i < klass->ext->event.count; ++i) {
8676 if (event == &klass->ext->events [i])
8677 return klass->ext->event.first + 1 + i;
8683 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8685 const char *p = (const char*)data;
8687 guint32 i, j, num_named;
8689 void *params_buf [32];
8690 void **params = NULL;
8691 MonoMethodSignature *sig;
8692 MonoObject *exc = NULL;
8694 mono_error_init (error);
8696 mono_class_init (method->klass);
8698 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8699 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8704 attr = mono_object_new (mono_domain_get (), method->klass);
8705 mono_runtime_invoke (method, attr, NULL, NULL);
8709 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8712 /*g_print ("got attr %s\n", method->klass->name);*/
8714 sig = mono_method_signature (method);
8715 if (sig->param_count < 32) {
8716 params = params_buf;
8717 memset (params, 0, sizeof (void*) * sig->param_count);
8719 /* Allocate using GC so it gets GC tracking */
8720 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8725 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8726 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8727 if (!mono_error_ok (error))
8732 attr = mono_object_new (mono_domain_get (), method->klass);
8734 mono_runtime_invoke (method, attr, params, &exc);
8737 num_named = read16 (named);
8739 for (j = 0; j < num_named; j++) {
8741 char *name, named_type, data_type;
8742 named_type = *named++;
8743 data_type = *named++; /* type of data */
8744 if (data_type == MONO_TYPE_SZARRAY)
8745 data_type = *named++;
8746 if (data_type == MONO_TYPE_ENUM) {
8749 type_len = mono_metadata_decode_blob_size (named, &named);
8750 type_name = (char *)g_malloc (type_len + 1);
8751 memcpy (type_name, named, type_len);
8752 type_name [type_len] = 0;
8754 /* FIXME: lookup the type and check type consistency */
8757 name_len = mono_metadata_decode_blob_size (named, &named);
8758 name = (char *)g_malloc (name_len + 1);
8759 memcpy (name, named, name_len);
8760 name [name_len] = 0;
8762 if (named_type == 0x53) {
8763 MonoClassField *field;
8766 /* how this fail is a blackbox */
8767 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8769 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8774 val = load_cattr_value (image, field->type, named, &named, error);
8775 if (!mono_error_ok (error)) {
8777 if (!type_is_reference (field->type))
8782 mono_field_set_value (attr, field, val);
8783 if (!type_is_reference (field->type))
8785 } else if (named_type == 0x54) {
8788 MonoType *prop_type;
8790 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8793 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8799 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8804 /* can we have more that 1 arg in a custom attr named property? */
8805 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8806 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8808 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8809 if (!mono_error_ok (error)) {
8811 if (!type_is_reference (prop_type))
8812 g_free (pparams [0]);
8817 mono_property_set_value (prop, attr, pparams, NULL);
8818 if (!type_is_reference (prop_type))
8819 g_free (pparams [0]);
8824 free_param_data (method->signature, params);
8825 if (params != params_buf)
8826 mono_gc_free_fixed (params);
8831 free_param_data (method->signature, params);
8832 if (params != params_buf)
8833 mono_gc_free_fixed (params);
8835 mono_raise_exception ((MonoException*)exc);
8840 * mono_reflection_create_custom_attr_data_args:
8842 * Create an array of typed and named arguments from the cattr blob given by DATA.
8843 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8844 * NAMED_ARG_INFO will contain information about the named arguments.
8847 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)
8849 MonoArray *typedargs, *namedargs;
8850 MonoClass *attrklass;
8852 const char *p = (const char*)data;
8854 guint32 i, j, num_named;
8855 CattrNamedArg *arginfo = NULL;
8859 *named_arg_info = NULL;
8861 mono_error_init (error);
8863 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8864 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8868 mono_class_init (method->klass);
8870 domain = mono_domain_get ();
8872 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8875 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8879 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8883 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8884 if (!mono_error_ok (error)) {
8885 if (!type_is_reference (mono_method_signature (method)->params [i]))
8890 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8891 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8892 mono_array_setref (typedargs, i, obj);
8894 if (!type_is_reference (mono_method_signature (method)->params [i]))
8899 num_named = read16 (named);
8900 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8902 attrklass = method->klass;
8904 arginfo = g_new0 (CattrNamedArg, num_named);
8905 *named_arg_info = arginfo;
8907 for (j = 0; j < num_named; j++) {
8909 char *name, named_type, data_type;
8910 named_type = *named++;
8911 data_type = *named++; /* type of data */
8912 if (data_type == MONO_TYPE_SZARRAY)
8913 data_type = *named++;
8914 if (data_type == MONO_TYPE_ENUM) {
8917 type_len = mono_metadata_decode_blob_size (named, &named);
8918 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8921 type_name = (char *)g_malloc (type_len + 1);
8922 memcpy (type_name, named, type_len);
8923 type_name [type_len] = 0;
8925 /* FIXME: lookup the type and check type consistency */
8928 name_len = mono_metadata_decode_blob_size (named, &named);
8929 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8931 name = (char *)g_malloc (name_len + 1);
8932 memcpy (name, named, name_len);
8933 name [name_len] = 0;
8935 if (named_type == 0x53) {
8937 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8945 arginfo [j].type = field->type;
8946 arginfo [j].field = field;
8948 val = load_cattr_value (image, field->type, named, &named, error);
8949 if (!mono_error_ok (error)) {
8950 if (!type_is_reference (field->type))
8956 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8957 mono_array_setref (namedargs, j, obj);
8958 if (!type_is_reference (field->type))
8960 } else if (named_type == 0x54) {
8962 MonoType *prop_type;
8963 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8966 if (!prop || !prop->set) {
8971 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8972 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8974 arginfo [j].type = prop_type;
8975 arginfo [j].prop = prop;
8977 val = load_cattr_value (image, prop_type, named, &named, error);
8978 if (!mono_error_ok (error)) {
8979 if (!type_is_reference (prop_type))
8985 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8986 mono_array_setref (namedargs, j, obj);
8987 if (!type_is_reference (prop_type))
8993 *typed_args = typedargs;
8994 *named_args = namedargs;
8997 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8999 *named_arg_info = NULL;
9003 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9006 MonoArray *typedargs, *namedargs;
9009 CattrNamedArg *arginfo = NULL;
9013 mono_error_init (&error);
9021 image = assembly->assembly->image;
9022 method = ref_method->method;
9023 domain = mono_object_domain (ref_method);
9025 if (!mono_class_init (method->klass))
9026 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9028 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9029 if (!mono_error_ok (&error))
9032 if (mono_loader_get_last_error ()) {
9033 mono_error_set_from_loader_error (&error);
9037 if (!typedargs || !namedargs)
9040 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9041 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9042 MonoObject *typedarg;
9044 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9045 mono_array_setref (typedargs, i, typedarg);
9048 for (i = 0; i < mono_array_length (namedargs); ++i) {
9049 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9050 MonoObject *typedarg, *namedarg, *minfo;
9052 if (arginfo [i].prop)
9053 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9055 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9056 if (!mono_error_ok (&error))
9060 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9061 namedarg = create_cattr_named_arg (minfo, typedarg);
9063 mono_array_setref (namedargs, i, namedarg);
9066 *ctor_args = typedargs;
9067 *named_args = namedargs;
9070 mono_error_raise_exception (&error);
9075 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9077 static MonoMethod *ctor;
9082 g_assert (image->assembly);
9085 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9087 domain = mono_domain_get ();
9088 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
9089 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
9090 params [1] = mono_assembly_get_object (domain, image->assembly);
9091 params [2] = (gpointer)&cattr->data;
9092 params [3] = &cattr->data_size;
9093 mono_runtime_invoke (ctor, attr, params, NULL);
9098 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9104 mono_error_init (error);
9107 for (i = 0; i < cinfo->num_attrs; ++i) {
9108 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9112 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9114 for (i = 0; i < cinfo->num_attrs; ++i) {
9115 if (!cinfo->attrs [i].ctor)
9116 /* The cattr type is not finished yet */
9117 /* We should include the type name but cinfo doesn't contain it */
9118 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9119 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9120 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9121 if (!mono_error_ok (error))
9123 mono_array_setref (result, n, attr);
9131 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9134 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9135 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9141 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9147 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9148 for (i = 0; i < cinfo->num_attrs; ++i) {
9149 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9150 mono_array_setref (result, i, attr);
9156 * mono_custom_attrs_from_index:
9158 * Returns: NULL if no attributes are found or if a loading error occurs.
9161 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9163 guint32 mtoken, i, len;
9164 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9166 MonoCustomAttrInfo *ainfo;
9167 GList *tmp, *list = NULL;
9169 MonoCustomAttrEntry* attr;
9171 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9173 i = mono_metadata_custom_attrs_from_index (image, idx);
9177 while (i < ca->rows) {
9178 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9180 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9183 len = g_list_length (list);
9186 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9187 ainfo->num_attrs = len;
9188 ainfo->image = image;
9189 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9191 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9192 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9193 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9194 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9195 mtoken |= MONO_TOKEN_METHOD_DEF;
9197 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9198 mtoken |= MONO_TOKEN_MEMBER_REF;
9201 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9204 attr = &ainfo->attrs [i - 1];
9205 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9207 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9208 mono_loader_set_error_from_mono_error (&error);
9214 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9215 /*FIXME raising an exception here doesn't make any sense*/
9216 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9221 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9222 attr->data_size = mono_metadata_decode_value (data, &data);
9223 attr->data = (guchar*)data;
9231 mono_custom_attrs_from_method (MonoMethod *method)
9236 * An instantiated method has the same cattrs as the generic method definition.
9238 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9239 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9241 if (method->is_inflated)
9242 method = ((MonoMethodInflated *) method)->declaring;
9244 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9245 return lookup_custom_attr (method->klass->image, method);
9248 /* Synthetic methods */
9251 idx = mono_method_get_index (method);
9252 idx <<= MONO_CUSTOM_ATTR_BITS;
9253 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9254 return mono_custom_attrs_from_index (method->klass->image, idx);
9258 mono_custom_attrs_from_class (MonoClass *klass)
9262 if (klass->generic_class)
9263 klass = klass->generic_class->container_class;
9265 if (image_is_dynamic (klass->image))
9266 return lookup_custom_attr (klass->image, klass);
9268 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9269 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9270 idx <<= MONO_CUSTOM_ATTR_BITS;
9271 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9273 idx = mono_metadata_token_index (klass->type_token);
9274 idx <<= MONO_CUSTOM_ATTR_BITS;
9275 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9277 return mono_custom_attrs_from_index (klass->image, idx);
9281 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9285 if (image_is_dynamic (assembly->image))
9286 return lookup_custom_attr (assembly->image, assembly);
9287 idx = 1; /* there is only one assembly */
9288 idx <<= MONO_CUSTOM_ATTR_BITS;
9289 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9290 return mono_custom_attrs_from_index (assembly->image, idx);
9293 static MonoCustomAttrInfo*
9294 mono_custom_attrs_from_module (MonoImage *image)
9298 if (image_is_dynamic (image))
9299 return lookup_custom_attr (image, image);
9300 idx = 1; /* there is only one module */
9301 idx <<= MONO_CUSTOM_ATTR_BITS;
9302 idx |= MONO_CUSTOM_ATTR_MODULE;
9303 return mono_custom_attrs_from_index (image, idx);
9307 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9311 if (image_is_dynamic (klass->image)) {
9312 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9313 return lookup_custom_attr (klass->image, property);
9315 idx = find_property_index (klass, property);
9316 idx <<= MONO_CUSTOM_ATTR_BITS;
9317 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9318 return mono_custom_attrs_from_index (klass->image, idx);
9322 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9326 if (image_is_dynamic (klass->image)) {
9327 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9328 return lookup_custom_attr (klass->image, event);
9330 idx = find_event_index (klass, event);
9331 idx <<= MONO_CUSTOM_ATTR_BITS;
9332 idx |= MONO_CUSTOM_ATTR_EVENT;
9333 return mono_custom_attrs_from_index (klass->image, idx);
9337 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9340 if (image_is_dynamic (klass->image)) {
9341 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9342 return lookup_custom_attr (klass->image, field);
9344 idx = find_field_index (klass, field);
9345 idx <<= MONO_CUSTOM_ATTR_BITS;
9346 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9347 return mono_custom_attrs_from_index (klass->image, idx);
9351 * mono_custom_attrs_from_param:
9352 * @method: handle to the method that we want to retrieve custom parameter information from
9353 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9355 * The result must be released with mono_custom_attrs_free().
9357 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9360 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9363 guint32 i, idx, method_index;
9364 guint32 param_list, param_last, param_pos, found;
9366 MonoReflectionMethodAux *aux;
9369 * An instantiated method has the same cattrs as the generic method definition.
9371 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9372 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9374 if (method->is_inflated)
9375 method = ((MonoMethodInflated *) method)->declaring;
9377 if (image_is_dynamic (method->klass->image)) {
9378 MonoCustomAttrInfo *res, *ainfo;
9381 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9382 if (!aux || !aux->param_cattr)
9385 /* Need to copy since it will be freed later */
9386 ainfo = aux->param_cattr [param];
9389 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9390 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9391 memcpy (res, ainfo, size);
9395 image = method->klass->image;
9396 method_index = mono_method_get_index (method);
9399 ca = &image->tables [MONO_TABLE_METHOD];
9401 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9402 if (method_index == ca->rows) {
9403 ca = &image->tables [MONO_TABLE_PARAM];
9404 param_last = ca->rows + 1;
9406 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9407 ca = &image->tables [MONO_TABLE_PARAM];
9410 for (i = param_list; i < param_last; ++i) {
9411 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9412 if (param_pos == param) {
9420 idx <<= MONO_CUSTOM_ATTR_BITS;
9421 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9422 return mono_custom_attrs_from_index (image, idx);
9426 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9430 for (i = 0; i < ainfo->num_attrs; ++i) {
9431 klass = ainfo->attrs [i].ctor->klass;
9432 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9439 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9442 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9443 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9448 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9454 mono_error_init (error);
9457 for (i = 0; i < ainfo->num_attrs; ++i) {
9458 klass = ainfo->attrs [i].ctor->klass;
9459 if (mono_class_has_parent (klass, attr_klass)) {
9464 if (attr_index == -1)
9467 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9468 if (!mono_error_ok (error))
9470 return mono_array_get (attrs, MonoObject*, attr_index);
9474 * mono_reflection_get_custom_attrs_info:
9475 * @obj: a reflection object handle
9477 * Return the custom attribute info for attributes defined for the
9478 * reflection handle @obj. The objects.
9480 * FIXME this function leaks like a sieve for SRE objects.
9483 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9486 MonoCustomAttrInfo *cinfo = NULL;
9488 klass = obj->vtable->klass;
9489 if (klass == mono_defaults.monotype_class) {
9490 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9491 klass = mono_class_from_mono_type (type);
9492 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9493 cinfo = mono_custom_attrs_from_class (klass);
9494 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9495 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9496 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9497 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9498 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9499 cinfo = mono_custom_attrs_from_module (module->image);
9500 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9501 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9502 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9503 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9504 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9505 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9506 } else if (strcmp ("MonoField", klass->name) == 0) {
9507 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9508 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9509 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9510 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9511 cinfo = mono_custom_attrs_from_method (rmethod->method);
9512 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9513 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9514 cinfo = mono_custom_attrs_from_method (rmethod->method);
9515 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9516 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9517 MonoClass *member_class = mono_object_class (param->MemberImpl);
9518 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9519 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9520 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9521 } else if (is_sr_mono_property (member_class)) {
9522 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9524 if (!(method = prop->property->get))
9525 method = prop->property->set;
9528 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9530 #ifndef DISABLE_REFLECTION_EMIT
9531 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9532 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9533 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9534 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9535 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9536 MonoMethod *method = NULL;
9537 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9538 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9539 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9540 method = ((MonoReflectionMethod *)c->cb)->method;
9542 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));
9544 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9548 char *type_name = mono_type_get_full_name (member_class);
9549 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9550 MonoException *ex = mono_get_exception_not_supported (msg);
9553 mono_raise_exception (ex);
9555 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9556 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9557 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9558 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9559 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9560 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9561 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9562 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9563 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9564 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9565 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9566 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9567 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9568 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9569 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9570 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9571 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9572 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9573 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9574 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9575 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9576 } else { /* handle other types here... */
9577 g_error ("get custom attrs not yet supported for %s", klass->name);
9584 * mono_reflection_get_custom_attrs_by_type:
9585 * @obj: a reflection object handle
9587 * Return an array with all the custom attributes defined of the
9588 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9589 * of that type are returned. The objects are fully build. Return NULL if a loading error
9593 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9596 MonoCustomAttrInfo *cinfo;
9598 mono_error_init (error);
9600 cinfo = mono_reflection_get_custom_attrs_info (obj);
9602 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9604 mono_custom_attrs_free (cinfo);
9606 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9607 if (mono_loader_get_last_error ())
9609 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9616 * mono_reflection_get_custom_attrs:
9617 * @obj: a reflection object handle
9619 * Return an array with all the custom attributes defined of the
9620 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9624 mono_reflection_get_custom_attrs (MonoObject *obj)
9628 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9632 * mono_reflection_get_custom_attrs_data:
9633 * @obj: a reflection obj handle
9635 * Returns an array of System.Reflection.CustomAttributeData,
9636 * which include information about attributes reflected on
9637 * types loaded using the Reflection Only methods
9640 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9643 MonoCustomAttrInfo *cinfo;
9645 cinfo = mono_reflection_get_custom_attrs_info (obj);
9647 result = mono_custom_attrs_data_construct (cinfo);
9649 mono_custom_attrs_free (cinfo);
9651 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9656 static MonoReflectionType*
9657 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9659 static MonoMethod *method_get_underlying_system_type = NULL;
9660 MonoMethod *usertype_method;
9662 if (!method_get_underlying_system_type)
9663 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9664 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9665 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9670 is_corlib_type (MonoClass *klass)
9672 return klass->image == mono_defaults.corlib;
9675 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9676 static MonoClass *cached_class; \
9678 return cached_class == _class; \
9679 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9680 cached_class = _class; \
9687 #ifndef DISABLE_REFLECTION_EMIT
9689 is_sre_array (MonoClass *klass)
9691 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9695 is_sre_byref (MonoClass *klass)
9697 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9701 is_sre_pointer (MonoClass *klass)
9703 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9707 is_sre_generic_instance (MonoClass *klass)
9709 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9713 is_sre_type_builder (MonoClass *klass)
9715 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9719 is_sre_method_builder (MonoClass *klass)
9721 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9725 is_sre_ctor_builder (MonoClass *klass)
9727 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9731 is_sre_field_builder (MonoClass *klass)
9733 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9737 is_sre_method_on_tb_inst (MonoClass *klass)
9739 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9743 is_sre_ctor_on_tb_inst (MonoClass *klass)
9745 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9749 mono_reflection_type_get_handle (MonoReflectionType* ref)
9757 if (is_usertype (ref)) {
9758 ref = mono_reflection_type_get_underlying_system_type (ref);
9759 if (ref == NULL || is_usertype (ref))
9765 klass = mono_object_class (ref);
9767 if (is_sre_array (klass)) {
9769 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9770 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9772 if (sre_array->rank == 0) //single dimentional array
9773 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9775 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9776 sre_array->type.type = res;
9778 } else if (is_sre_byref (klass)) {
9780 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9781 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9783 res = &mono_class_from_mono_type (base)->this_arg;
9784 sre_byref->type.type = res;
9786 } else if (is_sre_pointer (klass)) {
9788 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9789 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9791 res = &mono_ptr_class_get (base)->byval_arg;
9792 sre_pointer->type.type = res;
9794 } else if (is_sre_generic_instance (klass)) {
9795 MonoType *res, **types;
9796 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9799 count = mono_array_length (gclass->type_arguments);
9800 types = g_new0 (MonoType*, count);
9801 for (i = 0; i < count; ++i) {
9802 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9803 types [i] = mono_reflection_type_get_handle (t);
9810 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9813 gclass->type.type = res;
9817 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9824 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9826 mono_reflection_type_get_handle (type);
9830 mono_reflection_register_with_runtime (MonoReflectionType *type)
9832 MonoType *res = mono_reflection_type_get_handle (type);
9833 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9837 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9839 klass = mono_class_from_mono_type (res);
9841 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9842 mono_domain_lock (domain);
9844 if (!image_is_dynamic (klass->image)) {
9845 mono_class_setup_supertypes (klass);
9847 if (!domain->type_hash)
9848 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9849 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9850 mono_g_hash_table_insert (domain->type_hash, res, type);
9852 mono_domain_unlock (domain);
9853 mono_loader_unlock ();
9857 * LOCKING: Assumes the loader lock is held.
9859 static MonoMethodSignature*
9860 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9861 MonoMethodSignature *sig;
9864 count = parameters? mono_array_length (parameters): 0;
9866 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9867 sig->param_count = count;
9868 sig->sentinelpos = -1; /* FIXME */
9869 for (i = 0; i < count; ++i)
9870 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9875 * LOCKING: Assumes the loader lock is held.
9877 static MonoMethodSignature*
9878 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9879 MonoMethodSignature *sig;
9881 sig = parameters_to_signature (image, ctor->parameters);
9882 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9883 sig->ret = &mono_defaults.void_class->byval_arg;
9888 * LOCKING: Assumes the loader lock is held.
9890 static MonoMethodSignature*
9891 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9892 MonoMethodSignature *sig;
9894 sig = parameters_to_signature (image, method->parameters);
9895 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9896 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9897 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9901 static MonoMethodSignature*
9902 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9903 MonoMethodSignature *sig;
9905 sig = parameters_to_signature (NULL, method->parameters);
9906 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9907 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9908 sig->generic_param_count = 0;
9913 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9915 MonoClass *klass = mono_object_class (prop);
9916 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9917 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9918 *name = mono_string_to_utf8 (pb->name);
9919 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9921 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9922 *name = g_strdup (p->property->name);
9923 if (p->property->get)
9924 *type = mono_method_signature (p->property->get)->ret;
9926 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9931 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9933 MonoClass *klass = mono_object_class (field);
9934 if (strcmp (klass->name, "FieldBuilder") == 0) {
9935 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9936 *name = mono_string_to_utf8 (fb->name);
9937 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9939 MonoReflectionField *f = (MonoReflectionField *)field;
9940 *name = g_strdup (mono_field_get_name (f->field));
9941 *type = f->field->type;
9945 #else /* DISABLE_REFLECTION_EMIT */
9948 mono_reflection_register_with_runtime (MonoReflectionType *type)
9954 is_sre_type_builder (MonoClass *klass)
9960 is_sre_generic_instance (MonoClass *klass)
9966 init_type_builder_generics (MonoObject *type)
9970 #endif /* !DISABLE_REFLECTION_EMIT */
9974 is_sr_mono_field (MonoClass *klass)
9976 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9980 is_sr_mono_property (MonoClass *klass)
9982 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9986 is_sr_mono_method (MonoClass *klass)
9988 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9992 is_sr_mono_cmethod (MonoClass *klass)
9994 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9998 is_sr_mono_generic_method (MonoClass *klass)
10000 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10004 is_sr_mono_generic_cmethod (MonoClass *klass)
10006 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10010 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10012 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10016 is_usertype (MonoReflectionType *ref)
10018 MonoClass *klass = mono_object_class (ref);
10019 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10022 static MonoReflectionType*
10023 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10025 mono_error_init (error);
10026 if (!type || type->type)
10029 if (is_usertype (type)) {
10030 type = mono_reflection_type_get_underlying_system_type (type);
10031 if (is_usertype (type)) {
10032 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10040 * Encode a value in a custom attribute stream of bytes.
10041 * The value to encode is either supplied as an object in argument val
10042 * (valuetypes are boxed), or as a pointer to the data in the
10044 * @type represents the type of the value
10045 * @buffer is the start of the buffer
10046 * @p the current position in the buffer
10047 * @buflen contains the size of the buffer and is used to return the new buffer size
10048 * if this needs to be realloced.
10049 * @retbuffer and @retp return the start and the position of the buffer
10052 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10054 MonoTypeEnum simple_type;
10056 if ((p-buffer) + 10 >= *buflen) {
10059 newbuf = (char *)g_realloc (buffer, *buflen);
10060 p = newbuf + (p-buffer);
10064 argval = ((char*)arg + sizeof (MonoObject));
10065 simple_type = type->type;
10067 switch (simple_type) {
10068 case MONO_TYPE_BOOLEAN:
10073 case MONO_TYPE_CHAR:
10076 swap_with_size (p, argval, 2, 1);
10082 swap_with_size (p, argval, 4, 1);
10086 swap_with_size (p, argval, 8, 1);
10091 swap_with_size (p, argval, 8, 1);
10094 case MONO_TYPE_VALUETYPE:
10095 if (type->data.klass->enumtype) {
10096 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10099 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10102 case MONO_TYPE_STRING: {
10109 str = mono_string_to_utf8 ((MonoString*)arg);
10110 slen = strlen (str);
10111 if ((p-buffer) + 10 + slen >= *buflen) {
10115 newbuf = (char *)g_realloc (buffer, *buflen);
10116 p = newbuf + (p-buffer);
10119 mono_metadata_encode_value (slen, p, &p);
10120 memcpy (p, str, slen);
10125 case MONO_TYPE_CLASS: {
10133 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10134 slen = strlen (str);
10135 if ((p-buffer) + 10 + slen >= *buflen) {
10139 newbuf = (char *)g_realloc (buffer, *buflen);
10140 p = newbuf + (p-buffer);
10143 mono_metadata_encode_value (slen, p, &p);
10144 memcpy (p, str, slen);
10149 case MONO_TYPE_SZARRAY: {
10151 MonoClass *eclass, *arg_eclass;
10154 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10157 len = mono_array_length ((MonoArray*)arg);
10159 *p++ = (len >> 8) & 0xff;
10160 *p++ = (len >> 16) & 0xff;
10161 *p++ = (len >> 24) & 0xff;
10163 *retbuffer = buffer;
10164 eclass = type->data.klass;
10165 arg_eclass = mono_object_class (arg)->element_class;
10168 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10169 eclass = mono_defaults.object_class;
10171 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10172 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10173 int elsize = mono_class_array_element_size (arg_eclass);
10174 for (i = 0; i < len; ++i) {
10175 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10178 } else if (eclass->valuetype && arg_eclass->valuetype) {
10179 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10180 int elsize = mono_class_array_element_size (eclass);
10181 for (i = 0; i < len; ++i) {
10182 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10186 for (i = 0; i < len; ++i) {
10187 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10192 case MONO_TYPE_OBJECT: {
10198 * The parameter type is 'object' but the type of the actual
10199 * argument is not. So we have to add type information to the blob
10200 * too. This is completely undocumented in the spec.
10204 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10209 klass = mono_object_class (arg);
10211 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10214 } else if (klass->enumtype) {
10216 } else if (klass == mono_defaults.string_class) {
10217 simple_type = MONO_TYPE_STRING;
10220 } else if (klass->rank == 1) {
10222 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10223 /* See Partition II, Appendix B3 */
10226 *p++ = klass->element_class->byval_arg.type;
10227 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10229 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10230 *p++ = simple_type = klass->byval_arg.type;
10233 g_error ("unhandled type in custom attr");
10235 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10236 slen = strlen (str);
10237 if ((p-buffer) + 10 + slen >= *buflen) {
10241 newbuf = (char *)g_realloc (buffer, *buflen);
10242 p = newbuf + (p-buffer);
10245 mono_metadata_encode_value (slen, p, &p);
10246 memcpy (p, str, slen);
10249 simple_type = mono_class_enum_basetype (klass)->type;
10253 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10256 *retbuffer = buffer;
10260 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10262 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10263 char *str = type_get_qualified_name (type, NULL);
10264 int slen = strlen (str);
10268 * This seems to be optional...
10271 mono_metadata_encode_value (slen, p, &p);
10272 memcpy (p, str, slen);
10275 } else if (type->type == MONO_TYPE_OBJECT) {
10277 } else if (type->type == MONO_TYPE_CLASS) {
10278 /* it should be a type: encode_cattr_value () has the check */
10281 mono_metadata_encode_value (type->type, p, &p);
10282 if (type->type == MONO_TYPE_SZARRAY)
10283 /* See the examples in Partition VI, Annex B */
10284 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10290 #ifndef DISABLE_REFLECTION_EMIT
10292 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10295 /* Preallocate a large enough buffer */
10296 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10297 char *str = type_get_qualified_name (type, NULL);
10298 len = strlen (str);
10300 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10301 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10302 len = strlen (str);
10307 len += strlen (name);
10309 if ((p-buffer) + 20 + len >= *buflen) {
10313 newbuf = (char *)g_realloc (buffer, *buflen);
10314 p = newbuf + (p-buffer);
10318 encode_field_or_prop_type (type, p, &p);
10320 len = strlen (name);
10321 mono_metadata_encode_value (len, p, &p);
10322 memcpy (p, name, len);
10324 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10326 *retbuffer = buffer;
10330 * mono_reflection_get_custom_attrs_blob:
10331 * @ctor: custom attribute constructor
10332 * @ctorArgs: arguments o the constructor
10338 * Creates the blob of data that needs to be saved in the metadata and that represents
10339 * the custom attributed described by @ctor, @ctorArgs etc.
10340 * Returns: a Byte array representing the blob of data.
10343 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10346 MonoMethodSignature *sig;
10351 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10352 /* sig is freed later so allocate it in the heap */
10353 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10355 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10358 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10360 p = buffer = (char *)g_malloc (buflen);
10361 /* write the prolog */
10364 for (i = 0; i < sig->param_count; ++i) {
10365 arg = mono_array_get (ctorArgs, MonoObject*, i);
10366 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10370 i += mono_array_length (properties);
10372 i += mono_array_length (fields);
10374 *p++ = (i >> 8) & 0xff;
10377 for (i = 0; i < mono_array_length (properties); ++i) {
10381 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10382 get_prop_name_and_type (prop, &pname, &ptype);
10383 *p++ = 0x54; /* PROPERTY signature */
10384 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10391 for (i = 0; i < mono_array_length (fields); ++i) {
10395 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10396 get_field_name_and_type (field, &fname, &ftype);
10397 *p++ = 0x53; /* FIELD signature */
10398 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10403 g_assert (p - buffer <= buflen);
10404 buflen = p - buffer;
10405 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10406 p = mono_array_addr (result, char, 0);
10407 memcpy (p, buffer, buflen);
10409 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10415 * mono_reflection_setup_internal_class:
10416 * @tb: a TypeBuilder object
10418 * Creates a MonoClass that represents the TypeBuilder.
10419 * This is a trick that lets us simplify a lot of reflection code
10420 * (and will allow us to support Build and Run assemblies easier).
10423 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10426 MonoClass *klass, *parent;
10428 RESOLVE_TYPE (tb->parent, &error);
10429 mono_error_raise_exception (&error); /* FIXME don't raise here */
10431 mono_loader_lock ();
10434 /* check so we can compile corlib correctly */
10435 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10436 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10437 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10439 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10445 /* the type has already being created: it means we just have to change the parent */
10446 if (tb->type.type) {
10447 klass = mono_class_from_mono_type (tb->type.type);
10448 klass->parent = NULL;
10449 /* fool mono_class_setup_parent */
10450 klass->supertypes = NULL;
10451 mono_class_setup_parent (klass, parent);
10452 mono_class_setup_mono_type (klass);
10453 mono_loader_unlock ();
10457 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10459 klass->image = &tb->module->dynamic_image->image;
10461 klass->inited = 1; /* we lie to the runtime */
10462 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10463 if (!mono_error_ok (&error))
10465 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10466 if (!mono_error_ok (&error))
10468 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10469 klass->flags = tb->attrs;
10471 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10473 klass->element_class = klass;
10475 if (mono_class_get_ref_info (klass) == NULL) {
10477 mono_class_set_ref_info (klass, tb);
10479 /* Put into cache so mono_class_get_checked () will find it.
10480 Skip nested types as those should not be available on the global scope. */
10481 if (!tb->nesting_type)
10482 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10485 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10486 by performing a mono_class_get which does the full resolution.
10488 Working around this semantics would require us to write a lot of code for no clear advantage.
10490 mono_image_append_class_to_reflection_info_set (klass);
10492 g_assert (mono_class_get_ref_info (klass) == tb);
10495 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10497 if (parent != NULL) {
10498 mono_class_setup_parent (klass, parent);
10499 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10500 const char *old_n = klass->name;
10501 /* trick to get relative numbering right when compiling corlib */
10502 klass->name = "BuildingObject";
10503 mono_class_setup_parent (klass, mono_defaults.object_class);
10504 klass->name = old_n;
10507 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10508 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10509 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10510 klass->instance_size = sizeof (MonoObject);
10511 klass->size_inited = 1;
10512 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10515 mono_class_setup_mono_type (klass);
10517 mono_class_setup_supertypes (klass);
10520 * FIXME: handle interfaces.
10523 tb->type.type = &klass->byval_arg;
10525 if (tb->nesting_type) {
10526 g_assert (tb->nesting_type->type);
10527 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10530 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10532 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10534 mono_loader_unlock ();
10538 mono_loader_unlock ();
10539 mono_error_raise_exception (&error);
10543 * mono_reflection_setup_generic_class:
10544 * @tb: a TypeBuilder object
10546 * Setup the generic class before adding the first generic parameter.
10549 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10554 * mono_reflection_create_generic_class:
10555 * @tb: a TypeBuilder object
10557 * Creates the generic class after all generic parameters have been added.
10560 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10565 klass = mono_class_from_mono_type (tb->type.type);
10567 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10569 if (klass->generic_container || (count == 0))
10572 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10574 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10576 klass->generic_container->owner.klass = klass;
10577 klass->generic_container->type_argc = count;
10578 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10580 klass->is_generic = 1;
10582 for (i = 0; i < count; i++) {
10583 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10584 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10585 klass->generic_container->type_params [i] = *param;
10586 /*Make sure we are a diferent type instance */
10587 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10588 klass->generic_container->type_params [i].info.pklass = NULL;
10589 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10591 g_assert (klass->generic_container->type_params [i].param.owner);
10594 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10598 * mono_reflection_create_internal_class:
10599 * @tb: a TypeBuilder object
10601 * Actually create the MonoClass that is associated with the TypeBuilder.
10604 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10608 klass = mono_class_from_mono_type (tb->type.type);
10610 mono_loader_lock ();
10611 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10612 MonoReflectionFieldBuilder *fb;
10614 MonoType *enum_basetype;
10616 g_assert (tb->fields != NULL);
10617 g_assert (mono_array_length (tb->fields) >= 1);
10619 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10621 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10622 mono_loader_unlock ();
10626 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10627 klass->element_class = mono_class_from_mono_type (enum_basetype);
10628 if (!klass->element_class)
10629 klass->element_class = mono_class_from_mono_type (enum_basetype);
10632 * get the element_class from the current corlib.
10634 ec = default_class_from_mono_type (enum_basetype);
10635 klass->instance_size = ec->instance_size;
10636 klass->size_inited = 1;
10638 * this is almost safe to do with enums and it's needed to be able
10639 * to create objects of the enum type (for use in SetConstant).
10641 /* FIXME: Does this mean enums can't have method overrides ? */
10642 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10644 mono_loader_unlock ();
10647 static MonoMarshalSpec*
10648 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10649 MonoReflectionMarshal *minfo)
10651 MonoMarshalSpec *res;
10653 res = image_g_new0 (image, MonoMarshalSpec, 1);
10654 res->native = (MonoMarshalNative)minfo->type;
10656 switch (minfo->type) {
10657 case MONO_NATIVE_LPARRAY:
10658 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10659 if (minfo->has_size) {
10660 res->data.array_data.param_num = minfo->param_num;
10661 res->data.array_data.num_elem = minfo->count;
10662 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10665 res->data.array_data.param_num = -1;
10666 res->data.array_data.num_elem = -1;
10667 res->data.array_data.elem_mult = -1;
10671 case MONO_NATIVE_BYVALTSTR:
10672 case MONO_NATIVE_BYVALARRAY:
10673 res->data.array_data.num_elem = minfo->count;
10676 case MONO_NATIVE_CUSTOM:
10677 if (minfo->marshaltyperef)
10678 res->data.custom_data.custom_name =
10679 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10680 if (minfo->mcookie)
10681 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10690 #endif /* !DISABLE_REFLECTION_EMIT */
10692 MonoReflectionMarshalAsAttribute*
10693 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10694 MonoMarshalSpec *spec)
10696 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10698 MonoReflectionType *rt;
10699 MonoReflectionMarshalAsAttribute *minfo;
10702 if (!System_Reflection_Emit_MarshalAsAttribute) {
10703 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10704 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10705 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10708 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10709 minfo->utype = spec->native;
10711 switch (minfo->utype) {
10712 case MONO_NATIVE_LPARRAY:
10713 minfo->array_subtype = spec->data.array_data.elem_type;
10714 minfo->size_const = spec->data.array_data.num_elem;
10715 if (spec->data.array_data.param_num != -1)
10716 minfo->size_param_index = spec->data.array_data.param_num;
10719 case MONO_NATIVE_BYVALTSTR:
10720 case MONO_NATIVE_BYVALARRAY:
10721 minfo->size_const = spec->data.array_data.num_elem;
10724 case MONO_NATIVE_CUSTOM:
10725 if (spec->data.custom_data.custom_name) {
10726 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10728 rt = mono_type_get_object_checked (domain, mtype, &error);
10729 mono_error_raise_exception (&error); /* FIXME don't raise here */
10731 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10734 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10736 if (spec->data.custom_data.cookie)
10737 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10747 #ifndef DISABLE_REFLECTION_EMIT
10749 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10750 ReflectionMethodBuilder *rmb,
10751 MonoMethodSignature *sig)
10755 MonoMethodWrapper *wrapperm;
10756 MonoMarshalSpec **specs;
10757 MonoReflectionMethodAux *method_aux;
10762 mono_error_init (&error);
10764 * Methods created using a MethodBuilder should have their memory allocated
10765 * inside the image mempool, while dynamic methods should have their memory
10768 dynamic = rmb->refs != NULL;
10769 image = dynamic ? NULL : klass->image;
10772 g_assert (!klass->generic_class);
10774 mono_loader_lock ();
10776 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10777 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10778 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10780 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10782 wrapperm = (MonoMethodWrapper*)m;
10784 m->dynamic = dynamic;
10786 m->flags = rmb->attrs;
10787 m->iflags = rmb->iattrs;
10788 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10790 m->signature = sig;
10791 m->sre_method = TRUE;
10792 m->skip_visibility = rmb->skip_visibility;
10793 if (rmb->table_idx)
10794 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10796 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10797 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10798 m->string_ctor = 1;
10800 m->signature->pinvoke = 1;
10801 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10802 m->signature->pinvoke = 1;
10804 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10806 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10807 g_assert (mono_error_ok (&error));
10808 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10809 g_assert (mono_error_ok (&error));
10811 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10813 if (image_is_dynamic (klass->image))
10814 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10816 mono_loader_unlock ();
10819 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10820 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10821 MonoMethodHeader *header;
10823 gint32 max_stack, i;
10824 gint32 num_locals = 0;
10825 gint32 num_clauses = 0;
10829 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10830 code_size = rmb->ilgen->code_len;
10831 max_stack = rmb->ilgen->max_stack;
10832 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10833 if (rmb->ilgen->ex_handlers)
10834 num_clauses = method_count_clauses (rmb->ilgen);
10837 code = mono_array_addr (rmb->code, guint8, 0);
10838 code_size = mono_array_length (rmb->code);
10839 /* we probably need to run a verifier on the code... */
10849 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10850 header->code_size = code_size;
10851 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10852 memcpy ((char*)header->code, code, code_size);
10853 header->max_stack = max_stack;
10854 header->init_locals = rmb->init_locals;
10855 header->num_locals = num_locals;
10857 for (i = 0; i < num_locals; ++i) {
10858 MonoReflectionLocalBuilder *lb =
10859 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10861 header->locals [i] = image_g_new0 (image, MonoType, 1);
10862 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10865 header->num_clauses = num_clauses;
10867 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10868 rmb->ilgen, num_clauses);
10871 wrapperm->header = header;
10874 if (rmb->generic_params) {
10875 int count = mono_array_length (rmb->generic_params);
10876 MonoGenericContainer *container = rmb->generic_container;
10878 g_assert (container);
10880 container->type_argc = count;
10881 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10882 container->owner.method = m;
10883 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10885 m->is_generic = TRUE;
10886 mono_method_set_generic_container (m, container);
10888 for (i = 0; i < count; i++) {
10889 MonoReflectionGenericParam *gp =
10890 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10891 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10892 container->type_params [i] = *param;
10896 * The method signature might have pointers to generic parameters that belong to other methods.
10897 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10898 * generic parameters.
10900 for (i = 0; i < m->signature->param_count; ++i) {
10901 MonoType *t = m->signature->params [i];
10902 if (t->type == MONO_TYPE_MVAR) {
10903 MonoGenericParam *gparam = t->data.generic_param;
10904 if (gparam->num < count) {
10905 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10906 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10912 if (klass->generic_container) {
10913 container->parent = klass->generic_container;
10914 container->context.class_inst = klass->generic_container->context.class_inst;
10916 container->context.method_inst = mono_get_shared_generic_inst (container);
10920 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10924 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10926 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10927 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10928 for (i = 0; i < rmb->nrefs; ++i)
10929 data [i + 1] = rmb->refs [i];
10934 /* Parameter info */
10937 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10938 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10939 for (i = 0; i <= m->signature->param_count; ++i) {
10940 MonoReflectionParamBuilder *pb;
10941 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10942 if ((i > 0) && (pb->attrs)) {
10943 /* Make a copy since it might point to a shared type structure */
10944 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10945 m->signature->params [i - 1]->attrs = pb->attrs;
10948 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10949 MonoDynamicImage *assembly;
10951 MonoTypeEnum def_type;
10955 if (!method_aux->param_defaults) {
10956 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10957 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10959 assembly = (MonoDynamicImage*)klass->image;
10960 idx = encode_constant (assembly, pb->def_value, &def_type);
10961 /* Copy the data from the blob since it might get realloc-ed */
10962 p = assembly->blob.data + idx;
10963 len = mono_metadata_decode_blob_size (p, &p2);
10965 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10966 method_aux->param_default_types [i] = def_type;
10967 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10971 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10972 g_assert (mono_error_ok (&error));
10975 if (!method_aux->param_cattr)
10976 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10977 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10983 /* Parameter marshalling */
10986 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10987 MonoReflectionParamBuilder *pb;
10988 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10989 if (pb->marshal_info) {
10991 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10992 specs [pb->position] =
10993 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10997 if (specs != NULL) {
10999 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11000 method_aux->param_marshall = specs;
11003 if (image_is_dynamic (klass->image) && method_aux)
11004 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11006 mono_loader_unlock ();
11012 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11014 ReflectionMethodBuilder rmb;
11015 MonoMethodSignature *sig;
11017 mono_loader_lock ();
11018 sig = ctor_builder_to_signature (klass->image, mb);
11019 mono_loader_unlock ();
11021 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11023 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11024 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11026 /* If we are in a generic class, we might be called multiple times from inflate_method */
11027 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11028 /* ilgen is no longer needed */
11032 return mb->mhandle;
11036 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11038 ReflectionMethodBuilder rmb;
11039 MonoMethodSignature *sig;
11041 mono_loader_lock ();
11042 sig = method_builder_to_signature (klass->image, mb);
11043 mono_loader_unlock ();
11045 reflection_methodbuilder_from_method_builder (&rmb, mb);
11047 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11048 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11050 /* If we are in a generic class, we might be called multiple times from inflate_method */
11051 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11052 /* ilgen is no longer needed */
11055 return mb->mhandle;
11058 static MonoClassField*
11059 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11061 MonoClassField *field;
11065 field = g_new0 (MonoClassField, 1);
11067 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11068 g_assert (mono_error_ok (&error));
11069 if (fb->attrs || fb->modreq || fb->modopt) {
11070 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11071 field->type->attrs = fb->attrs;
11073 g_assert (image_is_dynamic (klass->image));
11074 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11075 g_free (field->type);
11076 field->type = mono_metadata_type_dup (klass->image, custom);
11079 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11081 if (fb->offset != -1)
11082 field->offset = fb->offset;
11083 field->parent = klass;
11084 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11086 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11093 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11096 MonoReflectionTypeBuilder *tb = NULL;
11097 gboolean is_dynamic = FALSE;
11098 MonoClass *geninst;
11100 mono_loader_lock ();
11102 if (is_sre_type_builder (mono_object_class (type))) {
11103 tb = (MonoReflectionTypeBuilder *) type;
11106 } else if (is_sre_generic_instance (mono_object_class (type))) {
11107 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11108 MonoReflectionType *gtd = rgi->generic_type;
11110 if (is_sre_type_builder (mono_object_class (gtd))) {
11111 tb = (MonoReflectionTypeBuilder *)gtd;
11116 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11117 if (tb && tb->generic_container)
11118 mono_reflection_create_generic_class (tb);
11120 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11121 if (!klass->generic_container) {
11122 mono_loader_unlock ();
11126 if (klass->wastypebuilder) {
11127 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11132 mono_loader_unlock ();
11134 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11136 return &geninst->byval_arg;
11140 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11142 MonoGenericClass *gclass;
11143 MonoGenericInst *inst;
11145 g_assert (klass->generic_container);
11147 inst = mono_metadata_get_generic_inst (type_argc, types);
11148 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11150 return mono_generic_class_get_class (gclass);
11153 MonoReflectionMethod*
11154 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11158 MonoMethod *method, *inflated;
11159 MonoMethodInflated *imethod;
11160 MonoGenericContext tmp_context;
11161 MonoGenericInst *ginst;
11162 MonoType **type_argv;
11165 /*FIXME but this no longer should happen*/
11166 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11167 #ifndef DISABLE_REFLECTION_EMIT
11168 MonoReflectionMethodBuilder *mb = NULL;
11169 MonoReflectionTypeBuilder *tb;
11172 mb = (MonoReflectionMethodBuilder *) rmethod;
11173 tb = (MonoReflectionTypeBuilder *) mb->type;
11174 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11176 method = methodbuilder_to_mono_method (klass, mb);
11178 g_assert_not_reached ();
11182 method = rmethod->method;
11185 klass = method->klass;
11187 if (method->is_inflated)
11188 method = ((MonoMethodInflated *) method)->declaring;
11190 count = mono_method_signature (method)->generic_param_count;
11191 if (count != mono_array_length (types))
11194 type_argv = g_new0 (MonoType *, count);
11195 for (i = 0; i < count; i++) {
11196 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11197 type_argv [i] = mono_reflection_type_get_handle (garg);
11199 ginst = mono_metadata_get_generic_inst (count, type_argv);
11200 g_free (type_argv);
11202 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11203 tmp_context.method_inst = ginst;
11205 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11206 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11207 imethod = (MonoMethodInflated *) inflated;
11209 /*FIXME but I think this is no longer necessary*/
11210 if (image_is_dynamic (method->klass->image)) {
11211 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11213 * This table maps metadata structures representing inflated methods/fields
11214 * to the reflection objects representing their generic definitions.
11216 mono_image_lock ((MonoImage*)image);
11217 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11218 mono_image_unlock ((MonoImage*)image);
11221 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11222 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11224 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11227 #ifndef DISABLE_REFLECTION_EMIT
11229 static MonoMethod *
11230 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11232 MonoMethodInflated *imethod;
11233 MonoGenericContext *context;
11237 * With generic code sharing the klass might not be inflated.
11238 * This can happen because classes inflated with their own
11239 * type arguments are "normalized" to the uninflated class.
11241 if (!klass->generic_class)
11244 context = mono_class_get_context (klass);
11246 if (klass->method.count && klass->methods) {
11247 /* Find the already created inflated method */
11248 for (i = 0; i < klass->method.count; ++i) {
11249 g_assert (klass->methods [i]->is_inflated);
11250 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11253 g_assert (i < klass->method.count);
11254 imethod = (MonoMethodInflated*)klass->methods [i];
11257 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11258 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11261 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11262 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11264 mono_image_lock ((MonoImage*)image);
11265 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11266 mono_image_unlock ((MonoImage*)image);
11268 return (MonoMethod *) imethod;
11271 static MonoMethod *
11272 inflate_method (MonoReflectionType *type, MonoObject *obj)
11274 MonoMethod *method;
11277 MonoClass *type_class = mono_object_class (type);
11279 if (is_sre_generic_instance (type_class)) {
11280 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11281 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11282 } else if (is_sre_type_builder (type_class)) {
11283 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11284 } else if (type->type) {
11285 gklass = mono_class_from_mono_type (type->type);
11286 gklass = mono_class_get_generic_type_definition (gklass);
11288 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11291 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11292 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11293 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11295 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11296 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11297 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11298 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11299 method = ((MonoReflectionMethod *) obj)->method;
11301 method = NULL; /* prevent compiler warning */
11302 g_error ("can't handle type %s", obj->vtable->klass->name);
11305 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11308 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11310 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11312 MonoGenericClass *gclass;
11313 MonoDynamicGenericClass *dgclass;
11314 MonoClass *klass, *gklass;
11318 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11319 klass = mono_class_from_mono_type (gtype);
11320 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11321 gclass = gtype->data.generic_class;
11323 if (!gclass->is_dynamic)
11326 dgclass = (MonoDynamicGenericClass *) gclass;
11328 if (dgclass->initialized)
11331 gklass = gclass->container_class;
11332 mono_class_init (gklass);
11334 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11336 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11337 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11338 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11340 for (i = 0; i < dgclass->count_fields; i++) {
11341 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11342 MonoClassField *field, *inflated_field = NULL;
11344 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11345 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11346 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11347 field = ((MonoReflectionField *) obj)->field;
11349 field = NULL; /* prevent compiler warning */
11350 g_assert_not_reached ();
11353 dgclass->fields [i] = *field;
11354 dgclass->fields [i].parent = klass;
11355 dgclass->fields [i].type = mono_class_inflate_generic_type (
11356 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11357 dgclass->field_generic_types [i] = field->type;
11358 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11359 dgclass->field_objects [i] = obj;
11361 if (inflated_field) {
11362 g_free (inflated_field);
11364 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11368 dgclass->initialized = TRUE;
11372 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11374 MonoDynamicGenericClass *dgclass;
11377 g_assert (gclass->is_dynamic);
11379 dgclass = (MonoDynamicGenericClass *)gclass;
11381 for (i = 0; i < dgclass->count_fields; ++i) {
11382 MonoClassField *field = dgclass->fields + i;
11383 mono_metadata_free_type (field->type);
11384 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11389 fix_partial_generic_class (MonoClass *klass)
11391 MonoClass *gklass = klass->generic_class->container_class;
11392 MonoDynamicGenericClass *dgclass;
11395 if (klass->wastypebuilder)
11398 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11399 if (klass->parent != gklass->parent) {
11401 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11402 if (mono_error_ok (&error)) {
11403 MonoClass *parent = mono_class_from_mono_type (parent_type);
11404 mono_metadata_free_type (parent_type);
11405 if (parent != klass->parent) {
11406 /*fool mono_class_setup_parent*/
11407 klass->supertypes = NULL;
11408 mono_class_setup_parent (klass, parent);
11411 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11412 mono_error_cleanup (&error);
11413 if (gklass->wastypebuilder)
11414 klass->wastypebuilder = TRUE;
11419 if (!dgclass->initialized)
11422 if (klass->method.count != gklass->method.count) {
11423 klass->method.count = gklass->method.count;
11424 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11426 for (i = 0; i < klass->method.count; i++) {
11428 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11429 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11430 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11434 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11435 klass->interface_count = gklass->interface_count;
11436 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11437 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11439 for (i = 0; i < gklass->interface_count; ++i) {
11440 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11441 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11442 mono_metadata_free_type (iface_type);
11444 ensure_runtime_vtable (klass->interfaces [i]);
11446 klass->interfaces_inited = 1;
11449 if (klass->field.count != gklass->field.count) {
11450 klass->field.count = gklass->field.count;
11451 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11453 for (i = 0; i < klass->field.count; i++) {
11454 klass->fields [i] = gklass->fields [i];
11455 klass->fields [i].parent = klass;
11456 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11460 /*We can only finish with this klass once it's parent has as well*/
11461 if (gklass->wastypebuilder)
11462 klass->wastypebuilder = TRUE;
11467 ensure_generic_class_runtime_vtable (MonoClass *klass)
11469 MonoClass *gklass = klass->generic_class->container_class;
11471 ensure_runtime_vtable (gklass);
11473 fix_partial_generic_class (klass);
11477 ensure_runtime_vtable (MonoClass *klass)
11479 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11482 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11485 ensure_runtime_vtable (klass->parent);
11488 num = tb->ctors? mono_array_length (tb->ctors): 0;
11489 num += tb->num_methods;
11490 klass->method.count = num;
11491 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11492 num = tb->ctors? mono_array_length (tb->ctors): 0;
11493 for (i = 0; i < num; ++i)
11494 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11495 num = tb->num_methods;
11497 for (i = 0; i < num; ++i)
11498 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11500 if (tb->interfaces) {
11501 klass->interface_count = mono_array_length (tb->interfaces);
11502 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11503 for (i = 0; i < klass->interface_count; ++i) {
11504 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11505 klass->interfaces [i] = mono_class_from_mono_type (iface);
11506 ensure_runtime_vtable (klass->interfaces [i]);
11508 klass->interfaces_inited = 1;
11510 } else if (klass->generic_class){
11511 ensure_generic_class_runtime_vtable (klass);
11514 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11516 for (i = 0; i < klass->method.count; ++i) {
11517 MonoMethod *im = klass->methods [i];
11518 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11519 im->slot = slot_num++;
11522 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11523 mono_class_setup_interface_offsets (klass);
11524 mono_class_setup_interface_id (klass);
11528 * The generic vtable is needed even if image->run is not set since some
11529 * runtime code like ves_icall_Type_GetMethodsByName depends on
11530 * method->slot being defined.
11534 * tb->methods could not be freed since it is used for determining
11535 * overrides during dynamic vtable construction.
11540 mono_reflection_method_get_handle (MonoObject *method)
11542 MonoClass *klass = mono_object_class (method);
11543 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11544 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11545 return sr_method->method;
11547 if (is_sre_method_builder (klass)) {
11548 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11549 return mb->mhandle;
11551 if (is_sre_method_on_tb_inst (klass)) {
11552 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11553 MonoMethod *result;
11554 /*FIXME move this to a proper method and unify with resolve_object*/
11555 if (m->method_args) {
11556 result = mono_reflection_method_on_tb_inst_get_handle (m);
11558 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11559 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11560 MonoMethod *mono_method;
11562 if (is_sre_method_builder (mono_object_class (m->mb)))
11563 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11564 else if (is_sr_mono_method (mono_object_class (m->mb)))
11565 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11567 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)));
11569 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11574 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11579 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11581 MonoReflectionTypeBuilder *tb;
11583 MonoReflectionMethod *m;
11586 *num_overrides = 0;
11588 g_assert (image_is_dynamic (klass->image));
11590 if (!mono_class_get_ref_info (klass))
11593 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11595 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11599 for (i = 0; i < tb->num_methods; ++i) {
11600 MonoReflectionMethodBuilder *mb =
11601 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11602 if (mb->override_methods)
11603 onum += mono_array_length (mb->override_methods);
11608 *overrides = g_new0 (MonoMethod*, onum * 2);
11611 for (i = 0; i < tb->num_methods; ++i) {
11612 MonoReflectionMethodBuilder *mb =
11613 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11614 if (mb->override_methods) {
11615 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11616 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11618 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11619 (*overrides) [onum * 2 + 1] = mb->mhandle;
11621 g_assert (mb->mhandle);
11629 *num_overrides = onum;
11633 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11635 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11636 MonoReflectionFieldBuilder *fb;
11637 MonoClassField *field;
11638 MonoImage *image = klass->image;
11639 const char *p, *p2;
11641 guint32 len, idx, real_size = 0;
11643 klass->field.count = tb->num_fields;
11644 klass->field.first = 0;
11646 mono_error_init (error);
11648 if (tb->class_size) {
11649 if ((tb->packing_size & 0xffffff00) != 0) {
11650 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11651 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11654 klass->packing_size = tb->packing_size;
11655 real_size = klass->instance_size + tb->class_size;
11658 if (!klass->field.count) {
11659 klass->instance_size = MAX (klass->instance_size, real_size);
11663 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11664 mono_class_alloc_ext (klass);
11665 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11667 This is, guess what, a hack.
11668 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11669 On the static path no field class is resolved, only types are built. This is the right thing to do
11671 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11673 klass->size_inited = 1;
11675 for (i = 0; i < klass->field.count; ++i) {
11676 MonoArray *rva_data;
11677 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11678 field = &klass->fields [i];
11679 field->name = mono_string_to_utf8_image (image, fb->name, error);
11680 if (!mono_error_ok (error))
11683 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11684 field->type->attrs = fb->attrs;
11686 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11689 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11690 char *base = mono_array_addr (rva_data, char, 0);
11691 size_t size = mono_array_length (rva_data);
11692 char *data = (char *)mono_image_alloc (klass->image, size);
11693 memcpy (data, base, size);
11694 klass->ext->field_def_values [i].data = data;
11696 if (fb->offset != -1)
11697 field->offset = fb->offset;
11698 field->parent = klass;
11699 fb->handle = field;
11700 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11702 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11703 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11705 if (fb->def_value) {
11706 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11707 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11708 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11709 /* Copy the data from the blob since it might get realloc-ed */
11710 p = assembly->blob.data + idx;
11711 len = mono_metadata_decode_blob_size (p, &p2);
11713 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11714 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11718 klass->instance_size = MAX (klass->instance_size, real_size);
11719 mono_class_layout_fields (klass);
11723 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11725 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11726 MonoReflectionPropertyBuilder *pb;
11727 MonoImage *image = klass->image;
11728 MonoProperty *properties;
11731 mono_error_init (error);
11734 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11736 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11737 klass->ext->property.first = 0;
11739 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11740 klass->ext->properties = properties;
11741 for (i = 0; i < klass->ext->property.count; ++i) {
11742 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11743 properties [i].parent = klass;
11744 properties [i].attrs = pb->attrs;
11745 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11746 if (!mono_error_ok (error))
11748 if (pb->get_method)
11749 properties [i].get = pb->get_method->mhandle;
11750 if (pb->set_method)
11751 properties [i].set = pb->set_method->mhandle;
11753 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11754 if (pb->def_value) {
11756 const char *p, *p2;
11757 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11758 if (!klass->ext->prop_def_values)
11759 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11760 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11761 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11762 /* Copy the data from the blob since it might get realloc-ed */
11763 p = assembly->blob.data + idx;
11764 len = mono_metadata_decode_blob_size (p, &p2);
11766 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11767 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11772 MonoReflectionEvent *
11773 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11775 MonoEvent *event = g_new0 (MonoEvent, 1);
11778 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11780 event->parent = klass;
11781 event->attrs = eb->attrs;
11782 event->name = mono_string_to_utf8 (eb->name);
11783 if (eb->add_method)
11784 event->add = eb->add_method->mhandle;
11785 if (eb->remove_method)
11786 event->remove = eb->remove_method->mhandle;
11787 if (eb->raise_method)
11788 event->raise = eb->raise_method->mhandle;
11790 #ifndef MONO_SMALL_CONFIG
11791 if (eb->other_methods) {
11793 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11794 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11795 MonoReflectionMethodBuilder *mb =
11796 mono_array_get (eb->other_methods,
11797 MonoReflectionMethodBuilder*, j);
11798 event->other [j] = mb->mhandle;
11803 return mono_event_get_object (mono_object_domain (tb), klass, event);
11807 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11809 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11810 MonoReflectionEventBuilder *eb;
11811 MonoImage *image = klass->image;
11815 mono_error_init (error);
11818 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11820 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11821 klass->ext->event.first = 0;
11823 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11824 klass->ext->events = events;
11825 for (i = 0; i < klass->ext->event.count; ++i) {
11826 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11827 events [i].parent = klass;
11828 events [i].attrs = eb->attrs;
11829 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11830 if (!mono_error_ok (error))
11832 if (eb->add_method)
11833 events [i].add = eb->add_method->mhandle;
11834 if (eb->remove_method)
11835 events [i].remove = eb->remove_method->mhandle;
11836 if (eb->raise_method)
11837 events [i].raise = eb->raise_method->mhandle;
11839 #ifndef MONO_SMALL_CONFIG
11840 if (eb->other_methods) {
11842 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11843 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11844 MonoReflectionMethodBuilder *mb =
11845 mono_array_get (eb->other_methods,
11846 MonoReflectionMethodBuilder*, j);
11847 events [i].other [j] = mb->mhandle;
11851 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11856 remove_instantiations_of_and_ensure_contents (gpointer key,
11858 gpointer user_data)
11860 MonoType *type = (MonoType*)key;
11861 MonoClass *klass = (MonoClass*)user_data;
11863 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11864 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11871 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11873 mono_error_init (error);
11879 for (i = 0; i < mono_array_length (arr); ++i) {
11880 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11881 if (!mono_error_ok (error))
11886 MonoReflectionType*
11887 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11891 MonoDomain* domain;
11892 MonoReflectionType* res;
11895 domain = mono_object_domain (tb);
11896 klass = mono_class_from_mono_type (tb->type.type);
11899 * Check for user defined Type subclasses.
11901 RESOLVE_TYPE (tb->parent, &error);
11902 mono_error_raise_exception (&error); /* FIXME don't raise here */
11903 check_array_for_usertypes (tb->interfaces, &error);
11904 mono_error_raise_exception (&error); /*FIXME don't raise here */
11906 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11907 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11909 RESOLVE_TYPE (fb->type, &error);
11910 mono_error_raise_exception (&error); /* FIXME don't raise here */
11911 check_array_for_usertypes (fb->modreq, &error);
11912 mono_error_raise_exception (&error); /*FIXME don't raise here */
11913 check_array_for_usertypes (fb->modopt, &error);
11914 mono_error_raise_exception (&error); /*FIXME don't raise here */
11915 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11916 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11917 mono_error_raise_exception (&error); /* FIXME don't raise here */
11923 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11924 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11926 RESOLVE_TYPE (mb->rtype, &error);
11927 mono_error_raise_exception (&error); /* FIXME don't raise here */
11928 check_array_for_usertypes (mb->return_modreq, &error);
11929 mono_error_raise_exception (&error); /*FIXME don't raise here */
11930 check_array_for_usertypes (mb->return_modopt, &error);
11931 mono_error_raise_exception (&error); /*FIXME don't raise here */
11932 check_array_for_usertypes (mb->parameters, &error);
11933 mono_error_raise_exception (&error); /*FIXME don't raise here */
11934 if (mb->param_modreq)
11935 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11936 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11937 mono_error_raise_exception (&error); /*FIXME don't raise here */
11939 if (mb->param_modopt)
11940 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11941 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11942 mono_error_raise_exception (&error); /*FIXME don't raise here */
11948 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11949 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11951 check_array_for_usertypes (mb->parameters, &error);
11952 mono_error_raise_exception (&error); /*FIXME don't raise here */
11953 if (mb->param_modreq)
11954 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11955 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11956 mono_error_raise_exception (&error); /*FIXME don't raise here */
11958 if (mb->param_modopt)
11959 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11960 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11961 mono_error_raise_exception (&error); /*FIXME don't raise here */
11967 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11970 * we need to lock the domain because the lock will be taken inside
11971 * So, we need to keep the locking order correct.
11973 mono_loader_lock ();
11974 mono_domain_lock (domain);
11975 if (klass->wastypebuilder) {
11976 mono_domain_unlock (domain);
11977 mono_loader_unlock ();
11979 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11980 mono_error_raise_exception (&error); /* FIXME don't raise here */
11985 * Fields to set in klass:
11986 * the various flags: delegate/unicode/contextbound etc.
11988 klass->flags = tb->attrs;
11989 klass->has_cctor = 1;
11990 klass->has_finalize = 1;
11991 klass->has_finalize_inited = 1;
11993 mono_class_setup_parent (klass, klass->parent);
11994 /* fool mono_class_setup_supertypes */
11995 klass->supertypes = NULL;
11996 mono_class_setup_supertypes (klass);
11997 mono_class_setup_mono_type (klass);
12000 if (!((MonoDynamicImage*)klass->image)->run) {
12001 if (klass->generic_container) {
12002 /* FIXME: The code below can't handle generic classes */
12003 klass->wastypebuilder = TRUE;
12004 mono_loader_unlock ();
12005 mono_domain_unlock (domain);
12007 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12008 mono_error_raise_exception (&error); /* FIXME don't raise here */
12015 /* enums are done right away */
12016 if (!klass->enumtype)
12017 ensure_runtime_vtable (klass);
12019 if (tb->subtypes) {
12020 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12021 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12022 mono_class_alloc_ext (klass);
12023 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)));
12027 klass->nested_classes_inited = TRUE;
12029 /* fields and object layout */
12030 if (klass->parent) {
12031 if (!klass->parent->size_inited)
12032 mono_class_init (klass->parent);
12033 klass->instance_size = klass->parent->instance_size;
12034 klass->sizes.class_size = 0;
12035 klass->min_align = klass->parent->min_align;
12036 /* if the type has no fields we won't call the field_setup
12037 * routine which sets up klass->has_references.
12039 klass->has_references |= klass->parent->has_references;
12041 klass->instance_size = sizeof (MonoObject);
12042 klass->min_align = 1;
12045 /* FIXME: handle packing_size and instance_size */
12046 typebuilder_setup_fields (klass, &error);
12047 if (!mono_error_ok (&error))
12049 typebuilder_setup_properties (klass, &error);
12050 if (!mono_error_ok (&error))
12053 typebuilder_setup_events (klass, &error);
12054 if (!mono_error_ok (&error))
12057 klass->wastypebuilder = TRUE;
12060 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12061 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12062 * we want to return normal System.MonoType objects, so clear these out from the cache.
12064 * Together with this we must ensure the contents of all instances to match the created type.
12066 if (domain->type_hash && klass->generic_container)
12067 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12069 mono_domain_unlock (domain);
12070 mono_loader_unlock ();
12072 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12073 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12074 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12077 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12078 mono_error_raise_exception (&error); /* FIXME don't raise here */
12080 g_assert (res != (MonoReflectionType*)tb);
12085 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12086 klass->wastypebuilder = TRUE;
12087 mono_domain_unlock (domain);
12088 mono_loader_unlock ();
12089 mono_error_raise_exception (&error);
12094 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12096 MonoGenericParamFull *param;
12101 image = &gparam->tbuilder->module->dynamic_image->image;
12103 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12105 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12106 g_assert (mono_error_ok (&error));
12107 param->param.num = gparam->index;
12109 if (gparam->mbuilder) {
12110 if (!gparam->mbuilder->generic_container) {
12111 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12112 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12113 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12114 gparam->mbuilder->generic_container->is_method = TRUE;
12116 * Cannot set owner.method, since the MonoMethod is not created yet.
12117 * Set the image field instead, so type_in_image () works.
12119 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12120 gparam->mbuilder->generic_container->owner.image = klass->image;
12122 param->param.owner = gparam->mbuilder->generic_container;
12123 } else if (gparam->tbuilder) {
12124 if (!gparam->tbuilder->generic_container) {
12125 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12126 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12127 gparam->tbuilder->generic_container->owner.klass = klass;
12129 param->param.owner = gparam->tbuilder->generic_container;
12132 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12134 gparam->type.type = &pklass->byval_arg;
12136 mono_class_set_ref_info (pklass, gparam);
12137 mono_image_append_class_to_reflection_info_set (pklass);
12141 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12144 MonoReflectionModuleBuilder *module = sig->module;
12145 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12146 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12151 check_array_for_usertypes (sig->arguments, &error);
12152 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12154 sigbuffer_init (&buf, 32);
12156 sigbuffer_add_value (&buf, 0x07);
12157 sigbuffer_add_value (&buf, na);
12158 if (assembly != NULL){
12159 for (i = 0; i < na; ++i) {
12160 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12161 encode_reflection_type (assembly, type, &buf);
12165 buflen = buf.p - buf.buf;
12166 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12167 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12168 sigbuffer_free (&buf);
12174 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12177 MonoDynamicImage *assembly = sig->module->dynamic_image;
12178 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12183 check_array_for_usertypes (sig->arguments, &error);
12184 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12186 sigbuffer_init (&buf, 32);
12188 sigbuffer_add_value (&buf, 0x06);
12189 for (i = 0; i < na; ++i) {
12190 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12191 encode_reflection_type (assembly, type, &buf);
12194 buflen = buf.p - buf.buf;
12195 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12196 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12197 sigbuffer_free (&buf);
12203 MonoMethod *handle;
12204 MonoDomain *domain;
12205 } DynamicMethodReleaseData;
12208 * The runtime automatically clean up those after finalization.
12210 static MonoReferenceQueue *dynamic_method_queue;
12213 free_dynamic_method (void *dynamic_method)
12215 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12216 MonoDomain *domain = data->domain;
12217 MonoMethod *method = data->handle;
12220 mono_domain_lock (domain);
12221 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12222 g_hash_table_remove (domain->method_to_dyn_method, method);
12223 mono_domain_unlock (domain);
12224 g_assert (dis_link);
12225 mono_gchandle_free (dis_link);
12227 mono_runtime_free_method (domain, method);
12232 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12234 MonoReferenceQueue *queue;
12235 MonoMethod *handle;
12236 DynamicMethodReleaseData *release_data;
12237 ReflectionMethodBuilder rmb;
12238 MonoMethodSignature *sig;
12240 MonoDomain *domain;
12244 if (mono_runtime_is_shutting_down ())
12245 mono_raise_exception (mono_get_exception_invalid_operation (""));
12247 if (!(queue = dynamic_method_queue)) {
12248 mono_loader_lock ();
12249 if (!(queue = dynamic_method_queue))
12250 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12251 mono_loader_unlock ();
12254 sig = dynamic_method_to_signature (mb);
12256 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12259 * Resolve references.
12262 * Every second entry in the refs array is reserved for storing handle_class,
12263 * which is needed by the ldtoken implementation in the JIT.
12265 rmb.nrefs = mb->nrefs;
12266 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12267 for (i = 0; i < mb->nrefs; i += 2) {
12268 MonoClass *handle_class;
12270 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12272 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12273 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12275 * The referenced DynamicMethod should already be created by the managed
12276 * code, except in the case of circular references. In that case, we store
12277 * method in the refs array, and fix it up later when the referenced
12278 * DynamicMethod is created.
12280 if (method->mhandle) {
12281 ref = method->mhandle;
12283 /* FIXME: GC object stored in unmanaged memory */
12286 /* FIXME: GC object stored in unmanaged memory */
12287 method->referenced_by = g_slist_append (method->referenced_by, mb);
12289 handle_class = mono_defaults.methodhandle_class;
12291 MonoException *ex = NULL;
12292 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12294 ex = mono_get_exception_type_load (NULL, NULL);
12295 else if (mono_security_core_clr_enabled ())
12296 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12300 mono_raise_exception (ex);
12305 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12306 rmb.refs [i + 1] = handle_class;
12309 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12311 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12312 release_data = g_new (DynamicMethodReleaseData, 1);
12313 release_data->handle = handle;
12314 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12315 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12316 g_free (release_data);
12318 /* Fix up refs entries pointing at us */
12319 for (l = mb->referenced_by; l; l = l->next) {
12320 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12321 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12324 g_assert (method->mhandle);
12326 data = (gpointer*)wrapper->method_data;
12327 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12328 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12329 data [i + 1] = mb->mhandle;
12332 g_slist_free (mb->referenced_by);
12336 /* ilgen is no longer needed */
12339 domain = mono_domain_get ();
12340 mono_domain_lock (domain);
12341 if (!domain->method_to_dyn_method)
12342 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12343 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12344 mono_domain_unlock (domain);
12347 #endif /* DISABLE_REFLECTION_EMIT */
12351 * mono_reflection_is_valid_dynamic_token:
12353 * Returns TRUE if token is valid.
12357 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12359 return lookup_dyn_token (image, token) != NULL;
12362 MonoMethodSignature *
12363 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12365 MonoMethodSignature *sig;
12366 g_assert (image_is_dynamic (image));
12368 mono_error_init (error);
12370 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12374 return mono_method_signature_checked (method, error);
12377 #ifndef DISABLE_REFLECTION_EMIT
12380 * mono_reflection_lookup_dynamic_token:
12382 * Finish the Builder object pointed to by TOKEN and return the corresponding
12383 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12384 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12387 * LOCKING: Take the loader lock
12390 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12392 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12396 obj = lookup_dyn_token (assembly, token);
12399 g_error ("Could not find required dynamic token 0x%08x", token);
12405 handle_class = &klass;
12406 return resolve_object (image, obj, handle_class, context);
12410 * ensure_complete_type:
12412 * Ensure that KLASS is completed if it is a dynamic type, or references
12416 ensure_complete_type (MonoClass *klass)
12418 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12419 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12421 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12423 // Asserting here could break a lot of code
12424 //g_assert (klass->wastypebuilder);
12427 if (klass->generic_class) {
12428 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12431 for (i = 0; i < inst->type_argc; ++i) {
12432 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12438 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12440 gpointer result = NULL;
12442 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12443 result = mono_string_intern ((MonoString*)obj);
12444 *handle_class = mono_defaults.string_class;
12446 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12447 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12448 MonoClass *mc = mono_class_from_mono_type (type);
12449 if (!mono_class_init (mc))
12450 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12453 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12454 result = mono_class_from_mono_type (inflated);
12455 mono_metadata_free_type (inflated);
12457 result = mono_class_from_mono_type (type);
12459 *handle_class = mono_defaults.typehandle_class;
12461 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12462 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12463 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12464 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12465 result = ((MonoReflectionMethod*)obj)->method;
12468 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12469 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12471 *handle_class = mono_defaults.methodhandle_class;
12473 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12474 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12475 result = mb->mhandle;
12477 /* Type is not yet created */
12478 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12480 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12483 * Hopefully this has been filled in by calling CreateType() on the
12487 * TODO: This won't work if the application finishes another
12488 * TypeBuilder instance instead of this one.
12490 result = mb->mhandle;
12494 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12495 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12497 *handle_class = mono_defaults.methodhandle_class;
12498 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12499 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12501 result = cb->mhandle;
12503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12505 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12506 result = cb->mhandle;
12510 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12511 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12513 *handle_class = mono_defaults.methodhandle_class;
12514 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12515 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12517 ensure_complete_type (field->parent);
12519 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12520 MonoClass *klass = mono_class_from_mono_type (inflated);
12521 MonoClassField *inflated_field;
12522 gpointer iter = NULL;
12523 mono_metadata_free_type (inflated);
12524 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12525 if (!strcmp (field->name, inflated_field->name))
12528 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12529 result = inflated_field;
12533 *handle_class = mono_defaults.fieldhandle_class;
12535 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12536 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12537 result = fb->handle;
12540 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12542 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12543 result = fb->handle;
12546 if (fb->handle && fb->handle->parent->generic_container) {
12547 MonoClass *klass = fb->handle->parent;
12548 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12549 MonoClass *inflated = mono_class_from_mono_type (type);
12551 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12553 mono_metadata_free_type (type);
12555 *handle_class = mono_defaults.fieldhandle_class;
12556 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12557 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12558 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12561 klass = type->data.klass;
12562 if (klass->wastypebuilder) {
12563 /* Already created */
12567 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12568 result = type->data.klass;
12571 *handle_class = mono_defaults.typehandle_class;
12572 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12573 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12574 MonoMethodSignature *sig;
12577 if (helper->arguments)
12578 nargs = mono_array_length (helper->arguments);
12582 sig = mono_metadata_signature_alloc (image, nargs);
12583 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12584 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12586 if (helper->unmanaged_call_conv) { /* unmanaged */
12587 sig->call_convention = helper->unmanaged_call_conv - 1;
12588 sig->pinvoke = TRUE;
12589 } else if (helper->call_conv & 0x02) {
12590 sig->call_convention = MONO_CALL_VARARG;
12592 sig->call_convention = MONO_CALL_DEFAULT;
12595 sig->param_count = nargs;
12596 /* TODO: Copy type ? */
12597 sig->ret = helper->return_type->type;
12598 for (i = 0; i < nargs; ++i)
12599 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12602 *handle_class = NULL;
12603 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12604 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12605 /* Already created by the managed code */
12606 g_assert (method->mhandle);
12607 result = method->mhandle;
12608 *handle_class = mono_defaults.methodhandle_class;
12609 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12610 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12611 type = mono_class_inflate_generic_type (type, context);
12612 result = mono_class_from_mono_type (type);
12613 *handle_class = mono_defaults.typehandle_class;
12615 mono_metadata_free_type (type);
12616 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12617 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12618 type = mono_class_inflate_generic_type (type, context);
12619 result = mono_class_from_mono_type (type);
12620 *handle_class = mono_defaults.typehandle_class;
12622 mono_metadata_free_type (type);
12623 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12624 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12625 MonoClass *inflated;
12627 MonoClassField *field;
12629 if (is_sre_field_builder (mono_object_class (f->fb)))
12630 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12631 else if (is_sr_mono_field (mono_object_class (f->fb)))
12632 field = ((MonoReflectionField*)f->fb)->field;
12634 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)));
12636 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12637 inflated = mono_class_from_mono_type (type);
12639 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12640 ensure_complete_type (field->parent);
12642 mono_metadata_free_type (type);
12643 *handle_class = mono_defaults.fieldhandle_class;
12644 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12645 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12646 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12647 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12648 MonoMethod *method;
12650 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12651 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12652 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12653 method = ((MonoReflectionMethod *)c->cb)->method;
12655 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)));
12657 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12658 *handle_class = mono_defaults.methodhandle_class;
12659 mono_metadata_free_type (type);
12660 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12661 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12662 if (m->method_args) {
12663 result = mono_reflection_method_on_tb_inst_get_handle (m);
12666 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12667 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12670 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12671 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12672 MonoMethod *method;
12674 if (is_sre_method_builder (mono_object_class (m->mb)))
12675 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12676 else if (is_sr_mono_method (mono_object_class (m->mb)))
12677 method = ((MonoReflectionMethod *)m->mb)->method;
12679 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)));
12681 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12682 mono_metadata_free_type (type);
12684 *handle_class = mono_defaults.methodhandle_class;
12685 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12686 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12689 MonoMethod *method;
12693 mtype = mono_reflection_type_get_handle (m->parent);
12694 klass = mono_class_from_mono_type (mtype);
12696 /* Find the method */
12698 name = mono_string_to_utf8 (m->name);
12700 while ((method = mono_class_get_methods (klass, &iter))) {
12701 if (!strcmp (method->name, name))
12708 // FIXME: Check parameters/return value etc. match
12711 *handle_class = mono_defaults.methodhandle_class;
12712 } else if (is_sre_array (mono_object_get_class(obj)) ||
12713 is_sre_byref (mono_object_get_class(obj)) ||
12714 is_sre_pointer (mono_object_get_class(obj))) {
12715 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12716 MonoType *type = mono_reflection_type_get_handle (ref_type);
12719 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12720 result = mono_class_from_mono_type (inflated);
12721 mono_metadata_free_type (inflated);
12723 result = mono_class_from_mono_type (type);
12725 *handle_class = mono_defaults.typehandle_class;
12727 g_print ("%s\n", obj->vtable->klass->name);
12728 g_assert_not_reached ();
12733 #else /* DISABLE_REFLECTION_EMIT */
12736 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12738 g_assert_not_reached ();
12743 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12745 g_assert_not_reached ();
12749 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12751 g_assert_not_reached ();
12755 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12757 g_assert_not_reached ();
12761 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12763 g_assert_not_reached ();
12767 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12769 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12773 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12775 g_assert_not_reached ();
12779 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12781 g_assert_not_reached ();
12784 MonoReflectionModule *
12785 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12787 g_assert_not_reached ();
12792 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12794 g_assert_not_reached ();
12799 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12801 g_assert_not_reached ();
12806 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12807 gboolean create_open_instance, gboolean register_token)
12809 g_assert_not_reached ();
12814 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12819 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12821 g_assert_not_reached ();
12825 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12828 *num_overrides = 0;
12831 MonoReflectionEvent *
12832 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12834 g_assert_not_reached ();
12838 MonoReflectionType*
12839 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12841 g_assert_not_reached ();
12846 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12848 g_assert_not_reached ();
12852 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12854 g_assert_not_reached ();
12859 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12861 g_assert_not_reached ();
12866 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12871 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12877 mono_reflection_type_get_handle (MonoReflectionType* ref)
12885 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12887 g_assert_not_reached ();
12890 #endif /* DISABLE_REFLECTION_EMIT */
12892 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12893 const static guint32 declsec_flags_map[] = {
12894 0x00000000, /* empty */
12895 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12896 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12897 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12898 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12899 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12900 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12901 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12902 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12903 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12904 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12905 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12906 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12907 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12908 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12909 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12910 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12911 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12912 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12916 * Returns flags that includes all available security action associated to the handle.
12917 * @token: metadata token (either for a class or a method)
12918 * @image: image where resides the metadata.
12921 mono_declsec_get_flags (MonoImage *image, guint32 token)
12923 int index = mono_metadata_declsec_from_index (image, token);
12924 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12925 guint32 result = 0;
12929 /* HasSecurity can be present for other, not specially encoded, attributes,
12930 e.g. SuppressUnmanagedCodeSecurityAttribute */
12934 for (i = index; i < t->rows; i++) {
12935 guint32 cols [MONO_DECL_SECURITY_SIZE];
12937 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12938 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12941 action = cols [MONO_DECL_SECURITY_ACTION];
12942 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12943 result |= declsec_flags_map [action];
12945 g_assert_not_reached ();
12952 * Get the security actions (in the form of flags) associated with the specified method.
12954 * @method: The method for which we want the declarative security flags.
12955 * Return the declarative security flags for the method (only).
12957 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12958 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12961 mono_declsec_flags_from_method (MonoMethod *method)
12963 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12964 /* FIXME: No cache (for the moment) */
12965 guint32 idx = mono_method_get_index (method);
12966 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12967 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12968 return mono_declsec_get_flags (method->klass->image, idx);
12974 * Get the security actions (in the form of flags) associated with the specified class.
12976 * @klass: The class for which we want the declarative security flags.
12977 * Return the declarative security flags for the class.
12979 * Note: We cache the flags inside the MonoClass structure as this will get
12980 * called very often (at least for each method).
12983 mono_declsec_flags_from_class (MonoClass *klass)
12985 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12986 if (!klass->ext || !klass->ext->declsec_flags) {
12989 idx = mono_metadata_token_index (klass->type_token);
12990 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12991 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12992 mono_loader_lock ();
12993 mono_class_alloc_ext (klass);
12994 mono_loader_unlock ();
12995 /* we cache the flags on classes */
12996 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12998 return klass->ext->declsec_flags;
13004 * Get the security actions (in the form of flags) associated with the specified assembly.
13006 * @assembly: The assembly for which we want the declarative security flags.
13007 * Return the declarative security flags for the assembly.
13010 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13012 guint32 idx = 1; /* there is only one assembly */
13013 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13014 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13015 return mono_declsec_get_flags (assembly->image, idx);
13020 * Fill actions for the specific index (which may either be an encoded class token or
13021 * an encoded method token) from the metadata image.
13022 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13025 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13026 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13028 MonoBoolean result = FALSE;
13030 guint32 cols [MONO_DECL_SECURITY_SIZE];
13031 int index = mono_metadata_declsec_from_index (image, token);
13034 t = &image->tables [MONO_TABLE_DECLSECURITY];
13035 for (i = index; i < t->rows; i++) {
13036 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13038 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13041 /* if present only replace (class) permissions with method permissions */
13042 /* if empty accept either class or method permissions */
13043 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13044 if (!actions->demand.blob) {
13045 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13046 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13047 actions->demand.blob = (char*) (blob + 2);
13048 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13051 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13052 if (!actions->noncasdemand.blob) {
13053 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13054 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13055 actions->noncasdemand.blob = (char*) (blob + 2);
13056 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13059 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13060 if (!actions->demandchoice.blob) {
13061 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13062 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13063 actions->demandchoice.blob = (char*) (blob + 2);
13064 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13074 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13075 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13077 guint32 idx = mono_metadata_token_index (klass->type_token);
13078 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13079 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13080 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13084 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13085 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13087 guint32 idx = mono_method_get_index (method);
13088 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13089 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13090 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13094 * Collect all actions (that requires to generate code in mini) assigned for
13095 * the specified method.
13096 * Note: Don't use the content of actions if the function return FALSE.
13099 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13101 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13102 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13103 MonoBoolean result = FALSE;
13106 /* quick exit if no declarative security is present in the metadata */
13107 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13110 /* we want the original as the wrapper is "free" of the security informations */
13111 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13112 method = mono_marshal_method_from_wrapper (method);
13117 /* First we look for method-level attributes */
13118 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13119 mono_class_init (method->klass);
13120 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13122 result = mono_declsec_get_method_demands_params (method, demands,
13123 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13126 /* Here we use (or create) the class declarative cache to look for demands */
13127 flags = mono_declsec_flags_from_class (method->klass);
13128 if (flags & mask) {
13130 mono_class_init (method->klass);
13131 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13133 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13134 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13137 /* The boolean return value is used as a shortcut in case nothing needs to
13138 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13144 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13146 * Note: Don't use the content of actions if the function return FALSE.
13149 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13151 MonoBoolean result = FALSE;
13154 /* quick exit if no declarative security is present in the metadata */
13155 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13158 /* we want the original as the wrapper is "free" of the security informations */
13159 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13160 method = mono_marshal_method_from_wrapper (method);
13165 /* results are independant - zeroize both */
13166 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13167 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13169 /* First we look for method-level attributes */
13170 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13171 mono_class_init (method->klass);
13173 result = mono_declsec_get_method_demands_params (method, cmethod,
13174 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13177 /* Here we use (or create) the class declarative cache to look for demands */
13178 flags = mono_declsec_flags_from_class (method->klass);
13179 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13180 mono_class_init (method->klass);
13182 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13183 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13190 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13192 * @klass The inherited class - this is the class that provides the security check (attributes)
13194 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13196 * Note: Don't use the content of actions if the function return FALSE.
13199 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13201 MonoBoolean result = FALSE;
13204 /* quick exit if no declarative security is present in the metadata */
13205 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13208 /* Here we use (or create) the class declarative cache to look for demands */
13209 flags = mono_declsec_flags_from_class (klass);
13210 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13211 mono_class_init (klass);
13212 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13214 result |= mono_declsec_get_class_demands_params (klass, demands,
13215 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13222 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13224 * Note: Don't use the content of actions if the function return FALSE.
13227 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13229 /* quick exit if no declarative security is present in the metadata */
13230 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13233 /* we want the original as the wrapper is "free" of the security informations */
13234 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13235 method = mono_marshal_method_from_wrapper (method);
13240 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13241 mono_class_init (method->klass);
13242 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13244 return mono_declsec_get_method_demands_params (method, demands,
13245 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13252 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13254 guint32 cols [MONO_DECL_SECURITY_SIZE];
13258 int index = mono_metadata_declsec_from_index (image, token);
13262 t = &image->tables [MONO_TABLE_DECLSECURITY];
13263 for (i = index; i < t->rows; i++) {
13264 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13266 /* shortcut - index are ordered */
13267 if (token != cols [MONO_DECL_SECURITY_PARENT])
13270 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13271 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13272 entry->blob = (char*) (metadata + 2);
13273 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13282 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13284 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13285 guint32 idx = mono_method_get_index (method);
13286 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13287 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13288 return get_declsec_action (method->klass->image, idx, action, entry);
13294 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13297 guint32 flags = mono_declsec_flags_from_class (klass);
13298 if (declsec_flags_map [action] & flags) {
13299 guint32 idx = mono_metadata_token_index (klass->type_token);
13300 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13301 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13302 return get_declsec_action (klass->image, idx, action, entry);
13308 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13310 guint32 idx = 1; /* there is only one assembly */
13311 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13312 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13314 return get_declsec_action (assembly->image, idx, action, entry);
13318 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13321 MonoObject *res, *exc;
13323 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13324 static MonoMethod *method = NULL;
13326 if (!System_Reflection_Emit_TypeBuilder) {
13327 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13328 g_assert (System_Reflection_Emit_TypeBuilder);
13330 if (method == NULL) {
13331 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13336 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13337 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13339 g_assert (mono_class_get_ref_info (klass));
13340 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13342 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13343 mono_error_raise_exception (&error); /* FIXME don't raise here */
13345 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13349 return *(MonoBoolean*)mono_object_unbox (res);
13353 * mono_reflection_type_get_type:
13354 * @reftype: the System.Type object
13356 * Returns the MonoType* associated with the C# System.Type object @reftype.
13359 mono_reflection_type_get_type (MonoReflectionType *reftype)
13361 g_assert (reftype);
13363 return mono_reflection_type_get_handle (reftype);
13367 * mono_reflection_assembly_get_assembly:
13368 * @refassembly: the System.Reflection.Assembly object
13370 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13373 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13375 g_assert (refassembly);
13377 return refassembly->assembly;