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)
6504 static MonoClass *assembly_type;
6505 MonoReflectionAssembly *res;
6507 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6508 if (!assembly_type) {
6509 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6511 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6513 assembly_type = klass;
6515 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6516 mono_error_raise_exception (&error); /* FIXME don't raise here */
6517 res->assembly = assembly;
6519 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6524 MonoReflectionModule*
6525 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6528 static MonoClass *module_type;
6529 MonoReflectionModule *res;
6532 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6534 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6536 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6538 module_type = klass;
6540 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6541 mono_error_raise_exception (&error); /* FIXME don't raise here */
6544 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6546 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6547 basename = g_path_get_basename (image->name);
6548 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6549 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6553 if (image->assembly->image == image) {
6554 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6558 if (image->assembly->image->modules) {
6559 for (i = 0; i < image->assembly->image->module_count; i++) {
6560 if (image->assembly->image->modules [i] == image)
6561 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6563 g_assert (res->token);
6567 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6570 MonoReflectionModule*
6571 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6574 static MonoClass *module_type;
6575 MonoReflectionModule *res;
6576 MonoTableInfo *table;
6577 guint32 cols [MONO_FILE_SIZE];
6579 guint32 i, name_idx;
6583 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6585 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6587 module_type = klass;
6589 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6590 mono_error_raise_exception (&error); /* FIXME don't raise here */
6592 table = &image->tables [MONO_TABLE_FILE];
6593 g_assert (table_index < table->rows);
6594 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6597 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6598 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6600 /* Check whenever the row has a corresponding row in the moduleref table */
6601 table = &image->tables [MONO_TABLE_MODULEREF];
6602 for (i = 0; i < table->rows; ++i) {
6603 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6604 val = mono_metadata_string_heap (image, name_idx);
6605 if (strcmp (val, name) == 0)
6606 res->image = image->modules [i];
6609 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6610 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6611 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6612 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6613 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6619 verify_safe_for_managed_space (MonoType *type)
6621 switch (type->type) {
6623 case MONO_TYPE_ARRAY:
6624 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6626 return verify_safe_for_managed_space (type->data.type);
6627 case MONO_TYPE_SZARRAY:
6628 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6629 case MONO_TYPE_GENERICINST: {
6630 MonoGenericInst *inst = type->data.generic_class->inst;
6634 for (i = 0; i < inst->type_argc; ++i)
6635 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6641 case MONO_TYPE_MVAR:
6649 mono_type_normalize (MonoType *type)
6652 MonoGenericClass *gclass;
6653 MonoGenericInst *ginst;
6655 MonoGenericContainer *gcontainer;
6656 MonoType **argv = NULL;
6657 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6659 if (type->type != MONO_TYPE_GENERICINST)
6662 gclass = type->data.generic_class;
6663 ginst = gclass->context.class_inst;
6664 if (!ginst->is_open)
6667 gtd = gclass->container_class;
6668 gcontainer = gtd->generic_container;
6669 argv = g_newa (MonoType*, ginst->type_argc);
6671 for (i = 0; i < ginst->type_argc; ++i) {
6672 MonoType *t = ginst->type_argv [i], *norm;
6673 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6674 is_denorm_gtd = FALSE;
6675 norm = mono_type_normalize (t);
6678 requires_rebind = TRUE;
6682 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6684 if (requires_rebind) {
6685 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6686 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6692 * mono_type_get_object:
6693 * @domain: an app domain
6696 * Return an System.MonoType object representing the type @type.
6699 mono_type_get_object (MonoDomain *domain, MonoType *type)
6702 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6703 mono_error_raise_exception (&error);
6709 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6711 MonoType *norm_type;
6712 MonoReflectionType *res;
6715 mono_error_init (error);
6717 klass = mono_class_from_mono_type (type);
6719 /*we must avoid using @type as it might have come
6720 * from a mono_metadata_type_dup and the caller
6721 * expects that is can be freed.
6722 * Using the right type from
6724 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6726 /* void is very common */
6727 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6728 return (MonoReflectionType*)domain->typeof_void;
6731 * If the vtable of the given class was already created, we can use
6732 * the MonoType from there and avoid all locking and hash table lookups.
6734 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6735 * that the resulting object is different.
6737 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6738 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6739 if (vtable && vtable->type)
6740 return (MonoReflectionType *)vtable->type;
6743 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6744 mono_domain_lock (domain);
6745 if (!domain->type_hash)
6746 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6747 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6748 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6749 mono_domain_unlock (domain);
6750 mono_loader_unlock ();
6754 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6755 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6756 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6757 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6758 * artifact of how generics are encoded and should be transparent to managed code so we
6759 * need to weed out this diference when retrieving managed System.Type objects.
6761 norm_type = mono_type_normalize (type);
6762 if (norm_type != type) {
6763 res = mono_type_get_object_checked (domain, norm_type, error);
6764 if (!mono_error_ok (error))
6766 mono_g_hash_table_insert (domain->type_hash, type, res);
6767 mono_domain_unlock (domain);
6768 mono_loader_unlock ();
6772 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6773 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6776 if (!verify_safe_for_managed_space (type)) {
6777 mono_domain_unlock (domain);
6778 mono_loader_unlock ();
6779 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6782 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6783 gboolean is_type_done = TRUE;
6784 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6785 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6786 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6788 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6789 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6791 if (gparam->owner && gparam->owner->is_method) {
6792 MonoMethod *method = gparam->owner->owner.method;
6793 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6794 is_type_done = FALSE;
6795 } else if (gparam->owner && !gparam->owner->is_method) {
6796 MonoClass *klass = gparam->owner->owner.klass;
6797 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6798 is_type_done = FALSE;
6802 /* g_assert_not_reached (); */
6803 /* should this be considered an error condition? */
6804 if (is_type_done && !type->byref) {
6805 mono_domain_unlock (domain);
6806 mono_loader_unlock ();
6807 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6810 /* This is stored in vtables/JITted code so it has to be pinned */
6811 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6812 if (!mono_error_ok (error))
6816 mono_g_hash_table_insert (domain->type_hash, type, res);
6818 if (type->type == MONO_TYPE_VOID)
6819 domain->typeof_void = (MonoObject*)res;
6821 mono_domain_unlock (domain);
6822 mono_loader_unlock ();
6827 * mono_method_get_object:
6828 * @domain: an app domain
6830 * @refclass: the reflected type (can be NULL)
6832 * Return an System.Reflection.MonoMethod object representing the method @method.
6834 MonoReflectionMethod*
6835 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6838 MonoReflectionMethod *ret = NULL;
6839 ret = mono_method_get_object_checked (domain, method, refclass, &error);
6840 mono_error_raise_exception (&error);
6845 * mono_method_get_object_checked:
6846 * @domain: an app domain
6848 * @refclass: the reflected type (can be NULL)
6849 * @error: set on error.
6851 * Return an System.Reflection.MonoMethod object representing the method @method.
6852 * Returns NULL and sets @error on error.
6854 MonoReflectionMethod*
6855 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6858 * We use the same C representation for methods and constructors, but the type
6859 * name in C# is different.
6861 static MonoClass *System_Reflection_MonoMethod = NULL;
6862 static MonoClass *System_Reflection_MonoCMethod = NULL;
6863 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6864 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6865 MonoReflectionType *rt;
6867 MonoReflectionMethod *ret;
6869 mono_error_init (error);
6871 if (method->is_inflated) {
6872 MonoReflectionGenericMethod *gret;
6875 refclass = method->klass;
6876 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6877 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6878 if (!System_Reflection_MonoGenericCMethod) {
6879 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6880 if (!mono_error_ok (error))
6883 klass = System_Reflection_MonoGenericCMethod;
6885 if (!System_Reflection_MonoGenericMethod) {
6886 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
6887 if (!mono_error_ok (error))
6890 klass = System_Reflection_MonoGenericMethod;
6892 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
6893 if (!mono_error_ok (error))
6895 gret->method.method = method;
6897 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6899 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
6900 if (!mono_error_ok (error))
6903 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6905 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6909 refclass = method->klass;
6911 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6912 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6913 if (!System_Reflection_MonoCMethod) {
6914 System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
6915 if (!mono_error_ok (error))
6918 klass = System_Reflection_MonoCMethod;
6921 if (!System_Reflection_MonoMethod) {
6922 System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
6923 if (!mono_error_ok (error))
6926 klass = System_Reflection_MonoMethod;
6928 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
6929 if (!mono_error_ok (error))
6931 ret->method = method;
6933 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
6934 if (!mono_error_ok (error))
6937 MONO_OBJECT_SETREF (ret, reftype, rt);
6939 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6942 g_assert (!mono_error_ok (error));
6947 * mono_method_clear_object:
6949 * Clear the cached reflection objects for the dynamic method METHOD.
6952 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6955 g_assert (method_is_dynamic (method));
6957 klass = method->klass;
6959 clear_cached_object (domain, method, klass);
6960 klass = klass->parent;
6962 /* Added by mono_param_get_objects () */
6963 clear_cached_object (domain, &(method->signature), NULL);
6964 klass = method->klass;
6966 clear_cached_object (domain, &(method->signature), klass);
6967 klass = klass->parent;
6972 * mono_field_get_object:
6973 * @domain: an app domain
6977 * Return an System.Reflection.MonoField object representing the field @field
6980 MonoReflectionField*
6981 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6984 MonoReflectionField *result;
6985 result = mono_field_get_object_checked (domain, klass, field, &error);
6986 mono_error_raise_exception (&error);
6991 * mono_field_get_object_checked:
6992 * @domain: an app domain
6995 * @error: set on error
6997 * Return an System.Reflection.MonoField object representing the field @field
6998 * in class @klass. On error, returns NULL and sets @error.
7000 MonoReflectionField*
7001 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7003 MonoReflectionType *rt;
7004 MonoReflectionField *res;
7005 static MonoClass *monofield_klass;
7007 mono_error_init (error);
7009 CHECK_OBJECT (MonoReflectionField *, field, klass);
7010 if (!monofield_klass)
7011 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7012 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7013 mono_error_raise_exception (error); /* FIXME don't raise here */
7016 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7018 if (is_field_on_inst (field)) {
7019 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7021 rt = mono_type_get_object_checked (domain, field->type, error);
7022 if (!mono_error_ok (error))
7025 MONO_OBJECT_SETREF (res, type, rt);
7028 rt = mono_type_get_object_checked (domain, field->type, error);
7029 if (!mono_error_ok (error))
7032 MONO_OBJECT_SETREF (res, type, rt);
7034 res->attrs = mono_field_get_flags (field);
7036 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7040 * mono_property_get_object:
7041 * @domain: an app domain
7043 * @property: a property
7045 * Return an System.Reflection.MonoProperty object representing the property @property
7048 MonoReflectionProperty*
7049 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7052 MonoReflectionProperty *res;
7053 static MonoClass *monoproperty_klass;
7055 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7056 if (!monoproperty_klass)
7057 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7058 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7059 mono_error_raise_exception (&error); /* FIXME don't raise here */
7061 res->property = property;
7062 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7066 * mono_event_get_object:
7067 * @domain: an app domain
7071 * Return an System.Reflection.MonoEvent object representing the event @event
7074 MonoReflectionEvent*
7075 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7078 MonoReflectionEvent *res;
7079 MonoReflectionMonoEvent *mono_event;
7080 static MonoClass *monoevent_klass;
7082 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7083 if (!monoevent_klass)
7084 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7085 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7086 mono_error_raise_exception (&error); /* FIXME don't raise here */
7087 mono_event->klass = klass;
7088 mono_event->event = event;
7089 res = (MonoReflectionEvent*)mono_event;
7090 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7094 * mono_get_reflection_missing_object:
7095 * @domain: Domain where the object lives
7097 * Returns the System.Reflection.Missing.Value singleton object
7098 * (of type System.Reflection.Missing).
7100 * Used as the value for ParameterInfo.DefaultValue when Optional
7104 mono_get_reflection_missing_object (MonoDomain *domain)
7107 static MonoClassField *missing_value_field = NULL;
7109 if (!missing_value_field) {
7110 MonoClass *missing_klass;
7111 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7112 mono_class_init (missing_klass);
7113 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7114 g_assert (missing_value_field);
7116 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7122 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7125 *dbnull = mono_get_dbnull_object (domain);
7130 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7132 if (!*reflection_missing)
7133 *reflection_missing = mono_get_reflection_missing_object (domain);
7134 return *reflection_missing;
7138 * mono_param_get_objects:
7139 * @domain: an app domain
7142 * Return an System.Reflection.ParameterInfo array object representing the parameters
7143 * in the method @method.
7146 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7148 static MonoClass *System_Reflection_ParameterInfo;
7149 static MonoClass *System_Reflection_ParameterInfo_array;
7151 MonoArray *res = NULL;
7152 MonoReflectionMethod *member = NULL;
7153 MonoReflectionParameter *param = NULL;
7154 char **names, **blobs = NULL;
7155 guint32 *types = NULL;
7156 MonoType *type = NULL;
7157 MonoObject *dbnull = NULL;
7158 MonoObject *missing = NULL;
7159 MonoMarshalSpec **mspecs;
7160 MonoMethodSignature *sig;
7161 MonoVTable *pinfo_vtable;
7162 MonoReflectionType *rt;
7165 if (!System_Reflection_ParameterInfo_array) {
7168 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7170 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7172 mono_memory_barrier ();
7173 System_Reflection_ParameterInfo = klass;
7176 klass = mono_array_class_get (klass, 1);
7177 mono_memory_barrier ();
7178 System_Reflection_ParameterInfo_array = klass;
7181 sig = mono_method_signature_checked (method, &error);
7182 if (!mono_error_ok (&error))
7183 mono_error_raise_exception (&error);
7185 if (!sig->param_count) {
7186 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7187 mono_error_raise_exception (&error); /* FIXME don't raise here */
7192 /* Note: the cache is based on the address of the signature into the method
7193 * since we already cache MethodInfos with the method as keys.
7195 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7197 member = mono_method_get_object_checked (domain, method, refclass, &error);
7198 mono_error_raise_exception (&error); /* FIXME don't raise here */
7199 names = g_new (char *, sig->param_count);
7200 mono_method_get_param_names (method, (const char **) names);
7202 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7203 mono_method_get_marshal_info (method, mspecs);
7205 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7206 mono_error_raise_exception (&error); /* FIXME don't raise here */
7208 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7209 for (i = 0; i < sig->param_count; ++i) {
7210 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7211 mono_error_raise_exception (&error); /* FIXME don't raise here */
7213 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7214 mono_error_raise_exception (&error); /* FIXME don't raise here */
7216 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7218 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7220 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7222 param->PositionImpl = i;
7223 param->AttrsImpl = sig->params [i]->attrs;
7225 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7226 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7227 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7229 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7233 blobs = g_new0 (char *, sig->param_count);
7234 types = g_new0 (guint32, sig->param_count);
7235 get_default_param_value_blobs (method, blobs, types);
7238 /* Build MonoType for the type from the Constant Table */
7240 type = g_new0 (MonoType, 1);
7241 type->type = (MonoTypeEnum)types [i];
7242 type->data.klass = NULL;
7243 if (types [i] == MONO_TYPE_CLASS)
7244 type->data.klass = mono_defaults.object_class;
7245 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7246 /* For enums, types [i] contains the base type */
7248 type->type = MONO_TYPE_VALUETYPE;
7249 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7251 type->data.klass = mono_class_from_mono_type (type);
7253 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7255 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7256 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7257 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7258 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7260 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7266 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7268 mono_array_setref (res, i, param);
7275 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7277 mono_metadata_free_marshal_spec (mspecs [i]);
7280 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7284 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7286 return mono_param_get_objects_internal (domain, method, NULL);
7290 * mono_method_body_get_object:
7291 * @domain: an app domain
7294 * Return an System.Reflection.MethodBody object representing the method @method.
7296 MonoReflectionMethodBody*
7297 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7299 static MonoClass *System_Reflection_MethodBody = NULL;
7300 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7301 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7303 MonoReflectionMethodBody *ret;
7304 MonoMethodHeader *header;
7306 MonoReflectionType *rt;
7307 guint32 method_rva, local_var_sig_token;
7309 unsigned char format, flags;
7312 /* for compatibility with .net */
7313 if (method_is_dynamic (method))
7314 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7316 if (!System_Reflection_MethodBody)
7317 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7318 if (!System_Reflection_LocalVariableInfo)
7319 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7320 if (!System_Reflection_ExceptionHandlingClause)
7321 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7323 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7325 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7326 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7327 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7328 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7329 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7332 image = method->klass->image;
7333 header = mono_method_get_header (method);
7335 if (!image_is_dynamic (image)) {
7336 /* Obtain local vars signature token */
7337 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7338 ptr = mono_image_rva_map (image, method_rva);
7339 flags = *(const unsigned char *) ptr;
7340 format = flags & METHOD_HEADER_FORMAT_MASK;
7342 case METHOD_HEADER_TINY_FORMAT:
7343 local_var_sig_token = 0;
7345 case METHOD_HEADER_FAT_FORMAT:
7349 local_var_sig_token = read32 (ptr);
7352 g_assert_not_reached ();
7355 local_var_sig_token = 0; //FIXME
7357 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7358 mono_error_raise_exception (&error); /* FIXME don't raise here */
7360 ret->init_locals = header->init_locals;
7361 ret->max_stack = header->max_stack;
7362 ret->local_var_sig_token = local_var_sig_token;
7363 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7364 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7367 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7368 for (i = 0; i < header->num_locals; ++i) {
7369 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7370 mono_error_raise_exception (&error); /* FIXME don't raise here */
7372 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7373 mono_error_raise_exception (&error); /* FIXME don't raise here */
7375 MONO_OBJECT_SETREF (info, local_type, rt);
7377 info->is_pinned = header->locals [i]->pinned;
7378 info->local_index = i;
7379 mono_array_setref (ret->locals, i, info);
7383 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7384 for (i = 0; i < header->num_clauses; ++i) {
7385 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7386 mono_error_raise_exception (&error); /* FIXME don't raise here */
7387 MonoExceptionClause *clause = &header->clauses [i];
7389 info->flags = clause->flags;
7390 info->try_offset = clause->try_offset;
7391 info->try_length = clause->try_len;
7392 info->handler_offset = clause->handler_offset;
7393 info->handler_length = clause->handler_len;
7394 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7395 info->filter_offset = clause->data.filter_offset;
7396 else if (clause->data.catch_class) {
7397 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7398 mono_error_raise_exception (&error); /* FIXME don't raise here */
7400 MONO_OBJECT_SETREF (info, catch_type, rt);
7403 mono_array_setref (ret->clauses, i, info);
7406 mono_metadata_free_mh (header);
7407 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7412 * mono_get_dbnull_object:
7413 * @domain: Domain where the object lives
7415 * Returns the System.DBNull.Value singleton object
7417 * Used as the value for ParameterInfo.DefaultValue
7420 mono_get_dbnull_object (MonoDomain *domain)
7423 static MonoClassField *dbnull_value_field = NULL;
7425 if (!dbnull_value_field) {
7426 MonoClass *dbnull_klass;
7427 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7428 mono_class_init (dbnull_klass);
7429 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7430 g_assert (dbnull_value_field);
7432 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7438 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7440 guint32 param_index, i, lastp, crow = 0;
7441 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7444 MonoClass *klass = method->klass;
7445 MonoImage *image = klass->image;
7446 MonoMethodSignature *methodsig = mono_method_signature (method);
7448 MonoTableInfo *constt;
7449 MonoTableInfo *methodt;
7450 MonoTableInfo *paramt;
7452 if (!methodsig->param_count)
7455 mono_class_init (klass);
7457 if (image_is_dynamic (klass->image)) {
7458 MonoReflectionMethodAux *aux;
7459 if (method->is_inflated)
7460 method = ((MonoMethodInflated*)method)->declaring;
7461 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7462 if (aux && aux->param_defaults) {
7463 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7464 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7469 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7470 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7471 constt = &image->tables [MONO_TABLE_CONSTANT];
7473 idx = mono_method_get_index (method) - 1;
7474 g_assert (idx != -1);
7476 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7477 if (idx + 1 < methodt->rows)
7478 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7480 lastp = paramt->rows + 1;
7482 for (i = param_index; i < lastp; ++i) {
7485 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7486 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7488 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7491 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7496 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7497 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7498 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7505 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7511 MonoType *basetype = type;
7516 klass = mono_class_from_mono_type (type);
7517 if (klass->valuetype) {
7518 object = mono_object_new_checked (domain, klass, &error);
7519 mono_error_raise_exception (&error); /* FIXME don't raise here */
7520 retval = ((gchar *) object + sizeof (MonoObject));
7521 if (klass->enumtype)
7522 basetype = mono_class_enum_basetype (klass);
7527 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7534 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7537 gboolean quoted = FALSE;
7539 memset (assembly, 0, sizeof (MonoAssemblyName));
7540 assembly->culture = "";
7541 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7548 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7559 /* Remove trailing whitespace */
7561 while (*s && g_ascii_isspace (*s))
7564 while (g_ascii_isspace (*p))
7567 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7569 assembly->major = strtoul (p, &s, 10);
7570 if (s == p || *s != '.')
7573 assembly->minor = strtoul (p, &s, 10);
7574 if (s == p || *s != '.')
7577 assembly->build = strtoul (p, &s, 10);
7578 if (s == p || *s != '.')
7581 assembly->revision = strtoul (p, &s, 10);
7585 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7587 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7588 assembly->culture = "";
7591 assembly->culture = p;
7592 while (*p && *p != ',') {
7596 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7598 if (strncmp (p, "null", 4) == 0) {
7603 while (*p && *p != ',') {
7606 len = (p - start + 1);
7607 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7608 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7609 g_strlcpy ((char*)assembly->public_key_token, start, len);
7612 while (*p && *p != ',')
7616 while (g_ascii_isspace (*p) || *p == ',') {
7630 * mono_reflection_parse_type:
7633 * Parse a type name as accepted by the GetType () method and output the info
7634 * extracted in the info structure.
7635 * the name param will be mangled, so, make a copy before passing it to this function.
7636 * The fields in info will be valid until the memory pointed to by name is valid.
7638 * See also mono_type_get_name () below.
7640 * Returns: 0 on parse error.
7643 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7644 MonoTypeNameParse *info)
7646 char *start, *p, *w, *last_point, *startn;
7647 int in_modifiers = 0;
7648 int isbyref = 0, rank = 0, isptr = 0;
7650 start = p = w = name;
7652 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7653 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7654 info->name = info->name_space = NULL;
7655 info->nested = NULL;
7656 info->modifiers = NULL;
7657 info->type_arguments = NULL;
7659 /* last_point separates the namespace from the name */
7662 while (*p == ' ') p++, start++, w++, name++;
7667 *p = 0; /* NULL terminate the name */
7669 info->nested = g_list_append (info->nested, startn);
7670 /* we have parsed the nesting namespace + name */
7674 info->name_space = start;
7676 info->name = last_point + 1;
7678 info->name_space = (char *)"";
7706 info->name_space = start;
7708 info->name = last_point + 1;
7710 info->name_space = (char *)"";
7717 if (isbyref) /* only one level allowed by the spec */
7721 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7725 if (isbyref) /* pointer to ref not okay */
7727 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7732 if (isbyref) /* array of ref and generic ref are not okay */
7734 //Decide if it's an array of a generic argument list
7739 if (*p == ',' || *p == '*' || *p == ']') { //array
7747 else if (*p == '*') /* '*' means unknown lower bound */
7748 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7755 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7757 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7760 info->type_arguments = g_ptr_array_new ();
7762 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7763 gboolean fqname = FALSE;
7765 g_ptr_array_add (info->type_arguments, subinfo);
7767 while (*p == ' ') p++;
7773 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7776 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7777 if (fqname && (*p != ']')) {
7785 while (*p && (*p != ']'))
7793 if (g_ascii_isspace (*aname)) {
7800 !assembly_name_to_aname (&subinfo->assembly, aname))
7802 } else if (fqname && (*p == ']')) {
7824 if (g_ascii_isspace (*p)) {
7831 return 0; /* missing assembly name */
7832 if (!assembly_name_to_aname (&info->assembly, p))
7838 if (info->assembly.name)
7841 // *w = 0; /* terminate class name */
7843 if (!info->name || !*info->name)
7847 /* add other consistency checks */
7853 * mono_identifier_unescape_type_name_chars:
7854 * @identifier: the display name of a mono type
7857 * The name in internal form, that is without escaping backslashes.
7859 * The string is modified in place!
7862 mono_identifier_unescape_type_name_chars(char* identifier)
7867 for (w = r = identifier; *r != 0; r++)
7885 mono_identifier_unescape_info (MonoTypeNameParse* info);
7888 unescape_each_type_argument(void* data, void* user_data)
7890 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7891 mono_identifier_unescape_info (info);
7895 unescape_each_nested_name (void* data, void* user_data)
7897 char* nested_name = (char*) data;
7898 mono_identifier_unescape_type_name_chars(nested_name);
7902 * mono_identifier_unescape_info:
7904 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7908 * Destructively updates the info by unescaping the identifiers that
7909 * comprise the type namespace, name, nested types (if any) and
7910 * generic type arguments (if any).
7912 * The resulting info has the names in internal form.
7916 mono_identifier_unescape_info (MonoTypeNameParse *info)
7920 mono_identifier_unescape_type_name_chars(info->name_space);
7921 mono_identifier_unescape_type_name_chars(info->name);
7922 // but don't escape info->assembly
7923 if (info->type_arguments)
7924 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7926 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7930 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7932 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7934 mono_identifier_unescape_info (info);
7940 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7942 gboolean type_resolve = FALSE;
7944 MonoImage *rootimage = image;
7946 if (info->assembly.name) {
7947 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7948 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7950 * This could happen in the AOT compiler case when the search hook is not
7953 assembly = image->assembly;
7955 /* then we must load the assembly ourselve - see #60439 */
7956 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7960 image = assembly->image;
7961 } else if (!image) {
7962 image = mono_defaults.corlib;
7965 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7966 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7967 image = mono_defaults.corlib;
7968 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7975 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7981 gboolean bounded = FALSE;
7984 image = mono_defaults.corlib;
7987 rootimage = mono_defaults.corlib;
7991 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7992 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7994 klass = mono_class_from_name (image, info->name_space, info->name);
7998 for (mod = info->nested; mod; mod = mod->next) {
7999 gpointer iter = NULL;
8003 mono_class_init (parent);
8005 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8007 char *nested_name, *nested_nspace;
8008 gboolean match = TRUE;
8010 lastp = strrchr ((const char *)mod->data, '.');
8012 /* Nested classes can have namespaces */
8015 nested_name = g_strdup (lastp + 1);
8016 nspace_len = lastp - (char*)mod->data;
8017 nested_nspace = (char *)g_malloc (nspace_len + 1);
8018 memcpy (nested_nspace, mod->data, nspace_len);
8019 nested_nspace [nspace_len] = '\0';
8022 nested_name = (char *)mod->data;
8023 nested_nspace = NULL;
8026 if (nested_nspace) {
8028 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8031 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8037 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8040 if (strcmp (klass->name, nested_name) != 0)
8045 g_free (nested_name);
8046 g_free (nested_nspace);
8058 if (info->type_arguments) {
8059 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8060 MonoReflectionType *the_type;
8064 for (i = 0; i < info->type_arguments->len; i++) {
8065 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8067 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8068 if (!type_args [i]) {
8074 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8075 mono_error_raise_exception (&error); /* FIXME don't raise here */
8077 instance = mono_reflection_bind_generic_parameters (
8078 the_type, info->type_arguments->len, type_args);
8084 klass = mono_class_from_mono_type (instance);
8087 for (mod = info->modifiers; mod; mod = mod->next) {
8088 modval = GPOINTER_TO_UINT (mod->data);
8089 if (!modval) { /* byref: must be last modifier */
8090 return &klass->this_arg;
8091 } else if (modval == -1) {
8092 klass = mono_ptr_class_get (&klass->byval_arg);
8093 } else if (modval == -2) {
8095 } else { /* array rank */
8096 klass = mono_bounded_array_class_get (klass, modval, bounded);
8100 return &klass->byval_arg;
8104 * mono_reflection_get_type:
8105 * @image: a metadata context
8106 * @info: type description structure
8107 * @ignorecase: flag for case-insensitive string compares
8108 * @type_resolve: whenever type resolve was already tried
8110 * Build a MonoType from the type description in @info.
8115 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8116 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8120 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8122 MonoReflectionAssemblyBuilder *abuilder;
8126 g_assert (assembly_is_dynamic (assembly));
8127 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8129 /* Enumerate all modules */
8132 if (abuilder->modules) {
8133 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8134 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8135 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8141 if (!type && abuilder->loaded_modules) {
8142 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8143 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8144 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8154 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8157 MonoReflectionAssembly *assembly;
8161 if (image && image_is_dynamic (image))
8162 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8164 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8167 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8174 *type_resolve = TRUE;
8177 /* Reconstruct the type name */
8178 fullName = g_string_new ("");
8179 if (info->name_space && (info->name_space [0] != '\0'))
8180 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8182 g_string_printf (fullName, "%s", info->name);
8183 for (mod = info->nested; mod; mod = mod->next)
8184 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8186 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8188 if (assembly_is_dynamic (assembly->assembly))
8189 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8191 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8194 g_string_free (fullName, TRUE);
8199 mono_reflection_free_type_info (MonoTypeNameParse *info)
8201 g_list_free (info->modifiers);
8202 g_list_free (info->nested);
8204 if (info->type_arguments) {
8207 for (i = 0; i < info->type_arguments->len; i++) {
8208 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8210 mono_reflection_free_type_info (subinfo);
8211 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8215 g_ptr_array_free (info->type_arguments, TRUE);
8220 * mono_reflection_type_from_name:
8222 * @image: a metadata context (can be NULL).
8224 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8225 * it defaults to get the type from @image or, if @image is NULL or loading
8226 * from it fails, uses corlib.
8230 mono_reflection_type_from_name (char *name, MonoImage *image)
8232 MonoType *type = NULL;
8233 MonoTypeNameParse info;
8236 /* Make a copy since parse_type modifies its argument */
8237 tmp = g_strdup (name);
8239 /*g_print ("requested type %s\n", str);*/
8240 if (mono_reflection_parse_type (tmp, &info)) {
8241 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8245 mono_reflection_free_type_info (&info);
8250 * mono_reflection_get_token:
8252 * Return the metadata token of OBJ which should be an object
8253 * representing a metadata element.
8256 mono_reflection_get_token (MonoObject *obj)
8261 klass = obj->vtable->klass;
8263 if (strcmp (klass->name, "MethodBuilder") == 0) {
8264 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8266 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8267 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8268 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8270 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8271 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8272 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8274 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8275 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8276 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8277 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8278 } else if (strcmp (klass->name, "MonoType") == 0) {
8279 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8280 MonoClass *mc = mono_class_from_mono_type (type);
8281 if (!mono_class_init (mc))
8282 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8284 token = mc->type_token;
8285 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8286 strcmp (klass->name, "MonoMethod") == 0 ||
8287 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8288 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8289 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8290 if (m->method->is_inflated) {
8291 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8292 return inflated->declaring->token;
8294 token = m->method->token;
8296 } else if (strcmp (klass->name, "MonoField") == 0) {
8297 MonoReflectionField *f = (MonoReflectionField*)obj;
8299 if (is_field_on_inst (f->field)) {
8300 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8302 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8303 int field_index = f->field - dgclass->fields;
8306 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8307 obj = dgclass->field_objects [field_index];
8308 return mono_reflection_get_token (obj);
8311 token = mono_class_get_field_token (f->field);
8312 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8313 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8315 token = mono_class_get_property_token (p->property);
8316 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8317 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8319 token = mono_class_get_event_token (p->event);
8320 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8321 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8322 MonoClass *member_class = mono_object_class (p->MemberImpl);
8323 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8325 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8326 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8327 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8330 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8331 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8333 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8334 MonoException *ex = mono_get_exception_not_implemented (msg);
8336 mono_raise_exception (ex);
8343 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8347 int slen = mono_metadata_decode_value (p, &p);
8349 mono_error_init (error);
8351 n = (char *)g_memdup (p, slen + 1);
8353 t = mono_reflection_type_from_name (n, image);
8355 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8356 /* We don't free n, it's consumed by mono_error */
8357 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8363 return mono_class_from_mono_type (t);
8367 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8369 int slen, type = t->type;
8370 MonoClass *tklass = t->data.klass;
8372 mono_error_init (error);
8378 case MONO_TYPE_BOOLEAN: {
8379 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8384 case MONO_TYPE_CHAR:
8386 case MONO_TYPE_I2: {
8387 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8392 #if SIZEOF_VOID_P == 4
8398 case MONO_TYPE_I4: {
8399 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8404 #if SIZEOF_VOID_P == 8
8405 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8409 case MONO_TYPE_I8: {
8410 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8415 case MONO_TYPE_R8: {
8416 double *val = (double *)g_malloc (sizeof (double));
8421 case MONO_TYPE_VALUETYPE:
8422 if (t->data.klass->enumtype) {
8423 type = mono_class_enum_basetype (t->data.klass)->type;
8426 MonoClass *k = t->data.klass;
8428 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8429 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8435 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8438 case MONO_TYPE_STRING:
8439 if (*p == (char)0xFF) {
8443 slen = mono_metadata_decode_value (p, &p);
8445 return mono_string_new_len (mono_domain_get (), p, slen);
8446 case MONO_TYPE_CLASS: {
8447 MonoReflectionType *rt;
8450 if (*p == (char)0xFF) {
8455 slen = mono_metadata_decode_value (p, &p);
8456 n = (char *)g_memdup (p, slen + 1);
8458 t = mono_reflection_type_from_name (n, image);
8460 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8461 /* We don't free n, it's consumed by mono_error */
8462 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8468 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8469 if (!mono_error_ok (error))
8474 case MONO_TYPE_OBJECT: {
8477 MonoClass *subc = NULL;
8482 } else if (subt == 0x0E) {
8483 type = MONO_TYPE_STRING;
8485 } else if (subt == 0x1D) {
8486 MonoType simple_type = {{0}};
8490 type = MONO_TYPE_SZARRAY;
8491 if (etype == 0x50) {
8492 tklass = mono_defaults.systemtype_class;
8493 } else if (etype == 0x55) {
8494 tklass = load_cattr_enum_type (image, p, &p, error);
8495 if (!mono_error_ok (error))
8499 /* See Partition II, Appendix B3 */
8500 etype = MONO_TYPE_OBJECT;
8501 simple_type.type = (MonoTypeEnum)etype;
8502 tklass = mono_class_from_mono_type (&simple_type);
8505 } else if (subt == 0x55) {
8508 slen = mono_metadata_decode_value (p, &p);
8509 n = (char *)g_memdup (p, slen + 1);
8511 t = mono_reflection_type_from_name (n, image);
8513 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8514 /* We don't free n, it's consumed by mono_error */
8515 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8520 subc = mono_class_from_mono_type (t);
8521 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8522 MonoType simple_type = {{0}};
8523 simple_type.type = (MonoTypeEnum)subt;
8524 subc = mono_class_from_mono_type (&simple_type);
8526 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8528 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8530 if (mono_error_ok (error)) {
8531 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8532 g_assert (!subc->has_references);
8533 if (mono_error_ok (error))
8534 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8540 case MONO_TYPE_SZARRAY: {
8542 guint32 i, alen, basetype;
8545 if (alen == 0xffffffff) {
8549 arr = mono_array_new (mono_domain_get(), tklass, alen);
8550 basetype = tklass->byval_arg.type;
8551 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8552 basetype = mono_class_enum_basetype (tklass)->type;
8557 case MONO_TYPE_BOOLEAN:
8558 for (i = 0; i < alen; i++) {
8559 MonoBoolean val = *p++;
8560 mono_array_set (arr, MonoBoolean, i, val);
8563 case MONO_TYPE_CHAR:
8566 for (i = 0; i < alen; i++) {
8567 guint16 val = read16 (p);
8568 mono_array_set (arr, guint16, i, val);
8575 for (i = 0; i < alen; i++) {
8576 guint32 val = read32 (p);
8577 mono_array_set (arr, guint32, i, val);
8582 for (i = 0; i < alen; i++) {
8585 mono_array_set (arr, double, i, val);
8591 for (i = 0; i < alen; i++) {
8592 guint64 val = read64 (p);
8593 mono_array_set (arr, guint64, i, val);
8597 case MONO_TYPE_CLASS:
8598 case MONO_TYPE_OBJECT:
8599 case MONO_TYPE_STRING:
8600 case MONO_TYPE_SZARRAY:
8601 for (i = 0; i < alen; i++) {
8602 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8603 if (!mono_error_ok (error))
8605 mono_array_setref (arr, i, item);
8609 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8615 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8621 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8623 static MonoClass *klass;
8624 static MonoMethod *ctor;
8627 void *params [2], *unboxed;
8630 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8632 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8634 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8635 mono_error_raise_exception (&error); /* FIXME don't raise here */
8638 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8639 mono_error_raise_exception (&error); /* FIXME don't raise here */
8640 unboxed = mono_object_unbox (retval);
8641 mono_runtime_invoke (ctor, unboxed, params, NULL);
8647 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8649 static MonoClass *klass;
8650 static MonoMethod *ctor;
8653 void *unboxed, *params [2];
8656 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8658 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8661 params [1] = typedarg;
8662 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8663 mono_error_raise_exception (&error); /* FIXME don't raise here */
8664 unboxed = mono_object_unbox (retval);
8665 mono_runtime_invoke (ctor, unboxed, params, NULL);
8671 type_is_reference (MonoType *type)
8673 switch (type->type) {
8674 case MONO_TYPE_BOOLEAN:
8675 case MONO_TYPE_CHAR:
8688 case MONO_TYPE_VALUETYPE:
8696 free_param_data (MonoMethodSignature *sig, void **params) {
8698 for (i = 0; i < sig->param_count; ++i) {
8699 if (!type_is_reference (sig->params [i]))
8700 g_free (params [i]);
8705 * Find the field index in the metadata FieldDef table.
8708 find_field_index (MonoClass *klass, MonoClassField *field) {
8711 for (i = 0; i < klass->field.count; ++i) {
8712 if (field == &klass->fields [i])
8713 return klass->field.first + 1 + i;
8719 * Find the property index in the metadata Property table.
8722 find_property_index (MonoClass *klass, MonoProperty *property) {
8725 for (i = 0; i < klass->ext->property.count; ++i) {
8726 if (property == &klass->ext->properties [i])
8727 return klass->ext->property.first + 1 + i;
8733 * Find the event index in the metadata Event table.
8736 find_event_index (MonoClass *klass, MonoEvent *event) {
8739 for (i = 0; i < klass->ext->event.count; ++i) {
8740 if (event == &klass->ext->events [i])
8741 return klass->ext->event.first + 1 + i;
8747 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8749 const char *p = (const char*)data;
8751 guint32 i, j, num_named;
8753 void *params_buf [32];
8754 void **params = NULL;
8755 MonoMethodSignature *sig;
8756 MonoObject *exc = NULL;
8758 mono_error_init (error);
8760 mono_class_init (method->klass);
8762 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8763 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8768 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8769 if (!mono_error_ok (error)) return NULL;
8770 mono_runtime_invoke (method, attr, NULL, NULL);
8774 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8777 /*g_print ("got attr %s\n", method->klass->name);*/
8779 sig = mono_method_signature (method);
8780 if (sig->param_count < 32) {
8781 params = params_buf;
8782 memset (params, 0, sizeof (void*) * sig->param_count);
8784 /* Allocate using GC so it gets GC tracking */
8785 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8790 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8791 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8792 if (!mono_error_ok (error))
8797 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8798 if (!mono_error_ok (error)) goto fail;
8800 mono_runtime_invoke (method, attr, params, &exc);
8803 num_named = read16 (named);
8805 for (j = 0; j < num_named; j++) {
8807 char *name, named_type, data_type;
8808 named_type = *named++;
8809 data_type = *named++; /* type of data */
8810 if (data_type == MONO_TYPE_SZARRAY)
8811 data_type = *named++;
8812 if (data_type == MONO_TYPE_ENUM) {
8815 type_len = mono_metadata_decode_blob_size (named, &named);
8816 type_name = (char *)g_malloc (type_len + 1);
8817 memcpy (type_name, named, type_len);
8818 type_name [type_len] = 0;
8820 /* FIXME: lookup the type and check type consistency */
8823 name_len = mono_metadata_decode_blob_size (named, &named);
8824 name = (char *)g_malloc (name_len + 1);
8825 memcpy (name, named, name_len);
8826 name [name_len] = 0;
8828 if (named_type == 0x53) {
8829 MonoClassField *field;
8832 /* how this fail is a blackbox */
8833 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8835 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8840 val = load_cattr_value (image, field->type, named, &named, error);
8841 if (!mono_error_ok (error)) {
8843 if (!type_is_reference (field->type))
8848 mono_field_set_value (attr, field, val);
8849 if (!type_is_reference (field->type))
8851 } else if (named_type == 0x54) {
8854 MonoType *prop_type;
8856 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8859 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8865 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8870 /* can we have more that 1 arg in a custom attr named property? */
8871 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8872 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8874 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8875 if (!mono_error_ok (error)) {
8877 if (!type_is_reference (prop_type))
8878 g_free (pparams [0]);
8883 mono_property_set_value (prop, attr, pparams, NULL);
8884 if (!type_is_reference (prop_type))
8885 g_free (pparams [0]);
8890 free_param_data (method->signature, params);
8891 if (params != params_buf)
8892 mono_gc_free_fixed (params);
8897 free_param_data (method->signature, params);
8898 if (params != params_buf)
8899 mono_gc_free_fixed (params);
8901 mono_raise_exception ((MonoException*)exc);
8906 * mono_reflection_create_custom_attr_data_args:
8908 * Create an array of typed and named arguments from the cattr blob given by DATA.
8909 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8910 * NAMED_ARG_INFO will contain information about the named arguments.
8913 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)
8915 MonoArray *typedargs, *namedargs;
8916 MonoClass *attrklass;
8918 const char *p = (const char*)data;
8920 guint32 i, j, num_named;
8921 CattrNamedArg *arginfo = NULL;
8925 *named_arg_info = NULL;
8927 mono_error_init (error);
8929 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8930 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8934 mono_class_init (method->klass);
8936 domain = mono_domain_get ();
8938 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8941 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8945 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8949 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8950 if (!mono_error_ok (error)) {
8951 if (!type_is_reference (mono_method_signature (method)->params [i]))
8956 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8957 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8958 mono_array_setref (typedargs, i, obj);
8960 if (!type_is_reference (mono_method_signature (method)->params [i]))
8965 num_named = read16 (named);
8966 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8968 attrklass = method->klass;
8970 arginfo = g_new0 (CattrNamedArg, num_named);
8971 *named_arg_info = arginfo;
8973 for (j = 0; j < num_named; j++) {
8975 char *name, named_type, data_type;
8976 named_type = *named++;
8977 data_type = *named++; /* type of data */
8978 if (data_type == MONO_TYPE_SZARRAY)
8979 data_type = *named++;
8980 if (data_type == MONO_TYPE_ENUM) {
8983 type_len = mono_metadata_decode_blob_size (named, &named);
8984 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8987 type_name = (char *)g_malloc (type_len + 1);
8988 memcpy (type_name, named, type_len);
8989 type_name [type_len] = 0;
8991 /* FIXME: lookup the type and check type consistency */
8994 name_len = mono_metadata_decode_blob_size (named, &named);
8995 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8997 name = (char *)g_malloc (name_len + 1);
8998 memcpy (name, named, name_len);
8999 name [name_len] = 0;
9001 if (named_type == 0x53) {
9003 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9011 arginfo [j].type = field->type;
9012 arginfo [j].field = field;
9014 val = load_cattr_value (image, field->type, named, &named, error);
9015 if (!mono_error_ok (error)) {
9016 if (!type_is_reference (field->type))
9022 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9023 mono_array_setref (namedargs, j, obj);
9024 if (!type_is_reference (field->type))
9026 } else if (named_type == 0x54) {
9028 MonoType *prop_type;
9029 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9032 if (!prop || !prop->set) {
9037 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9038 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9040 arginfo [j].type = prop_type;
9041 arginfo [j].prop = prop;
9043 val = load_cattr_value (image, prop_type, named, &named, error);
9044 if (!mono_error_ok (error)) {
9045 if (!type_is_reference (prop_type))
9051 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9052 mono_array_setref (namedargs, j, obj);
9053 if (!type_is_reference (prop_type))
9059 *typed_args = typedargs;
9060 *named_args = namedargs;
9063 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9065 *named_arg_info = NULL;
9069 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9072 MonoArray *typedargs, *namedargs;
9075 CattrNamedArg *arginfo = NULL;
9079 mono_error_init (&error);
9087 image = assembly->assembly->image;
9088 method = ref_method->method;
9089 domain = mono_object_domain (ref_method);
9091 if (!mono_class_init (method->klass))
9092 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9094 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9095 if (!mono_error_ok (&error))
9098 if (mono_loader_get_last_error ()) {
9099 mono_error_set_from_loader_error (&error);
9103 if (!typedargs || !namedargs)
9106 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9107 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9108 MonoObject *typedarg;
9110 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9111 mono_array_setref (typedargs, i, typedarg);
9114 for (i = 0; i < mono_array_length (namedargs); ++i) {
9115 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9116 MonoObject *typedarg, *namedarg, *minfo;
9118 if (arginfo [i].prop)
9119 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9121 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9122 if (!mono_error_ok (&error))
9126 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9127 namedarg = create_cattr_named_arg (minfo, typedarg);
9129 mono_array_setref (namedargs, i, namedarg);
9132 *ctor_args = typedargs;
9133 *named_args = namedargs;
9136 mono_error_raise_exception (&error);
9141 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9143 static MonoMethod *ctor;
9150 g_assert (image->assembly);
9153 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9155 domain = mono_domain_get ();
9156 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9157 mono_error_raise_exception (&error); /* FIXME don't raise here */
9158 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9159 mono_error_raise_exception (&error); /* FIXME don't raise here */
9160 params [1] = mono_assembly_get_object (domain, image->assembly);
9161 params [2] = (gpointer)&cattr->data;
9162 params [3] = &cattr->data_size;
9163 mono_runtime_invoke (ctor, attr, params, NULL);
9168 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9174 mono_error_init (error);
9177 for (i = 0; i < cinfo->num_attrs; ++i) {
9178 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9182 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9184 for (i = 0; i < cinfo->num_attrs; ++i) {
9185 if (!cinfo->attrs [i].ctor)
9186 /* The cattr type is not finished yet */
9187 /* We should include the type name but cinfo doesn't contain it */
9188 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9189 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9190 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9191 if (!mono_error_ok (error))
9193 mono_array_setref (result, n, attr);
9201 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9204 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9205 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9211 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9217 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9218 for (i = 0; i < cinfo->num_attrs; ++i) {
9219 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9220 mono_array_setref (result, i, attr);
9226 * mono_custom_attrs_from_index:
9228 * Returns: NULL if no attributes are found or if a loading error occurs.
9231 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9233 guint32 mtoken, i, len;
9234 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9236 MonoCustomAttrInfo *ainfo;
9237 GList *tmp, *list = NULL;
9239 MonoCustomAttrEntry* attr;
9241 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9243 i = mono_metadata_custom_attrs_from_index (image, idx);
9247 while (i < ca->rows) {
9248 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9250 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9253 len = g_list_length (list);
9256 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9257 ainfo->num_attrs = len;
9258 ainfo->image = image;
9259 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9261 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9262 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9263 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9264 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9265 mtoken |= MONO_TOKEN_METHOD_DEF;
9267 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9268 mtoken |= MONO_TOKEN_MEMBER_REF;
9271 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9274 attr = &ainfo->attrs [i - 1];
9275 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9277 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9278 mono_loader_set_error_from_mono_error (&error);
9284 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9285 /*FIXME raising an exception here doesn't make any sense*/
9286 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9291 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9292 attr->data_size = mono_metadata_decode_value (data, &data);
9293 attr->data = (guchar*)data;
9301 mono_custom_attrs_from_method (MonoMethod *method)
9306 * An instantiated method has the same cattrs as the generic method definition.
9308 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9309 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9311 if (method->is_inflated)
9312 method = ((MonoMethodInflated *) method)->declaring;
9314 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9315 return lookup_custom_attr (method->klass->image, method);
9318 /* Synthetic methods */
9321 idx = mono_method_get_index (method);
9322 idx <<= MONO_CUSTOM_ATTR_BITS;
9323 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9324 return mono_custom_attrs_from_index (method->klass->image, idx);
9328 mono_custom_attrs_from_class (MonoClass *klass)
9332 if (klass->generic_class)
9333 klass = klass->generic_class->container_class;
9335 if (image_is_dynamic (klass->image))
9336 return lookup_custom_attr (klass->image, klass);
9338 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9339 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9340 idx <<= MONO_CUSTOM_ATTR_BITS;
9341 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9343 idx = mono_metadata_token_index (klass->type_token);
9344 idx <<= MONO_CUSTOM_ATTR_BITS;
9345 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9347 return mono_custom_attrs_from_index (klass->image, idx);
9351 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9355 if (image_is_dynamic (assembly->image))
9356 return lookup_custom_attr (assembly->image, assembly);
9357 idx = 1; /* there is only one assembly */
9358 idx <<= MONO_CUSTOM_ATTR_BITS;
9359 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9360 return mono_custom_attrs_from_index (assembly->image, idx);
9363 static MonoCustomAttrInfo*
9364 mono_custom_attrs_from_module (MonoImage *image)
9368 if (image_is_dynamic (image))
9369 return lookup_custom_attr (image, image);
9370 idx = 1; /* there is only one module */
9371 idx <<= MONO_CUSTOM_ATTR_BITS;
9372 idx |= MONO_CUSTOM_ATTR_MODULE;
9373 return mono_custom_attrs_from_index (image, idx);
9377 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9381 if (image_is_dynamic (klass->image)) {
9382 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9383 return lookup_custom_attr (klass->image, property);
9385 idx = find_property_index (klass, property);
9386 idx <<= MONO_CUSTOM_ATTR_BITS;
9387 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9388 return mono_custom_attrs_from_index (klass->image, idx);
9392 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9396 if (image_is_dynamic (klass->image)) {
9397 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9398 return lookup_custom_attr (klass->image, event);
9400 idx = find_event_index (klass, event);
9401 idx <<= MONO_CUSTOM_ATTR_BITS;
9402 idx |= MONO_CUSTOM_ATTR_EVENT;
9403 return mono_custom_attrs_from_index (klass->image, idx);
9407 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9410 if (image_is_dynamic (klass->image)) {
9411 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9412 return lookup_custom_attr (klass->image, field);
9414 idx = find_field_index (klass, field);
9415 idx <<= MONO_CUSTOM_ATTR_BITS;
9416 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9417 return mono_custom_attrs_from_index (klass->image, idx);
9421 * mono_custom_attrs_from_param:
9422 * @method: handle to the method that we want to retrieve custom parameter information from
9423 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9425 * The result must be released with mono_custom_attrs_free().
9427 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9430 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9433 guint32 i, idx, method_index;
9434 guint32 param_list, param_last, param_pos, found;
9436 MonoReflectionMethodAux *aux;
9439 * An instantiated method has the same cattrs as the generic method definition.
9441 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9442 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9444 if (method->is_inflated)
9445 method = ((MonoMethodInflated *) method)->declaring;
9447 if (image_is_dynamic (method->klass->image)) {
9448 MonoCustomAttrInfo *res, *ainfo;
9451 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9452 if (!aux || !aux->param_cattr)
9455 /* Need to copy since it will be freed later */
9456 ainfo = aux->param_cattr [param];
9459 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9460 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9461 memcpy (res, ainfo, size);
9465 image = method->klass->image;
9466 method_index = mono_method_get_index (method);
9469 ca = &image->tables [MONO_TABLE_METHOD];
9471 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9472 if (method_index == ca->rows) {
9473 ca = &image->tables [MONO_TABLE_PARAM];
9474 param_last = ca->rows + 1;
9476 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9477 ca = &image->tables [MONO_TABLE_PARAM];
9480 for (i = param_list; i < param_last; ++i) {
9481 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9482 if (param_pos == param) {
9490 idx <<= MONO_CUSTOM_ATTR_BITS;
9491 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9492 return mono_custom_attrs_from_index (image, idx);
9496 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9500 for (i = 0; i < ainfo->num_attrs; ++i) {
9501 klass = ainfo->attrs [i].ctor->klass;
9502 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9509 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9512 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9513 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9518 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9524 mono_error_init (error);
9527 for (i = 0; i < ainfo->num_attrs; ++i) {
9528 klass = ainfo->attrs [i].ctor->klass;
9529 if (mono_class_has_parent (klass, attr_klass)) {
9534 if (attr_index == -1)
9537 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9538 if (!mono_error_ok (error))
9540 return mono_array_get (attrs, MonoObject*, attr_index);
9544 * mono_reflection_get_custom_attrs_info:
9545 * @obj: a reflection object handle
9547 * Return the custom attribute info for attributes defined for the
9548 * reflection handle @obj. The objects.
9550 * FIXME this function leaks like a sieve for SRE objects.
9553 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9556 MonoCustomAttrInfo *cinfo = NULL;
9558 klass = obj->vtable->klass;
9559 if (klass == mono_defaults.monotype_class) {
9560 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9561 klass = mono_class_from_mono_type (type);
9562 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9563 cinfo = mono_custom_attrs_from_class (klass);
9564 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9565 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9566 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9567 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9568 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9569 cinfo = mono_custom_attrs_from_module (module->image);
9570 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9571 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9572 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9573 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9574 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9575 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9576 } else if (strcmp ("MonoField", klass->name) == 0) {
9577 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9578 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9579 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9580 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9581 cinfo = mono_custom_attrs_from_method (rmethod->method);
9582 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9583 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9584 cinfo = mono_custom_attrs_from_method (rmethod->method);
9585 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9586 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9587 MonoClass *member_class = mono_object_class (param->MemberImpl);
9588 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9589 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9590 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9591 } else if (is_sr_mono_property (member_class)) {
9592 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9594 if (!(method = prop->property->get))
9595 method = prop->property->set;
9598 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9600 #ifndef DISABLE_REFLECTION_EMIT
9601 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9602 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9603 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9604 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9605 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9606 MonoMethod *method = NULL;
9607 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9608 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9609 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9610 method = ((MonoReflectionMethod *)c->cb)->method;
9612 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));
9614 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9618 char *type_name = mono_type_get_full_name (member_class);
9619 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9620 MonoException *ex = mono_get_exception_not_supported (msg);
9623 mono_raise_exception (ex);
9625 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9626 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9627 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9628 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9629 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9630 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9631 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9632 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9633 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9634 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9635 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9636 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9637 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9638 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9639 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9640 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9641 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9642 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9643 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9644 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9645 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9646 } else { /* handle other types here... */
9647 g_error ("get custom attrs not yet supported for %s", klass->name);
9654 * mono_reflection_get_custom_attrs_by_type:
9655 * @obj: a reflection object handle
9657 * Return an array with all the custom attributes defined of the
9658 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9659 * of that type are returned. The objects are fully build. Return NULL if a loading error
9663 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9666 MonoCustomAttrInfo *cinfo;
9668 mono_error_init (error);
9670 cinfo = mono_reflection_get_custom_attrs_info (obj);
9672 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9674 mono_custom_attrs_free (cinfo);
9676 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9677 if (mono_loader_get_last_error ())
9679 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9686 * mono_reflection_get_custom_attrs:
9687 * @obj: a reflection object handle
9689 * Return an array with all the custom attributes defined of the
9690 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9694 mono_reflection_get_custom_attrs (MonoObject *obj)
9698 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9702 * mono_reflection_get_custom_attrs_data:
9703 * @obj: a reflection obj handle
9705 * Returns an array of System.Reflection.CustomAttributeData,
9706 * which include information about attributes reflected on
9707 * types loaded using the Reflection Only methods
9710 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9713 MonoCustomAttrInfo *cinfo;
9715 cinfo = mono_reflection_get_custom_attrs_info (obj);
9717 result = mono_custom_attrs_data_construct (cinfo);
9719 mono_custom_attrs_free (cinfo);
9721 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9726 static MonoReflectionType*
9727 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9729 static MonoMethod *method_get_underlying_system_type = NULL;
9730 MonoMethod *usertype_method;
9732 if (!method_get_underlying_system_type)
9733 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9734 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9735 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9740 is_corlib_type (MonoClass *klass)
9742 return klass->image == mono_defaults.corlib;
9745 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9746 static MonoClass *cached_class; \
9748 return cached_class == _class; \
9749 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9750 cached_class = _class; \
9757 #ifndef DISABLE_REFLECTION_EMIT
9759 is_sre_array (MonoClass *klass)
9761 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9765 is_sre_byref (MonoClass *klass)
9767 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9771 is_sre_pointer (MonoClass *klass)
9773 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9777 is_sre_generic_instance (MonoClass *klass)
9779 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9783 is_sre_type_builder (MonoClass *klass)
9785 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9789 is_sre_method_builder (MonoClass *klass)
9791 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9795 is_sre_ctor_builder (MonoClass *klass)
9797 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9801 is_sre_field_builder (MonoClass *klass)
9803 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9807 is_sre_method_on_tb_inst (MonoClass *klass)
9809 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9813 is_sre_ctor_on_tb_inst (MonoClass *klass)
9815 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9819 mono_reflection_type_get_handle (MonoReflectionType* ref)
9827 if (is_usertype (ref)) {
9828 ref = mono_reflection_type_get_underlying_system_type (ref);
9829 if (ref == NULL || is_usertype (ref))
9835 klass = mono_object_class (ref);
9837 if (is_sre_array (klass)) {
9839 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9840 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9842 if (sre_array->rank == 0) //single dimentional array
9843 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9845 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9846 sre_array->type.type = res;
9848 } else if (is_sre_byref (klass)) {
9850 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9851 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9853 res = &mono_class_from_mono_type (base)->this_arg;
9854 sre_byref->type.type = res;
9856 } else if (is_sre_pointer (klass)) {
9858 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9859 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9861 res = &mono_ptr_class_get (base)->byval_arg;
9862 sre_pointer->type.type = res;
9864 } else if (is_sre_generic_instance (klass)) {
9865 MonoType *res, **types;
9866 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9869 count = mono_array_length (gclass->type_arguments);
9870 types = g_new0 (MonoType*, count);
9871 for (i = 0; i < count; ++i) {
9872 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9873 types [i] = mono_reflection_type_get_handle (t);
9880 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9883 gclass->type.type = res;
9887 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9894 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9896 mono_reflection_type_get_handle (type);
9900 mono_reflection_register_with_runtime (MonoReflectionType *type)
9902 MonoType *res = mono_reflection_type_get_handle (type);
9903 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9907 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9909 klass = mono_class_from_mono_type (res);
9911 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9912 mono_domain_lock (domain);
9914 if (!image_is_dynamic (klass->image)) {
9915 mono_class_setup_supertypes (klass);
9917 if (!domain->type_hash)
9918 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9919 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9920 mono_g_hash_table_insert (domain->type_hash, res, type);
9922 mono_domain_unlock (domain);
9923 mono_loader_unlock ();
9927 * LOCKING: Assumes the loader lock is held.
9929 static MonoMethodSignature*
9930 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9931 MonoMethodSignature *sig;
9934 count = parameters? mono_array_length (parameters): 0;
9936 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9937 sig->param_count = count;
9938 sig->sentinelpos = -1; /* FIXME */
9939 for (i = 0; i < count; ++i)
9940 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9945 * LOCKING: Assumes the loader lock is held.
9947 static MonoMethodSignature*
9948 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9949 MonoMethodSignature *sig;
9951 sig = parameters_to_signature (image, ctor->parameters);
9952 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9953 sig->ret = &mono_defaults.void_class->byval_arg;
9958 * LOCKING: Assumes the loader lock is held.
9960 static MonoMethodSignature*
9961 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9962 MonoMethodSignature *sig;
9964 sig = parameters_to_signature (image, method->parameters);
9965 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9966 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9967 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9971 static MonoMethodSignature*
9972 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9973 MonoMethodSignature *sig;
9975 sig = parameters_to_signature (NULL, method->parameters);
9976 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9977 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9978 sig->generic_param_count = 0;
9983 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9985 MonoClass *klass = mono_object_class (prop);
9986 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9987 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9988 *name = mono_string_to_utf8 (pb->name);
9989 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9991 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9992 *name = g_strdup (p->property->name);
9993 if (p->property->get)
9994 *type = mono_method_signature (p->property->get)->ret;
9996 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10001 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10003 MonoClass *klass = mono_object_class (field);
10004 if (strcmp (klass->name, "FieldBuilder") == 0) {
10005 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10006 *name = mono_string_to_utf8 (fb->name);
10007 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10009 MonoReflectionField *f = (MonoReflectionField *)field;
10010 *name = g_strdup (mono_field_get_name (f->field));
10011 *type = f->field->type;
10015 #else /* DISABLE_REFLECTION_EMIT */
10018 mono_reflection_register_with_runtime (MonoReflectionType *type)
10020 /* This is empty */
10024 is_sre_type_builder (MonoClass *klass)
10030 is_sre_generic_instance (MonoClass *klass)
10036 init_type_builder_generics (MonoObject *type)
10040 #endif /* !DISABLE_REFLECTION_EMIT */
10044 is_sr_mono_field (MonoClass *klass)
10046 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10050 is_sr_mono_property (MonoClass *klass)
10052 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10056 is_sr_mono_method (MonoClass *klass)
10058 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10062 is_sr_mono_cmethod (MonoClass *klass)
10064 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10068 is_sr_mono_generic_method (MonoClass *klass)
10070 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10074 is_sr_mono_generic_cmethod (MonoClass *klass)
10076 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10080 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10082 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10086 is_usertype (MonoReflectionType *ref)
10088 MonoClass *klass = mono_object_class (ref);
10089 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10092 static MonoReflectionType*
10093 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10095 mono_error_init (error);
10096 if (!type || type->type)
10099 if (is_usertype (type)) {
10100 type = mono_reflection_type_get_underlying_system_type (type);
10101 if (is_usertype (type)) {
10102 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10110 * Encode a value in a custom attribute stream of bytes.
10111 * The value to encode is either supplied as an object in argument val
10112 * (valuetypes are boxed), or as a pointer to the data in the
10114 * @type represents the type of the value
10115 * @buffer is the start of the buffer
10116 * @p the current position in the buffer
10117 * @buflen contains the size of the buffer and is used to return the new buffer size
10118 * if this needs to be realloced.
10119 * @retbuffer and @retp return the start and the position of the buffer
10122 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10124 MonoTypeEnum simple_type;
10126 if ((p-buffer) + 10 >= *buflen) {
10129 newbuf = (char *)g_realloc (buffer, *buflen);
10130 p = newbuf + (p-buffer);
10134 argval = ((char*)arg + sizeof (MonoObject));
10135 simple_type = type->type;
10137 switch (simple_type) {
10138 case MONO_TYPE_BOOLEAN:
10143 case MONO_TYPE_CHAR:
10146 swap_with_size (p, argval, 2, 1);
10152 swap_with_size (p, argval, 4, 1);
10156 swap_with_size (p, argval, 8, 1);
10161 swap_with_size (p, argval, 8, 1);
10164 case MONO_TYPE_VALUETYPE:
10165 if (type->data.klass->enumtype) {
10166 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10169 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10172 case MONO_TYPE_STRING: {
10179 str = mono_string_to_utf8 ((MonoString*)arg);
10180 slen = strlen (str);
10181 if ((p-buffer) + 10 + slen >= *buflen) {
10185 newbuf = (char *)g_realloc (buffer, *buflen);
10186 p = newbuf + (p-buffer);
10189 mono_metadata_encode_value (slen, p, &p);
10190 memcpy (p, str, slen);
10195 case MONO_TYPE_CLASS: {
10203 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10204 slen = strlen (str);
10205 if ((p-buffer) + 10 + slen >= *buflen) {
10209 newbuf = (char *)g_realloc (buffer, *buflen);
10210 p = newbuf + (p-buffer);
10213 mono_metadata_encode_value (slen, p, &p);
10214 memcpy (p, str, slen);
10219 case MONO_TYPE_SZARRAY: {
10221 MonoClass *eclass, *arg_eclass;
10224 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10227 len = mono_array_length ((MonoArray*)arg);
10229 *p++ = (len >> 8) & 0xff;
10230 *p++ = (len >> 16) & 0xff;
10231 *p++ = (len >> 24) & 0xff;
10233 *retbuffer = buffer;
10234 eclass = type->data.klass;
10235 arg_eclass = mono_object_class (arg)->element_class;
10238 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10239 eclass = mono_defaults.object_class;
10241 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10242 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10243 int elsize = mono_class_array_element_size (arg_eclass);
10244 for (i = 0; i < len; ++i) {
10245 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10248 } else if (eclass->valuetype && arg_eclass->valuetype) {
10249 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10250 int elsize = mono_class_array_element_size (eclass);
10251 for (i = 0; i < len; ++i) {
10252 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10256 for (i = 0; i < len; ++i) {
10257 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10262 case MONO_TYPE_OBJECT: {
10268 * The parameter type is 'object' but the type of the actual
10269 * argument is not. So we have to add type information to the blob
10270 * too. This is completely undocumented in the spec.
10274 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10279 klass = mono_object_class (arg);
10281 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10284 } else if (klass->enumtype) {
10286 } else if (klass == mono_defaults.string_class) {
10287 simple_type = MONO_TYPE_STRING;
10290 } else if (klass->rank == 1) {
10292 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10293 /* See Partition II, Appendix B3 */
10296 *p++ = klass->element_class->byval_arg.type;
10297 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10299 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10300 *p++ = simple_type = klass->byval_arg.type;
10303 g_error ("unhandled type in custom attr");
10305 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10306 slen = strlen (str);
10307 if ((p-buffer) + 10 + slen >= *buflen) {
10311 newbuf = (char *)g_realloc (buffer, *buflen);
10312 p = newbuf + (p-buffer);
10315 mono_metadata_encode_value (slen, p, &p);
10316 memcpy (p, str, slen);
10319 simple_type = mono_class_enum_basetype (klass)->type;
10323 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10326 *retbuffer = buffer;
10330 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10332 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10333 char *str = type_get_qualified_name (type, NULL);
10334 int slen = strlen (str);
10338 * This seems to be optional...
10341 mono_metadata_encode_value (slen, p, &p);
10342 memcpy (p, str, slen);
10345 } else if (type->type == MONO_TYPE_OBJECT) {
10347 } else if (type->type == MONO_TYPE_CLASS) {
10348 /* it should be a type: encode_cattr_value () has the check */
10351 mono_metadata_encode_value (type->type, p, &p);
10352 if (type->type == MONO_TYPE_SZARRAY)
10353 /* See the examples in Partition VI, Annex B */
10354 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10360 #ifndef DISABLE_REFLECTION_EMIT
10362 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10365 /* Preallocate a large enough buffer */
10366 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10367 char *str = type_get_qualified_name (type, NULL);
10368 len = strlen (str);
10370 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10371 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10372 len = strlen (str);
10377 len += strlen (name);
10379 if ((p-buffer) + 20 + len >= *buflen) {
10383 newbuf = (char *)g_realloc (buffer, *buflen);
10384 p = newbuf + (p-buffer);
10388 encode_field_or_prop_type (type, p, &p);
10390 len = strlen (name);
10391 mono_metadata_encode_value (len, p, &p);
10392 memcpy (p, name, len);
10394 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10396 *retbuffer = buffer;
10400 * mono_reflection_get_custom_attrs_blob:
10401 * @ctor: custom attribute constructor
10402 * @ctorArgs: arguments o the constructor
10408 * Creates the blob of data that needs to be saved in the metadata and that represents
10409 * the custom attributed described by @ctor, @ctorArgs etc.
10410 * Returns: a Byte array representing the blob of data.
10413 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10416 MonoMethodSignature *sig;
10421 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10422 /* sig is freed later so allocate it in the heap */
10423 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10425 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10428 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10430 p = buffer = (char *)g_malloc (buflen);
10431 /* write the prolog */
10434 for (i = 0; i < sig->param_count; ++i) {
10435 arg = mono_array_get (ctorArgs, MonoObject*, i);
10436 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10440 i += mono_array_length (properties);
10442 i += mono_array_length (fields);
10444 *p++ = (i >> 8) & 0xff;
10447 for (i = 0; i < mono_array_length (properties); ++i) {
10451 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10452 get_prop_name_and_type (prop, &pname, &ptype);
10453 *p++ = 0x54; /* PROPERTY signature */
10454 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10461 for (i = 0; i < mono_array_length (fields); ++i) {
10465 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10466 get_field_name_and_type (field, &fname, &ftype);
10467 *p++ = 0x53; /* FIELD signature */
10468 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10473 g_assert (p - buffer <= buflen);
10474 buflen = p - buffer;
10475 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10476 p = mono_array_addr (result, char, 0);
10477 memcpy (p, buffer, buflen);
10479 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10485 * mono_reflection_setup_internal_class:
10486 * @tb: a TypeBuilder object
10488 * Creates a MonoClass that represents the TypeBuilder.
10489 * This is a trick that lets us simplify a lot of reflection code
10490 * (and will allow us to support Build and Run assemblies easier).
10493 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10496 MonoClass *klass, *parent;
10498 RESOLVE_TYPE (tb->parent, &error);
10499 mono_error_raise_exception (&error); /* FIXME don't raise here */
10501 mono_loader_lock ();
10504 /* check so we can compile corlib correctly */
10505 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10506 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10507 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10509 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10515 /* the type has already being created: it means we just have to change the parent */
10516 if (tb->type.type) {
10517 klass = mono_class_from_mono_type (tb->type.type);
10518 klass->parent = NULL;
10519 /* fool mono_class_setup_parent */
10520 klass->supertypes = NULL;
10521 mono_class_setup_parent (klass, parent);
10522 mono_class_setup_mono_type (klass);
10523 mono_loader_unlock ();
10527 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10529 klass->image = &tb->module->dynamic_image->image;
10531 klass->inited = 1; /* we lie to the runtime */
10532 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10533 if (!mono_error_ok (&error))
10535 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10536 if (!mono_error_ok (&error))
10538 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10539 klass->flags = tb->attrs;
10541 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10543 klass->element_class = klass;
10545 if (mono_class_get_ref_info (klass) == NULL) {
10547 mono_class_set_ref_info (klass, tb);
10549 /* Put into cache so mono_class_get_checked () will find it.
10550 Skip nested types as those should not be available on the global scope. */
10551 if (!tb->nesting_type)
10552 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10555 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10556 by performing a mono_class_get which does the full resolution.
10558 Working around this semantics would require us to write a lot of code for no clear advantage.
10560 mono_image_append_class_to_reflection_info_set (klass);
10562 g_assert (mono_class_get_ref_info (klass) == tb);
10565 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10567 if (parent != NULL) {
10568 mono_class_setup_parent (klass, parent);
10569 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10570 const char *old_n = klass->name;
10571 /* trick to get relative numbering right when compiling corlib */
10572 klass->name = "BuildingObject";
10573 mono_class_setup_parent (klass, mono_defaults.object_class);
10574 klass->name = old_n;
10577 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10578 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10579 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10580 klass->instance_size = sizeof (MonoObject);
10581 klass->size_inited = 1;
10582 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10585 mono_class_setup_mono_type (klass);
10587 mono_class_setup_supertypes (klass);
10590 * FIXME: handle interfaces.
10593 tb->type.type = &klass->byval_arg;
10595 if (tb->nesting_type) {
10596 g_assert (tb->nesting_type->type);
10597 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10600 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10602 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10604 mono_loader_unlock ();
10608 mono_loader_unlock ();
10609 mono_error_raise_exception (&error);
10613 * mono_reflection_setup_generic_class:
10614 * @tb: a TypeBuilder object
10616 * Setup the generic class before adding the first generic parameter.
10619 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10624 * mono_reflection_create_generic_class:
10625 * @tb: a TypeBuilder object
10627 * Creates the generic class after all generic parameters have been added.
10630 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10635 klass = mono_class_from_mono_type (tb->type.type);
10637 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10639 if (klass->generic_container || (count == 0))
10642 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10644 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10646 klass->generic_container->owner.klass = klass;
10647 klass->generic_container->type_argc = count;
10648 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10650 klass->is_generic = 1;
10652 for (i = 0; i < count; i++) {
10653 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10654 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10655 klass->generic_container->type_params [i] = *param;
10656 /*Make sure we are a diferent type instance */
10657 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10658 klass->generic_container->type_params [i].info.pklass = NULL;
10659 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10661 g_assert (klass->generic_container->type_params [i].param.owner);
10664 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10668 * mono_reflection_create_internal_class:
10669 * @tb: a TypeBuilder object
10671 * Actually create the MonoClass that is associated with the TypeBuilder.
10674 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10678 klass = mono_class_from_mono_type (tb->type.type);
10680 mono_loader_lock ();
10681 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10682 MonoReflectionFieldBuilder *fb;
10684 MonoType *enum_basetype;
10686 g_assert (tb->fields != NULL);
10687 g_assert (mono_array_length (tb->fields) >= 1);
10689 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10691 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10692 mono_loader_unlock ();
10696 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10697 klass->element_class = mono_class_from_mono_type (enum_basetype);
10698 if (!klass->element_class)
10699 klass->element_class = mono_class_from_mono_type (enum_basetype);
10702 * get the element_class from the current corlib.
10704 ec = default_class_from_mono_type (enum_basetype);
10705 klass->instance_size = ec->instance_size;
10706 klass->size_inited = 1;
10708 * this is almost safe to do with enums and it's needed to be able
10709 * to create objects of the enum type (for use in SetConstant).
10711 /* FIXME: Does this mean enums can't have method overrides ? */
10712 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10714 mono_loader_unlock ();
10717 static MonoMarshalSpec*
10718 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10719 MonoReflectionMarshal *minfo)
10721 MonoMarshalSpec *res;
10723 res = image_g_new0 (image, MonoMarshalSpec, 1);
10724 res->native = (MonoMarshalNative)minfo->type;
10726 switch (minfo->type) {
10727 case MONO_NATIVE_LPARRAY:
10728 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10729 if (minfo->has_size) {
10730 res->data.array_data.param_num = minfo->param_num;
10731 res->data.array_data.num_elem = minfo->count;
10732 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10735 res->data.array_data.param_num = -1;
10736 res->data.array_data.num_elem = -1;
10737 res->data.array_data.elem_mult = -1;
10741 case MONO_NATIVE_BYVALTSTR:
10742 case MONO_NATIVE_BYVALARRAY:
10743 res->data.array_data.num_elem = minfo->count;
10746 case MONO_NATIVE_CUSTOM:
10747 if (minfo->marshaltyperef)
10748 res->data.custom_data.custom_name =
10749 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10750 if (minfo->mcookie)
10751 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10760 #endif /* !DISABLE_REFLECTION_EMIT */
10762 MonoReflectionMarshalAsAttribute*
10763 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10764 MonoMarshalSpec *spec)
10766 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10768 MonoReflectionType *rt;
10769 MonoReflectionMarshalAsAttribute *minfo;
10772 if (!System_Reflection_Emit_MarshalAsAttribute) {
10773 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10774 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10775 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10778 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10779 mono_error_raise_exception (&error); /* FIXME don't raise here */
10780 minfo->utype = spec->native;
10782 switch (minfo->utype) {
10783 case MONO_NATIVE_LPARRAY:
10784 minfo->array_subtype = spec->data.array_data.elem_type;
10785 minfo->size_const = spec->data.array_data.num_elem;
10786 if (spec->data.array_data.param_num != -1)
10787 minfo->size_param_index = spec->data.array_data.param_num;
10790 case MONO_NATIVE_BYVALTSTR:
10791 case MONO_NATIVE_BYVALARRAY:
10792 minfo->size_const = spec->data.array_data.num_elem;
10795 case MONO_NATIVE_CUSTOM:
10796 if (spec->data.custom_data.custom_name) {
10797 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10799 rt = mono_type_get_object_checked (domain, mtype, &error);
10800 mono_error_raise_exception (&error); /* FIXME don't raise here */
10802 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10805 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10807 if (spec->data.custom_data.cookie)
10808 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10818 #ifndef DISABLE_REFLECTION_EMIT
10820 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10821 ReflectionMethodBuilder *rmb,
10822 MonoMethodSignature *sig)
10826 MonoMethodWrapper *wrapperm;
10827 MonoMarshalSpec **specs;
10828 MonoReflectionMethodAux *method_aux;
10833 mono_error_init (&error);
10835 * Methods created using a MethodBuilder should have their memory allocated
10836 * inside the image mempool, while dynamic methods should have their memory
10839 dynamic = rmb->refs != NULL;
10840 image = dynamic ? NULL : klass->image;
10843 g_assert (!klass->generic_class);
10845 mono_loader_lock ();
10847 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10848 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10849 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10851 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10853 wrapperm = (MonoMethodWrapper*)m;
10855 m->dynamic = dynamic;
10857 m->flags = rmb->attrs;
10858 m->iflags = rmb->iattrs;
10859 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10861 m->signature = sig;
10862 m->sre_method = TRUE;
10863 m->skip_visibility = rmb->skip_visibility;
10864 if (rmb->table_idx)
10865 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10867 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10868 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10869 m->string_ctor = 1;
10871 m->signature->pinvoke = 1;
10872 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10873 m->signature->pinvoke = 1;
10875 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10877 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10878 g_assert (mono_error_ok (&error));
10879 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10880 g_assert (mono_error_ok (&error));
10882 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10884 if (image_is_dynamic (klass->image))
10885 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10887 mono_loader_unlock ();
10890 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10891 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10892 MonoMethodHeader *header;
10894 gint32 max_stack, i;
10895 gint32 num_locals = 0;
10896 gint32 num_clauses = 0;
10900 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10901 code_size = rmb->ilgen->code_len;
10902 max_stack = rmb->ilgen->max_stack;
10903 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10904 if (rmb->ilgen->ex_handlers)
10905 num_clauses = method_count_clauses (rmb->ilgen);
10908 code = mono_array_addr (rmb->code, guint8, 0);
10909 code_size = mono_array_length (rmb->code);
10910 /* we probably need to run a verifier on the code... */
10920 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10921 header->code_size = code_size;
10922 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10923 memcpy ((char*)header->code, code, code_size);
10924 header->max_stack = max_stack;
10925 header->init_locals = rmb->init_locals;
10926 header->num_locals = num_locals;
10928 for (i = 0; i < num_locals; ++i) {
10929 MonoReflectionLocalBuilder *lb =
10930 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10932 header->locals [i] = image_g_new0 (image, MonoType, 1);
10933 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10936 header->num_clauses = num_clauses;
10938 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10939 rmb->ilgen, num_clauses);
10942 wrapperm->header = header;
10945 if (rmb->generic_params) {
10946 int count = mono_array_length (rmb->generic_params);
10947 MonoGenericContainer *container = rmb->generic_container;
10949 g_assert (container);
10951 container->type_argc = count;
10952 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10953 container->owner.method = m;
10954 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10956 m->is_generic = TRUE;
10957 mono_method_set_generic_container (m, container);
10959 for (i = 0; i < count; i++) {
10960 MonoReflectionGenericParam *gp =
10961 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10962 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10963 container->type_params [i] = *param;
10967 * The method signature might have pointers to generic parameters that belong to other methods.
10968 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10969 * generic parameters.
10971 for (i = 0; i < m->signature->param_count; ++i) {
10972 MonoType *t = m->signature->params [i];
10973 if (t->type == MONO_TYPE_MVAR) {
10974 MonoGenericParam *gparam = t->data.generic_param;
10975 if (gparam->num < count) {
10976 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10977 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10983 if (klass->generic_container) {
10984 container->parent = klass->generic_container;
10985 container->context.class_inst = klass->generic_container->context.class_inst;
10987 container->context.method_inst = mono_get_shared_generic_inst (container);
10991 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10995 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10997 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10998 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10999 for (i = 0; i < rmb->nrefs; ++i)
11000 data [i + 1] = rmb->refs [i];
11005 /* Parameter info */
11008 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11009 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11010 for (i = 0; i <= m->signature->param_count; ++i) {
11011 MonoReflectionParamBuilder *pb;
11012 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11013 if ((i > 0) && (pb->attrs)) {
11014 /* Make a copy since it might point to a shared type structure */
11015 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11016 m->signature->params [i - 1]->attrs = pb->attrs;
11019 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11020 MonoDynamicImage *assembly;
11022 MonoTypeEnum def_type;
11026 if (!method_aux->param_defaults) {
11027 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11028 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11030 assembly = (MonoDynamicImage*)klass->image;
11031 idx = encode_constant (assembly, pb->def_value, &def_type);
11032 /* Copy the data from the blob since it might get realloc-ed */
11033 p = assembly->blob.data + idx;
11034 len = mono_metadata_decode_blob_size (p, &p2);
11036 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11037 method_aux->param_default_types [i] = def_type;
11038 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11042 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11043 g_assert (mono_error_ok (&error));
11046 if (!method_aux->param_cattr)
11047 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11048 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11054 /* Parameter marshalling */
11057 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11058 MonoReflectionParamBuilder *pb;
11059 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11060 if (pb->marshal_info) {
11062 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11063 specs [pb->position] =
11064 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11068 if (specs != NULL) {
11070 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11071 method_aux->param_marshall = specs;
11074 if (image_is_dynamic (klass->image) && method_aux)
11075 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11077 mono_loader_unlock ();
11083 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11085 ReflectionMethodBuilder rmb;
11086 MonoMethodSignature *sig;
11088 mono_loader_lock ();
11089 sig = ctor_builder_to_signature (klass->image, mb);
11090 mono_loader_unlock ();
11092 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11094 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11095 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11097 /* If we are in a generic class, we might be called multiple times from inflate_method */
11098 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11099 /* ilgen is no longer needed */
11103 return mb->mhandle;
11107 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11109 ReflectionMethodBuilder rmb;
11110 MonoMethodSignature *sig;
11112 mono_loader_lock ();
11113 sig = method_builder_to_signature (klass->image, mb);
11114 mono_loader_unlock ();
11116 reflection_methodbuilder_from_method_builder (&rmb, mb);
11118 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11119 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11121 /* If we are in a generic class, we might be called multiple times from inflate_method */
11122 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11123 /* ilgen is no longer needed */
11126 return mb->mhandle;
11129 static MonoClassField*
11130 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11132 MonoClassField *field;
11136 field = g_new0 (MonoClassField, 1);
11138 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11139 g_assert (mono_error_ok (&error));
11140 if (fb->attrs || fb->modreq || fb->modopt) {
11141 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11142 field->type->attrs = fb->attrs;
11144 g_assert (image_is_dynamic (klass->image));
11145 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11146 g_free (field->type);
11147 field->type = mono_metadata_type_dup (klass->image, custom);
11150 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11152 if (fb->offset != -1)
11153 field->offset = fb->offset;
11154 field->parent = klass;
11155 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11157 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11164 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11167 MonoReflectionTypeBuilder *tb = NULL;
11168 gboolean is_dynamic = FALSE;
11169 MonoClass *geninst;
11171 mono_loader_lock ();
11173 if (is_sre_type_builder (mono_object_class (type))) {
11174 tb = (MonoReflectionTypeBuilder *) type;
11177 } else if (is_sre_generic_instance (mono_object_class (type))) {
11178 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11179 MonoReflectionType *gtd = rgi->generic_type;
11181 if (is_sre_type_builder (mono_object_class (gtd))) {
11182 tb = (MonoReflectionTypeBuilder *)gtd;
11187 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11188 if (tb && tb->generic_container)
11189 mono_reflection_create_generic_class (tb);
11191 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11192 if (!klass->generic_container) {
11193 mono_loader_unlock ();
11197 if (klass->wastypebuilder) {
11198 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11203 mono_loader_unlock ();
11205 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11207 return &geninst->byval_arg;
11211 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11213 MonoGenericClass *gclass;
11214 MonoGenericInst *inst;
11216 g_assert (klass->generic_container);
11218 inst = mono_metadata_get_generic_inst (type_argc, types);
11219 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11221 return mono_generic_class_get_class (gclass);
11224 MonoReflectionMethod*
11225 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11229 MonoMethod *method, *inflated;
11230 MonoMethodInflated *imethod;
11231 MonoGenericContext tmp_context;
11232 MonoGenericInst *ginst;
11233 MonoType **type_argv;
11236 /*FIXME but this no longer should happen*/
11237 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11238 #ifndef DISABLE_REFLECTION_EMIT
11239 MonoReflectionMethodBuilder *mb = NULL;
11240 MonoReflectionTypeBuilder *tb;
11243 mb = (MonoReflectionMethodBuilder *) rmethod;
11244 tb = (MonoReflectionTypeBuilder *) mb->type;
11245 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11247 method = methodbuilder_to_mono_method (klass, mb);
11249 g_assert_not_reached ();
11253 method = rmethod->method;
11256 klass = method->klass;
11258 if (method->is_inflated)
11259 method = ((MonoMethodInflated *) method)->declaring;
11261 count = mono_method_signature (method)->generic_param_count;
11262 if (count != mono_array_length (types))
11265 type_argv = g_new0 (MonoType *, count);
11266 for (i = 0; i < count; i++) {
11267 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11268 type_argv [i] = mono_reflection_type_get_handle (garg);
11270 ginst = mono_metadata_get_generic_inst (count, type_argv);
11271 g_free (type_argv);
11273 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11274 tmp_context.method_inst = ginst;
11276 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11277 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11278 imethod = (MonoMethodInflated *) inflated;
11280 /*FIXME but I think this is no longer necessary*/
11281 if (image_is_dynamic (method->klass->image)) {
11282 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11284 * This table maps metadata structures representing inflated methods/fields
11285 * to the reflection objects representing their generic definitions.
11287 mono_image_lock ((MonoImage*)image);
11288 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11289 mono_image_unlock ((MonoImage*)image);
11292 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11293 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11295 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11296 mono_error_raise_exception (&error); /* FIXME don't raise here */
11300 #ifndef DISABLE_REFLECTION_EMIT
11302 static MonoMethod *
11303 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11305 MonoMethodInflated *imethod;
11306 MonoGenericContext *context;
11310 * With generic code sharing the klass might not be inflated.
11311 * This can happen because classes inflated with their own
11312 * type arguments are "normalized" to the uninflated class.
11314 if (!klass->generic_class)
11317 context = mono_class_get_context (klass);
11319 if (klass->method.count && klass->methods) {
11320 /* Find the already created inflated method */
11321 for (i = 0; i < klass->method.count; ++i) {
11322 g_assert (klass->methods [i]->is_inflated);
11323 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11326 g_assert (i < klass->method.count);
11327 imethod = (MonoMethodInflated*)klass->methods [i];
11330 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11331 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11334 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11335 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11337 mono_image_lock ((MonoImage*)image);
11338 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11339 mono_image_unlock ((MonoImage*)image);
11341 return (MonoMethod *) imethod;
11344 static MonoMethod *
11345 inflate_method (MonoReflectionType *type, MonoObject *obj)
11347 MonoMethod *method;
11350 MonoClass *type_class = mono_object_class (type);
11352 if (is_sre_generic_instance (type_class)) {
11353 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11354 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11355 } else if (is_sre_type_builder (type_class)) {
11356 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11357 } else if (type->type) {
11358 gklass = mono_class_from_mono_type (type->type);
11359 gklass = mono_class_get_generic_type_definition (gklass);
11361 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11364 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11365 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11366 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11368 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11369 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11370 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11371 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11372 method = ((MonoReflectionMethod *) obj)->method;
11374 method = NULL; /* prevent compiler warning */
11375 g_error ("can't handle type %s", obj->vtable->klass->name);
11378 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11381 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11383 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11385 MonoGenericClass *gclass;
11386 MonoDynamicGenericClass *dgclass;
11387 MonoClass *klass, *gklass;
11391 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11392 klass = mono_class_from_mono_type (gtype);
11393 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11394 gclass = gtype->data.generic_class;
11396 if (!gclass->is_dynamic)
11399 dgclass = (MonoDynamicGenericClass *) gclass;
11401 if (dgclass->initialized)
11404 gklass = gclass->container_class;
11405 mono_class_init (gklass);
11407 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11409 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11410 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11411 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11413 for (i = 0; i < dgclass->count_fields; i++) {
11414 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11415 MonoClassField *field, *inflated_field = NULL;
11417 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11418 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11419 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11420 field = ((MonoReflectionField *) obj)->field;
11422 field = NULL; /* prevent compiler warning */
11423 g_assert_not_reached ();
11426 dgclass->fields [i] = *field;
11427 dgclass->fields [i].parent = klass;
11428 dgclass->fields [i].type = mono_class_inflate_generic_type (
11429 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11430 dgclass->field_generic_types [i] = field->type;
11431 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11432 dgclass->field_objects [i] = obj;
11434 if (inflated_field) {
11435 g_free (inflated_field);
11437 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11441 dgclass->initialized = TRUE;
11445 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11447 MonoDynamicGenericClass *dgclass;
11450 g_assert (gclass->is_dynamic);
11452 dgclass = (MonoDynamicGenericClass *)gclass;
11454 for (i = 0; i < dgclass->count_fields; ++i) {
11455 MonoClassField *field = dgclass->fields + i;
11456 mono_metadata_free_type (field->type);
11457 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11462 fix_partial_generic_class (MonoClass *klass)
11464 MonoClass *gklass = klass->generic_class->container_class;
11465 MonoDynamicGenericClass *dgclass;
11468 if (klass->wastypebuilder)
11471 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11472 if (klass->parent != gklass->parent) {
11474 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11475 if (mono_error_ok (&error)) {
11476 MonoClass *parent = mono_class_from_mono_type (parent_type);
11477 mono_metadata_free_type (parent_type);
11478 if (parent != klass->parent) {
11479 /*fool mono_class_setup_parent*/
11480 klass->supertypes = NULL;
11481 mono_class_setup_parent (klass, parent);
11484 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11485 mono_error_cleanup (&error);
11486 if (gklass->wastypebuilder)
11487 klass->wastypebuilder = TRUE;
11492 if (!dgclass->initialized)
11495 if (klass->method.count != gklass->method.count) {
11496 klass->method.count = gklass->method.count;
11497 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11499 for (i = 0; i < klass->method.count; i++) {
11501 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11502 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11503 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11507 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11508 klass->interface_count = gklass->interface_count;
11509 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11510 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11512 for (i = 0; i < gklass->interface_count; ++i) {
11513 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11514 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11515 mono_metadata_free_type (iface_type);
11517 ensure_runtime_vtable (klass->interfaces [i]);
11519 klass->interfaces_inited = 1;
11522 if (klass->field.count != gklass->field.count) {
11523 klass->field.count = gklass->field.count;
11524 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11526 for (i = 0; i < klass->field.count; i++) {
11527 klass->fields [i] = gklass->fields [i];
11528 klass->fields [i].parent = klass;
11529 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11533 /*We can only finish with this klass once it's parent has as well*/
11534 if (gklass->wastypebuilder)
11535 klass->wastypebuilder = TRUE;
11540 ensure_generic_class_runtime_vtable (MonoClass *klass)
11542 MonoClass *gklass = klass->generic_class->container_class;
11544 ensure_runtime_vtable (gklass);
11546 fix_partial_generic_class (klass);
11550 ensure_runtime_vtable (MonoClass *klass)
11552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11555 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11558 ensure_runtime_vtable (klass->parent);
11561 num = tb->ctors? mono_array_length (tb->ctors): 0;
11562 num += tb->num_methods;
11563 klass->method.count = num;
11564 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11565 num = tb->ctors? mono_array_length (tb->ctors): 0;
11566 for (i = 0; i < num; ++i)
11567 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11568 num = tb->num_methods;
11570 for (i = 0; i < num; ++i)
11571 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11573 if (tb->interfaces) {
11574 klass->interface_count = mono_array_length (tb->interfaces);
11575 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11576 for (i = 0; i < klass->interface_count; ++i) {
11577 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11578 klass->interfaces [i] = mono_class_from_mono_type (iface);
11579 ensure_runtime_vtable (klass->interfaces [i]);
11581 klass->interfaces_inited = 1;
11583 } else if (klass->generic_class){
11584 ensure_generic_class_runtime_vtable (klass);
11587 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11589 for (i = 0; i < klass->method.count; ++i) {
11590 MonoMethod *im = klass->methods [i];
11591 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11592 im->slot = slot_num++;
11595 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11596 mono_class_setup_interface_offsets (klass);
11597 mono_class_setup_interface_id (klass);
11601 * The generic vtable is needed even if image->run is not set since some
11602 * runtime code like ves_icall_Type_GetMethodsByName depends on
11603 * method->slot being defined.
11607 * tb->methods could not be freed since it is used for determining
11608 * overrides during dynamic vtable construction.
11613 mono_reflection_method_get_handle (MonoObject *method)
11615 MonoClass *klass = mono_object_class (method);
11616 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11617 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11618 return sr_method->method;
11620 if (is_sre_method_builder (klass)) {
11621 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11622 return mb->mhandle;
11624 if (is_sre_method_on_tb_inst (klass)) {
11625 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11626 MonoMethod *result;
11627 /*FIXME move this to a proper method and unify with resolve_object*/
11628 if (m->method_args) {
11629 result = mono_reflection_method_on_tb_inst_get_handle (m);
11631 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11632 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11633 MonoMethod *mono_method;
11635 if (is_sre_method_builder (mono_object_class (m->mb)))
11636 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11637 else if (is_sr_mono_method (mono_object_class (m->mb)))
11638 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11640 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)));
11642 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11647 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11652 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11654 MonoReflectionTypeBuilder *tb;
11656 MonoReflectionMethod *m;
11659 *num_overrides = 0;
11661 g_assert (image_is_dynamic (klass->image));
11663 if (!mono_class_get_ref_info (klass))
11666 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11668 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11672 for (i = 0; i < tb->num_methods; ++i) {
11673 MonoReflectionMethodBuilder *mb =
11674 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11675 if (mb->override_methods)
11676 onum += mono_array_length (mb->override_methods);
11681 *overrides = g_new0 (MonoMethod*, onum * 2);
11684 for (i = 0; i < tb->num_methods; ++i) {
11685 MonoReflectionMethodBuilder *mb =
11686 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11687 if (mb->override_methods) {
11688 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11689 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11691 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11692 (*overrides) [onum * 2 + 1] = mb->mhandle;
11694 g_assert (mb->mhandle);
11702 *num_overrides = onum;
11706 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11708 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11709 MonoReflectionFieldBuilder *fb;
11710 MonoClassField *field;
11711 MonoImage *image = klass->image;
11712 const char *p, *p2;
11714 guint32 len, idx, real_size = 0;
11716 klass->field.count = tb->num_fields;
11717 klass->field.first = 0;
11719 mono_error_init (error);
11721 if (tb->class_size) {
11722 if ((tb->packing_size & 0xffffff00) != 0) {
11723 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11724 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11727 klass->packing_size = tb->packing_size;
11728 real_size = klass->instance_size + tb->class_size;
11731 if (!klass->field.count) {
11732 klass->instance_size = MAX (klass->instance_size, real_size);
11736 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11737 mono_class_alloc_ext (klass);
11738 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11740 This is, guess what, a hack.
11741 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11742 On the static path no field class is resolved, only types are built. This is the right thing to do
11744 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11746 klass->size_inited = 1;
11748 for (i = 0; i < klass->field.count; ++i) {
11749 MonoArray *rva_data;
11750 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11751 field = &klass->fields [i];
11752 field->name = mono_string_to_utf8_image (image, fb->name, error);
11753 if (!mono_error_ok (error))
11756 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11757 field->type->attrs = fb->attrs;
11759 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11762 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11763 char *base = mono_array_addr (rva_data, char, 0);
11764 size_t size = mono_array_length (rva_data);
11765 char *data = (char *)mono_image_alloc (klass->image, size);
11766 memcpy (data, base, size);
11767 klass->ext->field_def_values [i].data = data;
11769 if (fb->offset != -1)
11770 field->offset = fb->offset;
11771 field->parent = klass;
11772 fb->handle = field;
11773 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11775 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11776 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11778 if (fb->def_value) {
11779 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11780 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11781 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11782 /* Copy the data from the blob since it might get realloc-ed */
11783 p = assembly->blob.data + idx;
11784 len = mono_metadata_decode_blob_size (p, &p2);
11786 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11787 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11791 klass->instance_size = MAX (klass->instance_size, real_size);
11792 mono_class_layout_fields (klass);
11796 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11798 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11799 MonoReflectionPropertyBuilder *pb;
11800 MonoImage *image = klass->image;
11801 MonoProperty *properties;
11804 mono_error_init (error);
11807 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11809 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11810 klass->ext->property.first = 0;
11812 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11813 klass->ext->properties = properties;
11814 for (i = 0; i < klass->ext->property.count; ++i) {
11815 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11816 properties [i].parent = klass;
11817 properties [i].attrs = pb->attrs;
11818 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11819 if (!mono_error_ok (error))
11821 if (pb->get_method)
11822 properties [i].get = pb->get_method->mhandle;
11823 if (pb->set_method)
11824 properties [i].set = pb->set_method->mhandle;
11826 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11827 if (pb->def_value) {
11829 const char *p, *p2;
11830 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11831 if (!klass->ext->prop_def_values)
11832 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11833 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11834 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11835 /* Copy the data from the blob since it might get realloc-ed */
11836 p = assembly->blob.data + idx;
11837 len = mono_metadata_decode_blob_size (p, &p2);
11839 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11840 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11845 MonoReflectionEvent *
11846 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11848 MonoEvent *event = g_new0 (MonoEvent, 1);
11851 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11853 event->parent = klass;
11854 event->attrs = eb->attrs;
11855 event->name = mono_string_to_utf8 (eb->name);
11856 if (eb->add_method)
11857 event->add = eb->add_method->mhandle;
11858 if (eb->remove_method)
11859 event->remove = eb->remove_method->mhandle;
11860 if (eb->raise_method)
11861 event->raise = eb->raise_method->mhandle;
11863 #ifndef MONO_SMALL_CONFIG
11864 if (eb->other_methods) {
11866 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11867 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11868 MonoReflectionMethodBuilder *mb =
11869 mono_array_get (eb->other_methods,
11870 MonoReflectionMethodBuilder*, j);
11871 event->other [j] = mb->mhandle;
11876 return mono_event_get_object (mono_object_domain (tb), klass, event);
11880 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11883 MonoReflectionEventBuilder *eb;
11884 MonoImage *image = klass->image;
11888 mono_error_init (error);
11891 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11893 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11894 klass->ext->event.first = 0;
11896 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11897 klass->ext->events = events;
11898 for (i = 0; i < klass->ext->event.count; ++i) {
11899 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11900 events [i].parent = klass;
11901 events [i].attrs = eb->attrs;
11902 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11903 if (!mono_error_ok (error))
11905 if (eb->add_method)
11906 events [i].add = eb->add_method->mhandle;
11907 if (eb->remove_method)
11908 events [i].remove = eb->remove_method->mhandle;
11909 if (eb->raise_method)
11910 events [i].raise = eb->raise_method->mhandle;
11912 #ifndef MONO_SMALL_CONFIG
11913 if (eb->other_methods) {
11915 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11916 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11917 MonoReflectionMethodBuilder *mb =
11918 mono_array_get (eb->other_methods,
11919 MonoReflectionMethodBuilder*, j);
11920 events [i].other [j] = mb->mhandle;
11924 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11929 remove_instantiations_of_and_ensure_contents (gpointer key,
11931 gpointer user_data)
11933 MonoType *type = (MonoType*)key;
11934 MonoClass *klass = (MonoClass*)user_data;
11936 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11937 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11944 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11946 mono_error_init (error);
11952 for (i = 0; i < mono_array_length (arr); ++i) {
11953 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11954 if (!mono_error_ok (error))
11959 MonoReflectionType*
11960 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11964 MonoDomain* domain;
11965 MonoReflectionType* res;
11968 domain = mono_object_domain (tb);
11969 klass = mono_class_from_mono_type (tb->type.type);
11972 * Check for user defined Type subclasses.
11974 RESOLVE_TYPE (tb->parent, &error);
11975 mono_error_raise_exception (&error); /* FIXME don't raise here */
11976 check_array_for_usertypes (tb->interfaces, &error);
11977 mono_error_raise_exception (&error); /*FIXME don't raise here */
11979 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11980 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11982 RESOLVE_TYPE (fb->type, &error);
11983 mono_error_raise_exception (&error); /* FIXME don't raise here */
11984 check_array_for_usertypes (fb->modreq, &error);
11985 mono_error_raise_exception (&error); /*FIXME don't raise here */
11986 check_array_for_usertypes (fb->modopt, &error);
11987 mono_error_raise_exception (&error); /*FIXME don't raise here */
11988 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11989 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11990 mono_error_raise_exception (&error); /* FIXME don't raise here */
11996 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11997 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11999 RESOLVE_TYPE (mb->rtype, &error);
12000 mono_error_raise_exception (&error); /* FIXME don't raise here */
12001 check_array_for_usertypes (mb->return_modreq, &error);
12002 mono_error_raise_exception (&error); /*FIXME don't raise here */
12003 check_array_for_usertypes (mb->return_modopt, &error);
12004 mono_error_raise_exception (&error); /*FIXME don't raise here */
12005 check_array_for_usertypes (mb->parameters, &error);
12006 mono_error_raise_exception (&error); /*FIXME don't raise here */
12007 if (mb->param_modreq)
12008 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12009 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12010 mono_error_raise_exception (&error); /*FIXME don't raise here */
12012 if (mb->param_modopt)
12013 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12014 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12015 mono_error_raise_exception (&error); /*FIXME don't raise here */
12021 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12022 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12024 check_array_for_usertypes (mb->parameters, &error);
12025 mono_error_raise_exception (&error); /*FIXME don't raise here */
12026 if (mb->param_modreq)
12027 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12028 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12029 mono_error_raise_exception (&error); /*FIXME don't raise here */
12031 if (mb->param_modopt)
12032 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12033 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12034 mono_error_raise_exception (&error); /*FIXME don't raise here */
12040 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12043 * we need to lock the domain because the lock will be taken inside
12044 * So, we need to keep the locking order correct.
12046 mono_loader_lock ();
12047 mono_domain_lock (domain);
12048 if (klass->wastypebuilder) {
12049 mono_domain_unlock (domain);
12050 mono_loader_unlock ();
12052 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12053 mono_error_raise_exception (&error); /* FIXME don't raise here */
12058 * Fields to set in klass:
12059 * the various flags: delegate/unicode/contextbound etc.
12061 klass->flags = tb->attrs;
12062 klass->has_cctor = 1;
12063 klass->has_finalize = 1;
12064 klass->has_finalize_inited = 1;
12066 mono_class_setup_parent (klass, klass->parent);
12067 /* fool mono_class_setup_supertypes */
12068 klass->supertypes = NULL;
12069 mono_class_setup_supertypes (klass);
12070 mono_class_setup_mono_type (klass);
12073 if (!((MonoDynamicImage*)klass->image)->run) {
12074 if (klass->generic_container) {
12075 /* FIXME: The code below can't handle generic classes */
12076 klass->wastypebuilder = TRUE;
12077 mono_loader_unlock ();
12078 mono_domain_unlock (domain);
12080 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12081 mono_error_raise_exception (&error); /* FIXME don't raise here */
12088 /* enums are done right away */
12089 if (!klass->enumtype)
12090 ensure_runtime_vtable (klass);
12092 if (tb->subtypes) {
12093 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12094 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12095 mono_class_alloc_ext (klass);
12096 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)));
12100 klass->nested_classes_inited = TRUE;
12102 /* fields and object layout */
12103 if (klass->parent) {
12104 if (!klass->parent->size_inited)
12105 mono_class_init (klass->parent);
12106 klass->instance_size = klass->parent->instance_size;
12107 klass->sizes.class_size = 0;
12108 klass->min_align = klass->parent->min_align;
12109 /* if the type has no fields we won't call the field_setup
12110 * routine which sets up klass->has_references.
12112 klass->has_references |= klass->parent->has_references;
12114 klass->instance_size = sizeof (MonoObject);
12115 klass->min_align = 1;
12118 /* FIXME: handle packing_size and instance_size */
12119 typebuilder_setup_fields (klass, &error);
12120 if (!mono_error_ok (&error))
12122 typebuilder_setup_properties (klass, &error);
12123 if (!mono_error_ok (&error))
12126 typebuilder_setup_events (klass, &error);
12127 if (!mono_error_ok (&error))
12130 klass->wastypebuilder = TRUE;
12133 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12134 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12135 * we want to return normal System.MonoType objects, so clear these out from the cache.
12137 * Together with this we must ensure the contents of all instances to match the created type.
12139 if (domain->type_hash && klass->generic_container)
12140 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12142 mono_domain_unlock (domain);
12143 mono_loader_unlock ();
12145 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12146 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12147 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12150 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12151 mono_error_raise_exception (&error); /* FIXME don't raise here */
12153 g_assert (res != (MonoReflectionType*)tb);
12158 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12159 klass->wastypebuilder = TRUE;
12160 mono_domain_unlock (domain);
12161 mono_loader_unlock ();
12162 mono_error_raise_exception (&error);
12167 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12169 MonoGenericParamFull *param;
12174 image = &gparam->tbuilder->module->dynamic_image->image;
12176 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12178 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12179 g_assert (mono_error_ok (&error));
12180 param->param.num = gparam->index;
12182 if (gparam->mbuilder) {
12183 if (!gparam->mbuilder->generic_container) {
12184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12185 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12186 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12187 gparam->mbuilder->generic_container->is_method = TRUE;
12189 * Cannot set owner.method, since the MonoMethod is not created yet.
12190 * Set the image field instead, so type_in_image () works.
12192 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12193 gparam->mbuilder->generic_container->owner.image = klass->image;
12195 param->param.owner = gparam->mbuilder->generic_container;
12196 } else if (gparam->tbuilder) {
12197 if (!gparam->tbuilder->generic_container) {
12198 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12199 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12200 gparam->tbuilder->generic_container->owner.klass = klass;
12202 param->param.owner = gparam->tbuilder->generic_container;
12205 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12207 gparam->type.type = &pklass->byval_arg;
12209 mono_class_set_ref_info (pklass, gparam);
12210 mono_image_append_class_to_reflection_info_set (pklass);
12214 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12217 MonoReflectionModuleBuilder *module = sig->module;
12218 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12219 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12224 check_array_for_usertypes (sig->arguments, &error);
12225 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12227 sigbuffer_init (&buf, 32);
12229 sigbuffer_add_value (&buf, 0x07);
12230 sigbuffer_add_value (&buf, na);
12231 if (assembly != NULL){
12232 for (i = 0; i < na; ++i) {
12233 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12234 encode_reflection_type (assembly, type, &buf);
12238 buflen = buf.p - buf.buf;
12239 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12240 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12241 sigbuffer_free (&buf);
12247 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12250 MonoDynamicImage *assembly = sig->module->dynamic_image;
12251 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12256 check_array_for_usertypes (sig->arguments, &error);
12257 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12259 sigbuffer_init (&buf, 32);
12261 sigbuffer_add_value (&buf, 0x06);
12262 for (i = 0; i < na; ++i) {
12263 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12264 encode_reflection_type (assembly, type, &buf);
12267 buflen = buf.p - buf.buf;
12268 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12269 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12270 sigbuffer_free (&buf);
12276 MonoMethod *handle;
12277 MonoDomain *domain;
12278 } DynamicMethodReleaseData;
12281 * The runtime automatically clean up those after finalization.
12283 static MonoReferenceQueue *dynamic_method_queue;
12286 free_dynamic_method (void *dynamic_method)
12288 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12289 MonoDomain *domain = data->domain;
12290 MonoMethod *method = data->handle;
12293 mono_domain_lock (domain);
12294 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12295 g_hash_table_remove (domain->method_to_dyn_method, method);
12296 mono_domain_unlock (domain);
12297 g_assert (dis_link);
12298 mono_gchandle_free (dis_link);
12300 mono_runtime_free_method (domain, method);
12305 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12307 MonoReferenceQueue *queue;
12308 MonoMethod *handle;
12309 DynamicMethodReleaseData *release_data;
12310 ReflectionMethodBuilder rmb;
12311 MonoMethodSignature *sig;
12313 MonoDomain *domain;
12317 if (mono_runtime_is_shutting_down ())
12318 mono_raise_exception (mono_get_exception_invalid_operation (""));
12320 if (!(queue = dynamic_method_queue)) {
12321 mono_loader_lock ();
12322 if (!(queue = dynamic_method_queue))
12323 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12324 mono_loader_unlock ();
12327 sig = dynamic_method_to_signature (mb);
12329 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12332 * Resolve references.
12335 * Every second entry in the refs array is reserved for storing handle_class,
12336 * which is needed by the ldtoken implementation in the JIT.
12338 rmb.nrefs = mb->nrefs;
12339 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12340 for (i = 0; i < mb->nrefs; i += 2) {
12341 MonoClass *handle_class;
12343 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12345 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12346 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12348 * The referenced DynamicMethod should already be created by the managed
12349 * code, except in the case of circular references. In that case, we store
12350 * method in the refs array, and fix it up later when the referenced
12351 * DynamicMethod is created.
12353 if (method->mhandle) {
12354 ref = method->mhandle;
12356 /* FIXME: GC object stored in unmanaged memory */
12359 /* FIXME: GC object stored in unmanaged memory */
12360 method->referenced_by = g_slist_append (method->referenced_by, mb);
12362 handle_class = mono_defaults.methodhandle_class;
12364 MonoException *ex = NULL;
12365 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12367 ex = mono_get_exception_type_load (NULL, NULL);
12368 else if (mono_security_core_clr_enabled ())
12369 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12373 mono_raise_exception (ex);
12378 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12379 rmb.refs [i + 1] = handle_class;
12382 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12384 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12385 release_data = g_new (DynamicMethodReleaseData, 1);
12386 release_data->handle = handle;
12387 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12388 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12389 g_free (release_data);
12391 /* Fix up refs entries pointing at us */
12392 for (l = mb->referenced_by; l; l = l->next) {
12393 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12394 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12397 g_assert (method->mhandle);
12399 data = (gpointer*)wrapper->method_data;
12400 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12401 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12402 data [i + 1] = mb->mhandle;
12405 g_slist_free (mb->referenced_by);
12409 /* ilgen is no longer needed */
12412 domain = mono_domain_get ();
12413 mono_domain_lock (domain);
12414 if (!domain->method_to_dyn_method)
12415 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12416 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12417 mono_domain_unlock (domain);
12420 #endif /* DISABLE_REFLECTION_EMIT */
12424 * mono_reflection_is_valid_dynamic_token:
12426 * Returns TRUE if token is valid.
12430 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12432 return lookup_dyn_token (image, token) != NULL;
12435 MonoMethodSignature *
12436 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12438 MonoMethodSignature *sig;
12439 g_assert (image_is_dynamic (image));
12441 mono_error_init (error);
12443 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12447 return mono_method_signature_checked (method, error);
12450 #ifndef DISABLE_REFLECTION_EMIT
12453 * mono_reflection_lookup_dynamic_token:
12455 * Finish the Builder object pointed to by TOKEN and return the corresponding
12456 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12457 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12460 * LOCKING: Take the loader lock
12463 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12465 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12469 obj = lookup_dyn_token (assembly, token);
12472 g_error ("Could not find required dynamic token 0x%08x", token);
12478 handle_class = &klass;
12479 return resolve_object (image, obj, handle_class, context);
12483 * ensure_complete_type:
12485 * Ensure that KLASS is completed if it is a dynamic type, or references
12489 ensure_complete_type (MonoClass *klass)
12491 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12492 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12494 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12496 // Asserting here could break a lot of code
12497 //g_assert (klass->wastypebuilder);
12500 if (klass->generic_class) {
12501 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12504 for (i = 0; i < inst->type_argc; ++i) {
12505 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12511 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12513 gpointer result = NULL;
12515 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12516 result = mono_string_intern ((MonoString*)obj);
12517 *handle_class = mono_defaults.string_class;
12519 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12520 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12521 MonoClass *mc = mono_class_from_mono_type (type);
12522 if (!mono_class_init (mc))
12523 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12526 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12527 result = mono_class_from_mono_type (inflated);
12528 mono_metadata_free_type (inflated);
12530 result = mono_class_from_mono_type (type);
12532 *handle_class = mono_defaults.typehandle_class;
12534 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12535 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12536 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12537 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12538 result = ((MonoReflectionMethod*)obj)->method;
12541 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12542 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12544 *handle_class = mono_defaults.methodhandle_class;
12546 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12547 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12548 result = mb->mhandle;
12550 /* Type is not yet created */
12551 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12553 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12556 * Hopefully this has been filled in by calling CreateType() on the
12560 * TODO: This won't work if the application finishes another
12561 * TypeBuilder instance instead of this one.
12563 result = mb->mhandle;
12567 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12568 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12570 *handle_class = mono_defaults.methodhandle_class;
12571 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12572 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12574 result = cb->mhandle;
12576 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12578 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12579 result = cb->mhandle;
12583 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12584 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12586 *handle_class = mono_defaults.methodhandle_class;
12587 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12588 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12590 ensure_complete_type (field->parent);
12592 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12593 MonoClass *klass = mono_class_from_mono_type (inflated);
12594 MonoClassField *inflated_field;
12595 gpointer iter = NULL;
12596 mono_metadata_free_type (inflated);
12597 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12598 if (!strcmp (field->name, inflated_field->name))
12601 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12602 result = inflated_field;
12606 *handle_class = mono_defaults.fieldhandle_class;
12608 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12609 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12610 result = fb->handle;
12613 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12615 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12616 result = fb->handle;
12619 if (fb->handle && fb->handle->parent->generic_container) {
12620 MonoClass *klass = fb->handle->parent;
12621 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12622 MonoClass *inflated = mono_class_from_mono_type (type);
12624 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12626 mono_metadata_free_type (type);
12628 *handle_class = mono_defaults.fieldhandle_class;
12629 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12630 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12631 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12634 klass = type->data.klass;
12635 if (klass->wastypebuilder) {
12636 /* Already created */
12640 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12641 result = type->data.klass;
12644 *handle_class = mono_defaults.typehandle_class;
12645 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12646 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12647 MonoMethodSignature *sig;
12650 if (helper->arguments)
12651 nargs = mono_array_length (helper->arguments);
12655 sig = mono_metadata_signature_alloc (image, nargs);
12656 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12657 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12659 if (helper->unmanaged_call_conv) { /* unmanaged */
12660 sig->call_convention = helper->unmanaged_call_conv - 1;
12661 sig->pinvoke = TRUE;
12662 } else if (helper->call_conv & 0x02) {
12663 sig->call_convention = MONO_CALL_VARARG;
12665 sig->call_convention = MONO_CALL_DEFAULT;
12668 sig->param_count = nargs;
12669 /* TODO: Copy type ? */
12670 sig->ret = helper->return_type->type;
12671 for (i = 0; i < nargs; ++i)
12672 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12675 *handle_class = NULL;
12676 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12677 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12678 /* Already created by the managed code */
12679 g_assert (method->mhandle);
12680 result = method->mhandle;
12681 *handle_class = mono_defaults.methodhandle_class;
12682 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12683 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12684 type = mono_class_inflate_generic_type (type, context);
12685 result = mono_class_from_mono_type (type);
12686 *handle_class = mono_defaults.typehandle_class;
12688 mono_metadata_free_type (type);
12689 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12690 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12691 type = mono_class_inflate_generic_type (type, context);
12692 result = mono_class_from_mono_type (type);
12693 *handle_class = mono_defaults.typehandle_class;
12695 mono_metadata_free_type (type);
12696 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12697 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12698 MonoClass *inflated;
12700 MonoClassField *field;
12702 if (is_sre_field_builder (mono_object_class (f->fb)))
12703 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12704 else if (is_sr_mono_field (mono_object_class (f->fb)))
12705 field = ((MonoReflectionField*)f->fb)->field;
12707 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)));
12709 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12710 inflated = mono_class_from_mono_type (type);
12712 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12713 ensure_complete_type (field->parent);
12715 mono_metadata_free_type (type);
12716 *handle_class = mono_defaults.fieldhandle_class;
12717 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12718 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12719 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12720 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12721 MonoMethod *method;
12723 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12724 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12725 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12726 method = ((MonoReflectionMethod *)c->cb)->method;
12728 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)));
12730 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12731 *handle_class = mono_defaults.methodhandle_class;
12732 mono_metadata_free_type (type);
12733 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12734 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12735 if (m->method_args) {
12736 result = mono_reflection_method_on_tb_inst_get_handle (m);
12739 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12740 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12743 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12744 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12745 MonoMethod *method;
12747 if (is_sre_method_builder (mono_object_class (m->mb)))
12748 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12749 else if (is_sr_mono_method (mono_object_class (m->mb)))
12750 method = ((MonoReflectionMethod *)m->mb)->method;
12752 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)));
12754 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12755 mono_metadata_free_type (type);
12757 *handle_class = mono_defaults.methodhandle_class;
12758 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12759 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12762 MonoMethod *method;
12766 mtype = mono_reflection_type_get_handle (m->parent);
12767 klass = mono_class_from_mono_type (mtype);
12769 /* Find the method */
12771 name = mono_string_to_utf8 (m->name);
12773 while ((method = mono_class_get_methods (klass, &iter))) {
12774 if (!strcmp (method->name, name))
12781 // FIXME: Check parameters/return value etc. match
12784 *handle_class = mono_defaults.methodhandle_class;
12785 } else if (is_sre_array (mono_object_get_class(obj)) ||
12786 is_sre_byref (mono_object_get_class(obj)) ||
12787 is_sre_pointer (mono_object_get_class(obj))) {
12788 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12789 MonoType *type = mono_reflection_type_get_handle (ref_type);
12792 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12793 result = mono_class_from_mono_type (inflated);
12794 mono_metadata_free_type (inflated);
12796 result = mono_class_from_mono_type (type);
12798 *handle_class = mono_defaults.typehandle_class;
12800 g_print ("%s\n", obj->vtable->klass->name);
12801 g_assert_not_reached ();
12806 #else /* DISABLE_REFLECTION_EMIT */
12809 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12811 g_assert_not_reached ();
12816 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12818 g_assert_not_reached ();
12822 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12824 g_assert_not_reached ();
12828 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12830 g_assert_not_reached ();
12834 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12836 g_assert_not_reached ();
12840 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12842 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12846 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12848 g_assert_not_reached ();
12852 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12854 g_assert_not_reached ();
12857 MonoReflectionModule *
12858 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12860 g_assert_not_reached ();
12865 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12867 g_assert_not_reached ();
12872 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12874 g_assert_not_reached ();
12879 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12880 gboolean create_open_instance, gboolean register_token)
12882 g_assert_not_reached ();
12887 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12892 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12894 g_assert_not_reached ();
12898 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12901 *num_overrides = 0;
12904 MonoReflectionEvent *
12905 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12907 g_assert_not_reached ();
12911 MonoReflectionType*
12912 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12914 g_assert_not_reached ();
12919 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12921 g_assert_not_reached ();
12925 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12927 g_assert_not_reached ();
12932 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12934 g_assert_not_reached ();
12939 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12944 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12950 mono_reflection_type_get_handle (MonoReflectionType* ref)
12958 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12960 g_assert_not_reached ();
12963 #endif /* DISABLE_REFLECTION_EMIT */
12965 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12966 const static guint32 declsec_flags_map[] = {
12967 0x00000000, /* empty */
12968 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12969 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12970 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12971 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12972 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12973 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12974 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12975 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12976 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12977 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12978 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12979 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12980 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12981 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12982 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12983 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12984 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12985 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12989 * Returns flags that includes all available security action associated to the handle.
12990 * @token: metadata token (either for a class or a method)
12991 * @image: image where resides the metadata.
12994 mono_declsec_get_flags (MonoImage *image, guint32 token)
12996 int index = mono_metadata_declsec_from_index (image, token);
12997 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12998 guint32 result = 0;
13002 /* HasSecurity can be present for other, not specially encoded, attributes,
13003 e.g. SuppressUnmanagedCodeSecurityAttribute */
13007 for (i = index; i < t->rows; i++) {
13008 guint32 cols [MONO_DECL_SECURITY_SIZE];
13010 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13011 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13014 action = cols [MONO_DECL_SECURITY_ACTION];
13015 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13016 result |= declsec_flags_map [action];
13018 g_assert_not_reached ();
13025 * Get the security actions (in the form of flags) associated with the specified method.
13027 * @method: The method for which we want the declarative security flags.
13028 * Return the declarative security flags for the method (only).
13030 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13031 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13034 mono_declsec_flags_from_method (MonoMethod *method)
13036 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13037 /* FIXME: No cache (for the moment) */
13038 guint32 idx = mono_method_get_index (method);
13039 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13040 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13041 return mono_declsec_get_flags (method->klass->image, idx);
13047 * Get the security actions (in the form of flags) associated with the specified class.
13049 * @klass: The class for which we want the declarative security flags.
13050 * Return the declarative security flags for the class.
13052 * Note: We cache the flags inside the MonoClass structure as this will get
13053 * called very often (at least for each method).
13056 mono_declsec_flags_from_class (MonoClass *klass)
13058 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13059 if (!klass->ext || !klass->ext->declsec_flags) {
13062 idx = mono_metadata_token_index (klass->type_token);
13063 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13064 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13065 mono_loader_lock ();
13066 mono_class_alloc_ext (klass);
13067 mono_loader_unlock ();
13068 /* we cache the flags on classes */
13069 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13071 return klass->ext->declsec_flags;
13077 * Get the security actions (in the form of flags) associated with the specified assembly.
13079 * @assembly: The assembly for which we want the declarative security flags.
13080 * Return the declarative security flags for the assembly.
13083 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13085 guint32 idx = 1; /* there is only one assembly */
13086 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13087 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13088 return mono_declsec_get_flags (assembly->image, idx);
13093 * Fill actions for the specific index (which may either be an encoded class token or
13094 * an encoded method token) from the metadata image.
13095 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13098 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13099 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13101 MonoBoolean result = FALSE;
13103 guint32 cols [MONO_DECL_SECURITY_SIZE];
13104 int index = mono_metadata_declsec_from_index (image, token);
13107 t = &image->tables [MONO_TABLE_DECLSECURITY];
13108 for (i = index; i < t->rows; i++) {
13109 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13111 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13114 /* if present only replace (class) permissions with method permissions */
13115 /* if empty accept either class or method permissions */
13116 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13117 if (!actions->demand.blob) {
13118 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13119 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13120 actions->demand.blob = (char*) (blob + 2);
13121 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13124 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13125 if (!actions->noncasdemand.blob) {
13126 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13127 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13128 actions->noncasdemand.blob = (char*) (blob + 2);
13129 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13132 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13133 if (!actions->demandchoice.blob) {
13134 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13135 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13136 actions->demandchoice.blob = (char*) (blob + 2);
13137 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13147 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13148 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13150 guint32 idx = mono_metadata_token_index (klass->type_token);
13151 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13152 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13153 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13157 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13158 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13160 guint32 idx = mono_method_get_index (method);
13161 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13162 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13163 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13167 * Collect all actions (that requires to generate code in mini) assigned for
13168 * the specified method.
13169 * Note: Don't use the content of actions if the function return FALSE.
13172 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13174 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13175 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13176 MonoBoolean result = FALSE;
13179 /* quick exit if no declarative security is present in the metadata */
13180 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13183 /* we want the original as the wrapper is "free" of the security informations */
13184 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13185 method = mono_marshal_method_from_wrapper (method);
13190 /* First we look for method-level attributes */
13191 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13192 mono_class_init (method->klass);
13193 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13195 result = mono_declsec_get_method_demands_params (method, demands,
13196 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13199 /* Here we use (or create) the class declarative cache to look for demands */
13200 flags = mono_declsec_flags_from_class (method->klass);
13201 if (flags & mask) {
13203 mono_class_init (method->klass);
13204 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13206 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13207 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13210 /* The boolean return value is used as a shortcut in case nothing needs to
13211 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13217 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13219 * Note: Don't use the content of actions if the function return FALSE.
13222 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13224 MonoBoolean result = FALSE;
13227 /* quick exit if no declarative security is present in the metadata */
13228 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13231 /* we want the original as the wrapper is "free" of the security informations */
13232 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13233 method = mono_marshal_method_from_wrapper (method);
13238 /* results are independant - zeroize both */
13239 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13240 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13242 /* First we look for method-level attributes */
13243 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13244 mono_class_init (method->klass);
13246 result = mono_declsec_get_method_demands_params (method, cmethod,
13247 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13250 /* Here we use (or create) the class declarative cache to look for demands */
13251 flags = mono_declsec_flags_from_class (method->klass);
13252 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13253 mono_class_init (method->klass);
13255 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13256 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13263 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13265 * @klass The inherited class - this is the class that provides the security check (attributes)
13267 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13269 * Note: Don't use the content of actions if the function return FALSE.
13272 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13274 MonoBoolean result = FALSE;
13277 /* quick exit if no declarative security is present in the metadata */
13278 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13281 /* Here we use (or create) the class declarative cache to look for demands */
13282 flags = mono_declsec_flags_from_class (klass);
13283 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13284 mono_class_init (klass);
13285 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13287 result |= mono_declsec_get_class_demands_params (klass, demands,
13288 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13295 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13297 * Note: Don't use the content of actions if the function return FALSE.
13300 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13302 /* quick exit if no declarative security is present in the metadata */
13303 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13306 /* we want the original as the wrapper is "free" of the security informations */
13307 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13308 method = mono_marshal_method_from_wrapper (method);
13313 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13314 mono_class_init (method->klass);
13315 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13317 return mono_declsec_get_method_demands_params (method, demands,
13318 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13325 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13327 guint32 cols [MONO_DECL_SECURITY_SIZE];
13331 int index = mono_metadata_declsec_from_index (image, token);
13335 t = &image->tables [MONO_TABLE_DECLSECURITY];
13336 for (i = index; i < t->rows; i++) {
13337 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13339 /* shortcut - index are ordered */
13340 if (token != cols [MONO_DECL_SECURITY_PARENT])
13343 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13344 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13345 entry->blob = (char*) (metadata + 2);
13346 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13355 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13357 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13358 guint32 idx = mono_method_get_index (method);
13359 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13360 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13361 return get_declsec_action (method->klass->image, idx, action, entry);
13367 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13370 guint32 flags = mono_declsec_flags_from_class (klass);
13371 if (declsec_flags_map [action] & flags) {
13372 guint32 idx = mono_metadata_token_index (klass->type_token);
13373 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13374 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13375 return get_declsec_action (klass->image, idx, action, entry);
13381 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13383 guint32 idx = 1; /* there is only one assembly */
13384 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13385 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13387 return get_declsec_action (assembly->image, idx, action, entry);
13391 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13394 MonoObject *res, *exc;
13396 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13397 static MonoMethod *method = NULL;
13399 if (!System_Reflection_Emit_TypeBuilder) {
13400 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13401 g_assert (System_Reflection_Emit_TypeBuilder);
13403 if (method == NULL) {
13404 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13409 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13410 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13412 g_assert (mono_class_get_ref_info (klass));
13413 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13415 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13416 mono_error_raise_exception (&error); /* FIXME don't raise here */
13418 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13422 return *(MonoBoolean*)mono_object_unbox (res);
13426 * mono_reflection_type_get_type:
13427 * @reftype: the System.Type object
13429 * Returns the MonoType* associated with the C# System.Type object @reftype.
13432 mono_reflection_type_get_type (MonoReflectionType *reftype)
13434 g_assert (reftype);
13436 return mono_reflection_type_get_handle (reftype);
13440 * mono_reflection_assembly_get_assembly:
13441 * @refassembly: the System.Reflection.Assembly object
13443 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13446 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13448 g_assert (refassembly);
13450 return refassembly->assembly;