2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
226 dynamic_images_lock (void)
228 mono_os_mutex_lock (&dynamic_images_mutex);
232 dynamic_images_unlock (void)
234 mono_os_mutex_unlock (&dynamic_images_mutex);
238 * mono_find_dynamic_image_owner:
240 * Find the dynamic image, if any, which a given pointer is located in the memory of.
243 mono_find_dynamic_image_owner (void *ptr)
245 MonoImage *owner = NULL;
248 dynamic_images_lock ();
252 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254 if (mono_mempool_contains_addr (image->mempool, ptr))
259 dynamic_images_unlock ();
265 mono_reflection_init (void)
267 mono_os_mutex_init (&dynamic_images_mutex);
271 dynamic_image_lock (MonoDynamicImage *image)
273 MONO_PREPARE_BLOCKING;
274 mono_image_lock ((MonoImage*)image);
275 MONO_FINISH_BLOCKING;
279 dynamic_image_unlock (MonoDynamicImage *image)
281 mono_image_unlock ((MonoImage*)image);
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
287 MONO_REQ_GC_UNSAFE_MODE;
289 dynamic_image_lock (assembly);
290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291 dynamic_image_unlock (assembly);
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
297 MONO_REQ_GC_UNSAFE_MODE;
301 dynamic_image_lock (assembly);
302 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303 dynamic_image_unlock (assembly);
309 sigbuffer_init (SigBuffer *buf, int size)
311 MONO_REQ_GC_NEUTRAL_MODE;
313 buf->buf = (char *)g_malloc (size);
315 buf->end = buf->buf + size;
319 sigbuffer_make_room (SigBuffer *buf, int size)
321 MONO_REQ_GC_NEUTRAL_MODE;
323 if (buf->end - buf->p < size) {
324 int new_size = buf->end - buf->buf + size + 32;
325 char *p = (char *)g_realloc (buf->buf, new_size);
326 size = buf->p - buf->buf;
329 buf->end = buf->buf + new_size;
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
336 MONO_REQ_GC_NEUTRAL_MODE;
338 sigbuffer_make_room (buf, 6);
339 mono_metadata_encode_value (val, buf->p, &buf->p);
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 sigbuffer_make_room (buf, 1);
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
355 MONO_REQ_GC_NEUTRAL_MODE;
357 sigbuffer_make_room (buf, size);
358 memcpy (buf->p, p, size);
363 sigbuffer_free (SigBuffer *buf)
365 MONO_REQ_GC_NEUTRAL_MODE;
370 #ifndef DISABLE_REFLECTION_EMIT
374 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
378 image_g_malloc (MonoImage *image, guint size)
380 MONO_REQ_GC_NEUTRAL_MODE;
383 return mono_image_alloc (image, size);
385 return g_malloc (size);
387 #endif /* !DISABLE_REFLECTION_EMIT */
392 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 image_g_malloc0 (MonoImage *image, guint size)
398 MONO_REQ_GC_NEUTRAL_MODE;
401 return mono_image_alloc0 (image, size);
403 return g_malloc0 (size);
406 #ifndef DISABLE_REFLECTION_EMIT
408 image_strdup (MonoImage *image, const char *s)
410 MONO_REQ_GC_NEUTRAL_MODE;
413 return mono_image_strdup (image, s);
419 #define image_g_new(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
422 #define image_g_new0(image,struct_type, n_structs) \
423 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
427 alloc_table (MonoDynamicTable *table, guint nrows)
429 MONO_REQ_GC_NEUTRAL_MODE;
432 g_assert (table->columns);
433 if (nrows + 1 >= table->alloc_rows) {
434 while (nrows + 1 >= table->alloc_rows) {
435 if (table->alloc_rows == 0)
436 table->alloc_rows = 16;
438 table->alloc_rows *= 2;
441 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
446 make_room_in_stream (MonoDynamicStream *stream, int size)
448 MONO_REQ_GC_NEUTRAL_MODE;
450 if (size <= stream->alloc_size)
453 while (stream->alloc_size <= size) {
454 if (stream->alloc_size < 4096)
455 stream->alloc_size = 4096;
457 stream->alloc_size *= 2;
460 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
466 MONO_REQ_GC_NEUTRAL_MODE;
470 gpointer oldkey, oldval;
472 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473 return GPOINTER_TO_UINT (oldval);
475 len = strlen (str) + 1;
478 make_room_in_stream (sh, idx + len);
481 * We strdup the string even if we already copy them in sh->data
482 * so that the string pointers in the hash remain valid even if
483 * we need to realloc sh->data. We may want to avoid that later.
485 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486 memcpy (sh->data + idx, str, len);
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
494 MONO_REQ_GC_UNSAFE_MODE;
496 char *name = mono_string_to_utf8 (str);
498 idx = string_heap_insert (sh, name);
503 #ifndef DISABLE_REFLECTION_EMIT
505 string_heap_init (MonoDynamicStream *sh)
507 MONO_REQ_GC_NEUTRAL_MODE;
510 sh->alloc_size = 4096;
511 sh->data = (char *)g_malloc (4096);
512 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513 string_heap_insert (sh, "");
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 make_room_in_stream (stream, stream->index + len);
525 memcpy (stream->data + stream->index, data, len);
527 stream->index += len;
529 * align index? Not without adding an additional param that controls it since
530 * we may store a blob value in pieces.
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
538 MONO_REQ_GC_NEUTRAL_MODE;
542 make_room_in_stream (stream, stream->index + len);
543 memset (stream->data + stream->index, 0, len);
545 stream->index += len;
550 stream_data_align (MonoDynamicStream *stream)
552 MONO_REQ_GC_NEUTRAL_MODE;
555 guint32 count = stream->index % 4;
557 /* we assume the stream data will be aligned */
559 mono_image_add_stream_data (stream, buf, 4 - count);
562 #ifndef DISABLE_REFLECTION_EMIT
564 mono_blob_entry_hash (const char* str)
566 MONO_REQ_GC_NEUTRAL_MODE;
570 len = mono_metadata_decode_blob_size (str, &str);
574 for (str += 1; str < end; str++)
575 h = (h << 5) - h + *str;
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584 MONO_REQ_GC_NEUTRAL_MODE;
589 len = mono_metadata_decode_blob_size (str1, &end1);
590 len2 = mono_metadata_decode_blob_size (str2, &end2);
593 return memcmp (end1, end2, len) == 0;
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
599 MONO_REQ_GC_NEUTRAL_MODE;
603 gpointer oldkey, oldval;
605 copy = (char *)g_malloc (s1+s2);
606 memcpy (copy, b1, s1);
607 memcpy (copy + s1, b2, s2);
608 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
610 idx = GPOINTER_TO_UINT (oldval);
612 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613 mono_image_add_stream_data (&assembly->blob, b2, s2);
614 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
622 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 size = buf->p - buf->buf;
628 g_assert (size <= (buf->end - buf->buf));
629 mono_metadata_encode_value (size, b, &b);
630 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
634 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635 * dest may be misaligned.
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639 MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
643 for (elem = 0; elem < nelem; ++elem) {
669 g_assert_not_reached ();
675 memcpy (dest, val, len * nelem);
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
682 MONO_REQ_GC_UNSAFE_MODE;
686 guint32 idx = 0, len;
688 len = str->length * 2;
689 mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
692 char *swapped = g_malloc (2 * mono_string_length (str));
693 const char *p = (const char*)mono_string_chars (str);
695 swap_with_size (swapped, p, 2, mono_string_length (str));
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
700 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
705 #ifndef DISABLE_REFLECTION_EMIT
707 default_class_from_mono_type (MonoType *type)
709 MONO_REQ_GC_NEUTRAL_MODE;
711 switch (type->type) {
712 case MONO_TYPE_OBJECT:
713 return mono_defaults.object_class;
715 return mono_defaults.void_class;
716 case MONO_TYPE_BOOLEAN:
717 return mono_defaults.boolean_class;
719 return mono_defaults.char_class;
721 return mono_defaults.sbyte_class;
723 return mono_defaults.byte_class;
725 return mono_defaults.int16_class;
727 return mono_defaults.uint16_class;
729 return mono_defaults.int32_class;
731 return mono_defaults.uint32_class;
733 return mono_defaults.int_class;
735 return mono_defaults.uint_class;
737 return mono_defaults.int64_class;
739 return mono_defaults.uint64_class;
741 return mono_defaults.single_class;
743 return mono_defaults.double_class;
744 case MONO_TYPE_STRING:
745 return mono_defaults.string_class;
747 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748 g_assert_not_reached ();
756 * mono_class_get_ref_info:
758 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
761 mono_class_get_ref_info (MonoClass *klass)
763 MONO_REQ_GC_UNSAFE_MODE;
765 if (klass->ref_info_handle == 0)
768 return mono_gchandle_get_target (klass->ref_info_handle);
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
774 MONO_REQ_GC_UNSAFE_MODE;
776 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777 g_assert (klass->ref_info_handle != 0);
781 mono_class_free_ref_info (MonoClass *klass)
783 MONO_REQ_GC_NEUTRAL_MODE;
785 if (klass->ref_info_handle) {
786 mono_gchandle_free (klass->ref_info_handle);
787 klass->ref_info_handle = 0;
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
794 MONO_REQ_GC_NEUTRAL_MODE;
797 MonoGenericInst *class_inst;
802 class_inst = gclass->context.class_inst;
804 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805 klass = gclass->container_class;
806 sigbuffer_add_value (buf, klass->byval_arg.type);
807 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
809 sigbuffer_add_value (buf, class_inst->type_argc);
810 for (i = 0; i < class_inst->type_argc; ++i)
811 encode_type (assembly, class_inst->type_argv [i], buf);
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
818 MONO_REQ_GC_NEUTRAL_MODE;
821 g_assert_not_reached ();
826 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
830 case MONO_TYPE_BOOLEAN:
844 case MONO_TYPE_STRING:
845 case MONO_TYPE_OBJECT:
846 case MONO_TYPE_TYPEDBYREF:
847 sigbuffer_add_value (buf, type->type);
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, type->data.type, buf);
853 case MONO_TYPE_SZARRAY:
854 sigbuffer_add_value (buf, type->type);
855 encode_type (assembly, &type->data.klass->byval_arg, buf);
857 case MONO_TYPE_VALUETYPE:
858 case MONO_TYPE_CLASS: {
859 MonoClass *k = mono_class_from_mono_type (type);
861 if (k->generic_container) {
862 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863 encode_generic_class (assembly, gclass, buf);
866 * Make sure we use the correct type.
868 sigbuffer_add_value (buf, k->byval_arg.type);
870 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871 * otherwise two typerefs could point to the same type, leading to
872 * verification errors.
874 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
878 case MONO_TYPE_ARRAY:
879 sigbuffer_add_value (buf, type->type);
880 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881 sigbuffer_add_value (buf, type->data.array->rank);
882 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883 sigbuffer_add_value (buf, 0);
885 case MONO_TYPE_GENERICINST:
886 encode_generic_class (assembly, type->data.generic_class, buf);
890 sigbuffer_add_value (buf, type->type);
891 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
894 g_error ("need to encode type %x", type->type);
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
901 MONO_REQ_GC_UNSAFE_MODE;
904 sigbuffer_add_value (buf, MONO_TYPE_VOID);
908 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
914 MONO_REQ_GC_UNSAFE_MODE;
919 for (i = 0; i < mono_array_length (modreq); ++i) {
920 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926 for (i = 0; i < mono_array_length (modopt); ++i) {
927 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
934 #ifndef DISABLE_REFLECTION_EMIT
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
938 MONO_REQ_GC_UNSAFE_MODE;
942 guint32 nparams = sig->param_count;
948 sigbuffer_init (&buf, 32);
950 * FIXME: vararg, explicit_this, differenc call_conv values...
952 idx = sig->call_convention;
954 idx |= 0x20; /* hasthis */
955 if (sig->generic_param_count)
956 idx |= 0x10; /* generic */
957 sigbuffer_add_byte (&buf, idx);
958 if (sig->generic_param_count)
959 sigbuffer_add_value (&buf, sig->generic_param_count);
960 sigbuffer_add_value (&buf, nparams);
961 encode_type (assembly, sig->ret, &buf);
962 for (i = 0; i < nparams; ++i) {
963 if (i == sig->sentinelpos)
964 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965 encode_type (assembly, sig->params [i], &buf);
967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968 sigbuffer_free (&buf);
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
976 MONO_REQ_GC_UNSAFE_MODE;
979 * FIXME: reuse code from method_encode_signature().
983 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
984 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
988 sigbuffer_init (&buf, 32);
989 /* LAMESPEC: all the call conv spec is foobared */
990 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991 if (mb->call_conv & 2)
992 idx |= 0x5; /* vararg */
993 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994 idx |= 0x20; /* hasthis */
996 idx |= 0x10; /* generic */
997 sigbuffer_add_byte (&buf, idx);
999 sigbuffer_add_value (&buf, ngparams);
1000 sigbuffer_add_value (&buf, nparams + notypes);
1001 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002 encode_reflection_type (assembly, mb->rtype, &buf);
1003 for (i = 0; i < nparams; ++i) {
1004 MonoArray *modreq = NULL;
1005 MonoArray *modopt = NULL;
1006 MonoReflectionType *pt;
1008 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014 encode_reflection_type (assembly, pt, &buf);
1017 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018 for (i = 0; i < notypes; ++i) {
1019 MonoReflectionType *pt;
1021 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022 encode_reflection_type (assembly, pt, &buf);
1025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026 sigbuffer_free (&buf);
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1033 MONO_REQ_GC_UNSAFE_MODE;
1035 MonoDynamicTable *table;
1037 guint32 idx, sig_idx;
1038 guint nl = mono_array_length (ilgen->locals);
1042 sigbuffer_init (&buf, 32);
1043 sigbuffer_add_value (&buf, 0x07);
1044 sigbuffer_add_value (&buf, nl);
1045 for (i = 0; i < nl; ++i) {
1046 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1049 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1051 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1053 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1056 if (assembly->standalonesig_cache == NULL)
1057 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1062 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063 idx = table->next_idx ++;
1065 alloc_table (table, table->rows);
1066 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1068 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1070 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1078 MONO_REQ_GC_UNSAFE_MODE;
1080 guint32 num_clauses = 0;
1083 MonoILExceptionInfo *ex_info;
1084 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086 if (ex_info->handlers)
1087 num_clauses += mono_array_length (ex_info->handlers);
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 MonoExceptionClause *clauses;
1102 MonoExceptionClause *clause;
1103 MonoILExceptionInfo *ex_info;
1104 MonoILExceptionBlock *ex_block;
1105 guint32 finally_start;
1106 int i, j, clause_index;;
1108 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1111 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113 finally_start = ex_info->start + ex_info->len;
1114 if (!ex_info->handlers)
1116 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118 clause = &(clauses [clause_index]);
1120 clause->flags = ex_block->type;
1121 clause->try_offset = ex_info->start;
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124 clause->try_len = finally_start - ex_info->start;
1126 clause->try_len = ex_info->len;
1127 clause->handler_offset = ex_block->start;
1128 clause->handler_len = ex_block->len;
1129 if (ex_block->extype) {
1130 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1132 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133 clause->data.filter_offset = ex_block->filter_offset;
1135 clause->data.filter_offset = 0;
1137 finally_start = ex_block->start + ex_block->len;
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1148 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1150 MONO_REQ_GC_UNSAFE_MODE;
1155 gint32 max_stack, i;
1156 gint32 num_locals = 0;
1157 gint32 num_exception = 0;
1160 char fat_header [12];
1162 guint16 short_value;
1163 guint32 local_sig = 0;
1164 guint32 header_size = 12;
1167 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1168 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1172 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1174 code = mb->ilgen->code;
1175 code_size = mb->ilgen->code_len;
1176 max_stack = mb->ilgen->max_stack;
1177 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1178 if (mb->ilgen->ex_handlers)
1179 num_exception = method_count_clauses (mb->ilgen);
1183 char *name = mono_string_to_utf8 (mb->name);
1184 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1185 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1188 mono_raise_exception (exception);
1191 code_size = mono_array_length (code);
1192 max_stack = 8; /* we probably need to run a verifier on the code... */
1195 stream_data_align (&assembly->code);
1197 /* check for exceptions, maxstack, locals */
1198 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1200 if (code_size < 64 && !(code_size & 1)) {
1201 flags = (code_size << 2) | 0x2;
1202 } else if (code_size < 32 && (code_size & 1)) {
1203 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1207 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1208 /* add to the fixup todo list */
1209 if (mb->ilgen && mb->ilgen->num_token_fixups)
1210 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1211 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1212 return assembly->text_rva + idx;
1216 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1218 * FIXME: need to set also the header size in fat_flags.
1219 * (and more sects and init locals flags)
1223 fat_flags |= METHOD_HEADER_MORE_SECTS;
1224 if (mb->init_locals)
1225 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1226 fat_header [0] = fat_flags;
1227 fat_header [1] = (header_size / 4 ) << 4;
1228 short_value = GUINT16_TO_LE (max_stack);
1229 memcpy (fat_header + 2, &short_value, 2);
1230 int_value = GUINT32_TO_LE (code_size);
1231 memcpy (fat_header + 4, &int_value, 4);
1232 int_value = GUINT32_TO_LE (local_sig);
1233 memcpy (fat_header + 8, &int_value, 4);
1234 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1235 /* add to the fixup todo list */
1236 if (mb->ilgen && mb->ilgen->num_token_fixups)
1237 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1239 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1240 if (num_exception) {
1241 unsigned char sheader [4];
1242 MonoILExceptionInfo * ex_info;
1243 MonoILExceptionBlock * ex_block;
1246 stream_data_align (&assembly->code);
1247 /* always use fat format for now */
1248 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1249 num_exception *= 6 * sizeof (guint32);
1250 num_exception += 4; /* include the size of the header */
1251 sheader [1] = num_exception & 0xff;
1252 sheader [2] = (num_exception >> 8) & 0xff;
1253 sheader [3] = (num_exception >> 16) & 0xff;
1254 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1255 /* fat header, so we are already aligned */
1257 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1258 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1259 if (ex_info->handlers) {
1260 int finally_start = ex_info->start + ex_info->len;
1261 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1263 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1265 val = GUINT32_TO_LE (ex_block->type);
1266 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1268 val = GUINT32_TO_LE (ex_info->start);
1269 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1270 /* need fault, too, probably */
1271 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1272 val = GUINT32_TO_LE (finally_start - ex_info->start);
1274 val = GUINT32_TO_LE (ex_info->len);
1275 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276 /* handler offset */
1277 val = GUINT32_TO_LE (ex_block->start);
1278 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1280 val = GUINT32_TO_LE (ex_block->len);
1281 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1282 finally_start = ex_block->start + ex_block->len;
1283 if (ex_block->extype) {
1284 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1286 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1287 val = ex_block->filter_offset;
1291 val = GUINT32_TO_LE (val);
1292 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1294 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1297 g_error ("No clauses for ex info block %d", i);
1301 return assembly->text_rva + idx;
1305 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1307 MONO_REQ_GC_NEUTRAL_MODE;
1310 MonoDynamicTable *table;
1313 table = &assembly->tables [table_idx];
1315 g_assert (col < table->columns);
1317 values = table->values + table->columns;
1318 for (i = 1; i <= table->rows; ++i) {
1319 if (values [col] == token)
1321 values += table->columns;
1327 * LOCKING: Acquires the loader lock.
1329 static MonoCustomAttrInfo*
1330 lookup_custom_attr (MonoImage *image, gpointer member)
1332 MONO_REQ_GC_NEUTRAL_MODE;
1334 MonoCustomAttrInfo* res;
1336 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1341 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1347 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1349 MONO_REQ_GC_UNSAFE_MODE;
1351 /* FIXME: Need to do more checks */
1352 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1353 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1355 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1362 static MonoCustomAttrInfo*
1363 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1365 MONO_REQ_GC_UNSAFE_MODE;
1367 int i, index, count, not_visible;
1368 MonoCustomAttrInfo *ainfo;
1369 MonoReflectionCustomAttr *cattr;
1373 /* FIXME: check in assembly the Run flag is set */
1375 count = mono_array_length (cattrs);
1377 /* Skip nonpublic attributes since MS.NET seems to do the same */
1378 /* FIXME: This needs to be done more globally */
1380 for (i = 0; i < count; ++i) {
1381 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1382 if (!custom_attr_visible (image, cattr))
1385 count -= not_visible;
1387 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1389 ainfo->image = image;
1390 ainfo->num_attrs = count;
1391 ainfo->cached = alloc_img != NULL;
1393 for (i = 0; i < count; ++i) {
1394 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1395 if (custom_attr_visible (image, cattr)) {
1396 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1397 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1398 ainfo->attrs [index].ctor = cattr->ctor->method;
1399 ainfo->attrs [index].data = saved;
1400 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1408 #ifndef DISABLE_REFLECTION_EMIT
1410 * LOCKING: Acquires the loader lock.
1413 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1415 MONO_REQ_GC_UNSAFE_MODE;
1417 MonoCustomAttrInfo *ainfo, *tmp;
1419 if (!cattrs || !mono_array_length (cattrs))
1422 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1424 mono_loader_lock ();
1425 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1427 mono_custom_attrs_free (tmp);
1428 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1429 mono_loader_unlock ();
1435 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1437 MONO_REQ_GC_NEUTRAL_MODE;
1444 * idx is the table index of the object
1445 * type is one of MONO_CUSTOM_ATTR_*
1448 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1450 MONO_REQ_GC_UNSAFE_MODE;
1452 MonoDynamicTable *table;
1453 MonoReflectionCustomAttr *cattr;
1455 guint32 count, i, token;
1457 char *p = blob_size;
1459 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1462 count = mono_array_length (cattrs);
1463 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1464 table->rows += count;
1465 alloc_table (table, table->rows);
1466 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1467 idx <<= MONO_CUSTOM_ATTR_BITS;
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1472 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1473 type = mono_metadata_token_index (token);
1474 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1475 switch (mono_metadata_token_table (token)) {
1476 case MONO_TABLE_METHOD:
1477 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1479 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1480 * method, not the one returned by mono_image_create_token ().
1482 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1484 case MONO_TABLE_MEMBERREF:
1485 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1488 g_warning ("got wrong token in custom attr");
1491 values [MONO_CUSTOM_ATTR_TYPE] = type;
1493 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1494 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1495 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1496 values += MONO_CUSTOM_ATTR_SIZE;
1502 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoDynamicTable *table;
1508 guint32 count, i, idx;
1509 MonoReflectionPermissionSet *perm;
1514 count = mono_array_length (permissions);
1515 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1516 table->rows += count;
1517 alloc_table (table, table->rows);
1519 for (i = 0; i < mono_array_length (permissions); ++i) {
1520 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1522 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1524 idx = mono_metadata_token_index (parent_token);
1525 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1526 switch (mono_metadata_token_table (parent_token)) {
1527 case MONO_TABLE_TYPEDEF:
1528 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1530 case MONO_TABLE_METHOD:
1531 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1533 case MONO_TABLE_ASSEMBLY:
1534 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1537 g_assert_not_reached ();
1540 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1541 values [MONO_DECL_SECURITY_PARENT] = idx;
1542 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1549 * Fill in the MethodDef and ParamDef tables for a method.
1550 * This is used for both normal methods and constructors.
1553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1555 MONO_REQ_GC_UNSAFE_MODE;
1557 MonoDynamicTable *table;
1561 /* room in this table is already allocated */
1562 table = &assembly->tables [MONO_TABLE_METHOD];
1563 *mb->table_idx = table->next_idx ++;
1564 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1565 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1566 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1567 values [MONO_METHOD_FLAGS] = mb->attrs;
1568 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1569 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1570 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1572 table = &assembly->tables [MONO_TABLE_PARAM];
1573 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1575 mono_image_add_decl_security (assembly,
1576 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1579 MonoDynamicTable *mtable;
1582 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1583 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1586 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1587 if (mono_array_get (mb->pinfo, gpointer, i))
1590 table->rows += count;
1591 alloc_table (table, table->rows);
1592 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1593 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1594 MonoReflectionParamBuilder *pb;
1595 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1596 values [MONO_PARAM_FLAGS] = pb->attrs;
1597 values [MONO_PARAM_SEQUENCE] = i;
1598 if (pb->name != NULL) {
1599 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1601 values [MONO_PARAM_NAME] = 0;
1603 values += MONO_PARAM_SIZE;
1604 if (pb->marshal_info) {
1606 alloc_table (mtable, mtable->rows);
1607 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1608 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1609 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1611 pb->table_idx = table->next_idx++;
1612 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1613 guint32 field_type = 0;
1614 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1616 alloc_table (mtable, mtable->rows);
1617 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1618 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1619 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1620 mvalues [MONO_CONSTANT_TYPE] = field_type;
1621 mvalues [MONO_CONSTANT_PADDING] = 0;
1628 #ifndef DISABLE_REFLECTION_EMIT
1630 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1633 MONO_REQ_GC_UNSAFE_MODE;
1635 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1637 rmb->ilgen = mb->ilgen;
1638 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1639 mono_error_raise_exception (&error); /* FIXME don't raise here */
1640 rmb->parameters = mb->parameters;
1641 rmb->generic_params = mb->generic_params;
1642 rmb->generic_container = mb->generic_container;
1643 rmb->opt_types = NULL;
1644 rmb->pinfo = mb->pinfo;
1645 rmb->attrs = mb->attrs;
1646 rmb->iattrs = mb->iattrs;
1647 rmb->call_conv = mb->call_conv;
1648 rmb->code = mb->code;
1649 rmb->type = mb->type;
1650 rmb->name = mb->name;
1651 rmb->table_idx = &mb->table_idx;
1652 rmb->init_locals = mb->init_locals;
1653 rmb->skip_visibility = FALSE;
1654 rmb->return_modreq = mb->return_modreq;
1655 rmb->return_modopt = mb->return_modopt;
1656 rmb->param_modreq = mb->param_modreq;
1657 rmb->param_modopt = mb->param_modopt;
1658 rmb->permissions = mb->permissions;
1659 rmb->mhandle = mb->mhandle;
1664 rmb->charset = mb->charset;
1665 rmb->extra_flags = mb->extra_flags;
1666 rmb->native_cc = mb->native_cc;
1667 rmb->dllentry = mb->dllentry;
1673 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1675 MONO_REQ_GC_UNSAFE_MODE;
1678 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1680 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682 rmb->ilgen = mb->ilgen;
1683 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1684 mono_error_raise_exception (&error); /* FIXME don't raise here */
1685 rmb->parameters = mb->parameters;
1686 rmb->generic_params = NULL;
1687 rmb->generic_container = NULL;
1688 rmb->opt_types = NULL;
1689 rmb->pinfo = mb->pinfo;
1690 rmb->attrs = mb->attrs;
1691 rmb->iattrs = mb->iattrs;
1692 rmb->call_conv = mb->call_conv;
1694 rmb->type = mb->type;
1695 rmb->name = mono_string_new (mono_domain_get (), name);
1696 rmb->table_idx = &mb->table_idx;
1697 rmb->init_locals = mb->init_locals;
1698 rmb->skip_visibility = FALSE;
1699 rmb->return_modreq = NULL;
1700 rmb->return_modopt = NULL;
1701 rmb->param_modreq = mb->param_modreq;
1702 rmb->param_modopt = mb->param_modopt;
1703 rmb->permissions = mb->permissions;
1704 rmb->mhandle = mb->mhandle;
1710 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1712 MONO_REQ_GC_UNSAFE_MODE;
1714 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1716 rmb->ilgen = mb->ilgen;
1717 rmb->rtype = mb->rtype;
1718 rmb->parameters = mb->parameters;
1719 rmb->generic_params = NULL;
1720 rmb->generic_container = NULL;
1721 rmb->opt_types = NULL;
1723 rmb->attrs = mb->attrs;
1725 rmb->call_conv = mb->call_conv;
1727 rmb->type = (MonoObject *) mb->owner;
1728 rmb->name = mb->name;
1729 rmb->table_idx = NULL;
1730 rmb->init_locals = mb->init_locals;
1731 rmb->skip_visibility = mb->skip_visibility;
1732 rmb->return_modreq = NULL;
1733 rmb->return_modopt = NULL;
1734 rmb->param_modreq = NULL;
1735 rmb->param_modopt = NULL;
1736 rmb->permissions = NULL;
1737 rmb->mhandle = mb->mhandle;
1744 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1746 MONO_REQ_GC_UNSAFE_MODE;
1748 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1749 MonoDynamicTable *table;
1752 MonoReflectionMethod *m;
1755 if (!mb->override_methods)
1758 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1759 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1761 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1763 alloc_table (table, table->rows);
1764 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1765 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1766 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1768 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1769 switch (mono_metadata_token_table (tok)) {
1770 case MONO_TABLE_MEMBERREF:
1771 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1773 case MONO_TABLE_METHOD:
1774 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1777 g_assert_not_reached ();
1779 values [MONO_METHODIMPL_DECLARATION] = tok;
1783 #ifndef DISABLE_REFLECTION_EMIT
1785 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1787 MONO_REQ_GC_UNSAFE_MODE;
1789 MonoDynamicTable *table;
1791 ReflectionMethodBuilder rmb;
1794 reflection_methodbuilder_from_method_builder (&rmb, mb);
1796 mono_image_basic_method (&rmb, assembly);
1797 mb->table_idx = *rmb.table_idx;
1799 if (mb->dll) { /* It's a P/Invoke method */
1801 /* map CharSet values to on-disk values */
1802 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1803 int extra_flags = mb->extra_flags;
1804 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1806 alloc_table (table, table->rows);
1807 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1809 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1810 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1812 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1814 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1815 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1816 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1817 table = &assembly->tables [MONO_TABLE_MODULEREF];
1819 alloc_table (table, table->rows);
1820 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1821 values [MONO_IMPLMAP_SCOPE] = table->rows;
1825 if (mb->generic_params) {
1826 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1827 table->rows += mono_array_length (mb->generic_params);
1828 alloc_table (table, table->rows);
1829 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1830 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1832 mono_image_get_generic_param_info (
1833 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1840 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1842 MONO_REQ_GC_UNSAFE_MODE;
1844 ReflectionMethodBuilder rmb;
1846 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1848 mono_image_basic_method (&rmb, assembly);
1849 mb->table_idx = *rmb.table_idx;
1854 type_get_fully_qualified_name (MonoType *type)
1856 MONO_REQ_GC_NEUTRAL_MODE;
1858 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1862 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1864 MONO_REQ_GC_UNSAFE_MODE;
1869 klass = mono_class_from_mono_type (type);
1871 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872 ta = klass->image->assembly;
1873 if (assembly_is_dynamic (ta) || (ta == ass)) {
1874 if (klass->generic_class || klass->generic_container)
1875 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1876 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1878 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1881 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1884 #ifndef DISABLE_REFLECTION_EMIT
1885 /*field_image is the image to which the eventual custom mods have been encoded against*/
1887 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1889 MONO_REQ_GC_NEUTRAL_MODE;
1892 guint32 idx, i, token;
1894 if (!assembly->save)
1897 sigbuffer_init (&buf, 32);
1899 sigbuffer_add_value (&buf, 0x06);
1900 /* encode custom attributes before the type */
1901 if (type->num_mods) {
1902 for (i = 0; i < type->num_mods; ++i) {
1905 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1906 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1908 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1910 token = type->modifiers [i].token;
1913 if (type->modifiers [i].required)
1914 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1916 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1918 sigbuffer_add_value (&buf, token);
1921 encode_type (assembly, type, &buf);
1922 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1923 sigbuffer_free (&buf);
1929 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1931 MONO_REQ_GC_UNSAFE_MODE;
1935 guint32 typespec = 0;
1939 init_type_builder_generics (fb->type);
1941 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1942 klass = mono_class_from_mono_type (type);
1944 sigbuffer_init (&buf, 32);
1946 sigbuffer_add_value (&buf, 0x06);
1947 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1948 /* encode custom attributes before the type */
1950 if (klass->generic_container)
1951 typespec = create_typespec (assembly, type);
1954 MonoGenericClass *gclass;
1955 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1956 encode_generic_class (assembly, gclass, &buf);
1958 encode_type (assembly, type, &buf);
1960 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961 sigbuffer_free (&buf);
1966 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1968 MONO_REQ_GC_UNSAFE_MODE;
1970 char blob_size [64];
1971 char *b = blob_size;
1974 guint32 idx = 0, len = 0, dummy = 0;
1976 buf = (char *)g_malloc (64);
1978 *ret_type = MONO_TYPE_CLASS;
1980 box_val = (char*)&dummy;
1982 box_val = ((char*)val) + sizeof (MonoObject);
1983 *ret_type = val->vtable->klass->byval_arg.type;
1986 switch (*ret_type) {
1987 case MONO_TYPE_BOOLEAN:
1992 case MONO_TYPE_CHAR:
2009 case MONO_TYPE_VALUETYPE: {
2010 MonoClass *klass = val->vtable->klass;
2012 if (klass->enumtype) {
2013 *ret_type = mono_class_enum_basetype (klass)->type;
2015 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2018 g_error ("we can't encode valuetypes, we should have never reached this line");
2021 case MONO_TYPE_CLASS:
2023 case MONO_TYPE_STRING: {
2024 MonoString *str = (MonoString*)val;
2025 /* there is no signature */
2026 len = str->length * 2;
2027 mono_metadata_encode_value (len, b, &b);
2028 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2030 char *swapped = g_malloc (2 * mono_string_length (str));
2031 const char *p = (const char*)mono_string_chars (str);
2033 swap_with_size (swapped, p, 2, mono_string_length (str));
2034 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2038 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2044 case MONO_TYPE_GENERICINST:
2045 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2048 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2051 /* there is no signature */
2052 mono_metadata_encode_value (len, b, &b);
2053 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2054 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2055 swap_with_size (blob_size, box_val, len, 1);
2056 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2058 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2066 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2068 MONO_REQ_GC_UNSAFE_MODE;
2074 sigbuffer_init (&buf, 32);
2076 sigbuffer_add_value (&buf, minfo->type);
2078 switch (minfo->type) {
2079 case MONO_NATIVE_BYVALTSTR:
2080 case MONO_NATIVE_BYVALARRAY:
2081 sigbuffer_add_value (&buf, minfo->count);
2083 case MONO_NATIVE_LPARRAY:
2084 if (minfo->eltype || minfo->has_size) {
2085 sigbuffer_add_value (&buf, minfo->eltype);
2086 if (minfo->has_size) {
2087 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2088 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2090 /* LAMESPEC: ElemMult is undocumented */
2091 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2095 case MONO_NATIVE_SAFEARRAY:
2097 sigbuffer_add_value (&buf, minfo->eltype);
2099 case MONO_NATIVE_CUSTOM:
2101 str = mono_string_to_utf8 (minfo->guid);
2103 sigbuffer_add_value (&buf, len);
2104 sigbuffer_add_mem (&buf, str, len);
2107 sigbuffer_add_value (&buf, 0);
2109 /* native type name */
2110 sigbuffer_add_value (&buf, 0);
2111 /* custom marshaler type name */
2112 if (minfo->marshaltype || minfo->marshaltyperef) {
2113 if (minfo->marshaltyperef)
2114 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2116 str = mono_string_to_utf8 (minfo->marshaltype);
2118 sigbuffer_add_value (&buf, len);
2119 sigbuffer_add_mem (&buf, str, len);
2122 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2123 sigbuffer_add_value (&buf, 0);
2125 if (minfo->mcookie) {
2126 str = mono_string_to_utf8 (minfo->mcookie);
2128 sigbuffer_add_value (&buf, len);
2129 sigbuffer_add_mem (&buf, str, len);
2132 sigbuffer_add_value (&buf, 0);
2138 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2139 sigbuffer_free (&buf);
2144 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2146 MONO_REQ_GC_UNSAFE_MODE;
2148 MonoDynamicTable *table;
2151 /* maybe this fixup should be done in the C# code */
2152 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2153 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2154 table = &assembly->tables [MONO_TABLE_FIELD];
2155 fb->table_idx = table->next_idx ++;
2156 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2157 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2158 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2159 values [MONO_FIELD_FLAGS] = fb->attrs;
2160 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2162 if (fb->offset != -1) {
2163 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2165 alloc_table (table, table->rows);
2166 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2167 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2168 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2170 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2171 MonoTypeEnum field_type = (MonoTypeEnum)0;
2172 table = &assembly->tables [MONO_TABLE_CONSTANT];
2174 alloc_table (table, table->rows);
2175 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2176 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2177 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2178 values [MONO_CONSTANT_TYPE] = field_type;
2179 values [MONO_CONSTANT_PADDING] = 0;
2181 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2183 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2185 alloc_table (table, table->rows);
2186 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2187 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2189 * We store it in the code section because it's simpler for now.
2192 if (mono_array_length (fb->rva_data) >= 10)
2193 stream_data_align (&assembly->code);
2194 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2196 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2197 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2199 if (fb->marshal_info) {
2200 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2202 alloc_table (table, table->rows);
2203 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2204 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2205 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2210 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2212 MONO_REQ_GC_UNSAFE_MODE;
2215 guint32 nparams = 0;
2216 MonoReflectionMethodBuilder *mb = fb->get_method;
2217 MonoReflectionMethodBuilder *smb = fb->set_method;
2220 if (mb && mb->parameters)
2221 nparams = mono_array_length (mb->parameters);
2222 if (!mb && smb && smb->parameters)
2223 nparams = mono_array_length (smb->parameters) - 1;
2224 sigbuffer_init (&buf, 32);
2225 if (fb->call_conv & 0x20)
2226 sigbuffer_add_byte (&buf, 0x28);
2228 sigbuffer_add_byte (&buf, 0x08);
2229 sigbuffer_add_value (&buf, nparams);
2231 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2232 for (i = 0; i < nparams; ++i) {
2233 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2234 encode_reflection_type (assembly, pt, &buf);
2236 } else if (smb && smb->parameters) {
2237 /* the property type is the last param */
2238 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2239 for (i = 0; i < nparams; ++i) {
2240 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2241 encode_reflection_type (assembly, pt, &buf);
2244 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2247 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2248 sigbuffer_free (&buf);
2253 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2255 MONO_REQ_GC_UNSAFE_MODE;
2257 MonoDynamicTable *table;
2259 guint num_methods = 0;
2263 * we need to set things in the following tables:
2264 * PROPERTYMAP (info already filled in _get_type_info ())
2265 * PROPERTY (rows already preallocated in _get_type_info ())
2266 * METHOD (method info already done with the generic method code)
2270 table = &assembly->tables [MONO_TABLE_PROPERTY];
2271 pb->table_idx = table->next_idx ++;
2272 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2273 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2274 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2275 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2277 /* FIXME: we still don't handle 'other' methods */
2278 if (pb->get_method) num_methods ++;
2279 if (pb->set_method) num_methods ++;
2281 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2282 table->rows += num_methods;
2283 alloc_table (table, table->rows);
2285 if (pb->get_method) {
2286 semaidx = table->next_idx ++;
2287 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2289 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2290 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2292 if (pb->set_method) {
2293 semaidx = table->next_idx ++;
2294 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2295 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2296 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2297 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2299 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2300 MonoTypeEnum field_type = (MonoTypeEnum)0;
2301 table = &assembly->tables [MONO_TABLE_CONSTANT];
2303 alloc_table (table, table->rows);
2304 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2305 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2306 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2307 values [MONO_CONSTANT_TYPE] = field_type;
2308 values [MONO_CONSTANT_PADDING] = 0;
2313 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2315 MONO_REQ_GC_UNSAFE_MODE;
2317 MonoDynamicTable *table;
2319 guint num_methods = 0;
2323 * we need to set things in the following tables:
2324 * EVENTMAP (info already filled in _get_type_info ())
2325 * EVENT (rows already preallocated in _get_type_info ())
2326 * METHOD (method info already done with the generic method code)
2329 table = &assembly->tables [MONO_TABLE_EVENT];
2330 eb->table_idx = table->next_idx ++;
2331 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2332 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2333 values [MONO_EVENT_FLAGS] = eb->attrs;
2334 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2337 * FIXME: we still don't handle 'other' methods
2339 if (eb->add_method) num_methods ++;
2340 if (eb->remove_method) num_methods ++;
2341 if (eb->raise_method) num_methods ++;
2343 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2344 table->rows += num_methods;
2345 alloc_table (table, table->rows);
2347 if (eb->add_method) {
2348 semaidx = table->next_idx ++;
2349 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2351 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2352 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2354 if (eb->remove_method) {
2355 semaidx = table->next_idx ++;
2356 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2358 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2359 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2361 if (eb->raise_method) {
2362 semaidx = table->next_idx ++;
2363 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2364 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2365 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2366 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2371 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2373 MONO_REQ_GC_UNSAFE_MODE;
2375 MonoDynamicTable *table;
2376 guint32 num_constraints, i;
2380 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2381 num_constraints = gparam->iface_constraints ?
2382 mono_array_length (gparam->iface_constraints) : 0;
2383 table->rows += num_constraints;
2384 if (gparam->base_type)
2386 alloc_table (table, table->rows);
2388 if (gparam->base_type) {
2389 table_idx = table->next_idx ++;
2390 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2392 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2393 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2394 assembly, mono_reflection_type_get_handle (gparam->base_type));
2397 for (i = 0; i < num_constraints; i++) {
2398 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2399 gparam->iface_constraints, gpointer, i);
2401 table_idx = table->next_idx ++;
2402 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2404 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2405 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2406 assembly, mono_reflection_type_get_handle (constraint));
2411 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2413 MONO_REQ_GC_UNSAFE_MODE;
2415 GenericParamTableEntry *entry;
2418 * The GenericParam table must be sorted according to the `owner' field.
2419 * We need to do this sorting prior to writing the GenericParamConstraint
2420 * table, since we have to use the final GenericParam table indices there
2421 * and they must also be sorted.
2424 entry = g_new0 (GenericParamTableEntry, 1);
2425 entry->owner = owner;
2426 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2427 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2428 entry->gparam = gparam;
2430 g_ptr_array_add (assembly->gen_params, entry);
2434 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2436 MONO_REQ_GC_UNSAFE_MODE;
2438 MonoDynamicTable *table;
2439 MonoGenericParam *param;
2443 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2444 table_idx = table->next_idx ++;
2445 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2447 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2449 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2450 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2451 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2452 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2454 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2456 encode_constraints (entry->gparam, table_idx, assembly);
2460 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2462 MONO_REQ_GC_UNSAFE_MODE;
2464 MonoDynamicTable *table;
2467 guint32 cols [MONO_ASSEMBLY_SIZE];
2471 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2474 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2475 table = &assembly->tables [MONO_TABLE_MODULEREF];
2476 token = table->next_idx ++;
2478 alloc_table (table, table->rows);
2479 values = table->values + token * MONO_MODULEREF_SIZE;
2480 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2482 token <<= MONO_RESOLUTION_SCOPE_BITS;
2483 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2484 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2489 if (assembly_is_dynamic (image->assembly))
2491 memset (cols, 0, sizeof (cols));
2493 /* image->assembly->image is the manifest module */
2494 image = image->assembly->image;
2495 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2498 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2499 token = table->next_idx ++;
2501 alloc_table (table, table->rows);
2502 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2503 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2504 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2505 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2506 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2507 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2508 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2509 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2510 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2512 if (strcmp ("", image->assembly->aname.culture)) {
2513 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2514 image->assembly->aname.culture);
2517 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2518 guchar pubtoken [9];
2520 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2521 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2523 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2525 token <<= MONO_RESOLUTION_SCOPE_BITS;
2526 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2527 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2532 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2534 MONO_REQ_GC_NEUTRAL_MODE;
2536 MonoDynamicTable *table;
2541 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2544 sigbuffer_init (&buf, 32);
2545 switch (type->type) {
2546 case MONO_TYPE_FNPTR:
2548 case MONO_TYPE_SZARRAY:
2549 case MONO_TYPE_ARRAY:
2551 case MONO_TYPE_MVAR:
2552 case MONO_TYPE_GENERICINST:
2553 encode_type (assembly, type, &buf);
2555 case MONO_TYPE_CLASS:
2556 case MONO_TYPE_VALUETYPE: {
2557 MonoClass *k = mono_class_from_mono_type (type);
2558 if (!k || !k->generic_container) {
2559 sigbuffer_free (&buf);
2562 encode_type (assembly, type, &buf);
2566 sigbuffer_free (&buf);
2570 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571 if (assembly->save) {
2572 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573 alloc_table (table, table->rows + 1);
2574 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575 values [MONO_TYPESPEC_SIGNATURE] = token;
2577 sigbuffer_free (&buf);
2579 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2586 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2588 MONO_REQ_GC_UNSAFE_MODE;
2590 MonoDynamicTable *table;
2592 guint32 token, scope, enclosing;
2595 /* if the type requires a typespec, we must try that first*/
2596 if (try_typespec && (token = create_typespec (assembly, type)))
2598 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2601 klass = mono_class_from_mono_type (type);
2603 klass = mono_class_from_mono_type (type);
2606 * If it's in the same module and not a generic type parameter:
2608 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2609 (type->type != MONO_TYPE_MVAR)) {
2610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2611 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2612 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2616 if (klass->nested_in) {
2617 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2618 /* get the typeref idx of the enclosing type */
2619 enclosing >>= MONO_TYPEDEFORREF_BITS;
2620 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2622 scope = resolution_scope_from_image (assembly, klass->image);
2624 table = &assembly->tables [MONO_TABLE_TYPEREF];
2625 if (assembly->save) {
2626 alloc_table (table, table->rows + 1);
2627 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2628 values [MONO_TYPEREF_SCOPE] = scope;
2629 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2630 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2632 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2633 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2635 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2640 * Despite the name, we handle also TypeSpec (with the above helper).
2643 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2645 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2648 #ifndef DISABLE_REFLECTION_EMIT
2650 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2652 MONO_REQ_GC_NEUTRAL_MODE;
2654 MonoDynamicTable *table;
2656 guint32 token, pclass;
2658 switch (parent & MONO_TYPEDEFORREF_MASK) {
2659 case MONO_TYPEDEFORREF_TYPEREF:
2660 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2662 case MONO_TYPEDEFORREF_TYPESPEC:
2663 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2665 case MONO_TYPEDEFORREF_TYPEDEF:
2666 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2669 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2672 /* extract the index */
2673 parent >>= MONO_TYPEDEFORREF_BITS;
2675 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2677 if (assembly->save) {
2678 alloc_table (table, table->rows + 1);
2679 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2680 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2681 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2682 values [MONO_MEMBERREF_SIGNATURE] = sig;
2685 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2692 * Insert a memberef row into the metadata: the token that point to the memberref
2693 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2694 * mono_image_get_fieldref_token()).
2695 * The sig param is an index to an already built signature.
2698 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2700 MONO_REQ_GC_NEUTRAL_MODE;
2702 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2703 return mono_image_add_memberef_row (assembly, parent, name, sig);
2708 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2710 MONO_REQ_GC_NEUTRAL_MODE;
2713 MonoMethodSignature *sig;
2715 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2717 if (create_typespec) {
2718 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2723 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2724 if (token && !create_typespec)
2727 g_assert (!method->is_inflated);
2730 * A methodref signature can't contain an unmanaged calling convention.
2732 sig = mono_metadata_signature_dup (mono_method_signature (method));
2733 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2734 sig->call_convention = MONO_CALL_DEFAULT;
2735 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2736 method->name, method_encode_signature (assembly, sig));
2738 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2741 if (create_typespec) {
2742 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2743 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2744 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2746 if (assembly->save) {
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2751 values [MONO_METHODSPEC_METHOD] = token;
2752 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2755 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2757 /*methodspec and memberef tokens are diferent, */
2758 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2765 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2767 guint32 token, parent, sig;
2768 ReflectionMethodBuilder rmb;
2770 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2772 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2776 name = mono_string_to_utf8 (method->name);
2777 reflection_methodbuilder_from_method_builder (&rmb, method);
2780 * A methodref signature can't contain an unmanaged calling convention.
2781 * Since some flags are encoded as part of call_conv, we need to check against it.
2783 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2784 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2786 sig = method_builder_encode_signature (assembly, &rmb);
2788 if (tb->generic_params)
2789 parent = create_generic_typespec (assembly, tb);
2791 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2793 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2796 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2801 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2802 const gchar *name, guint32 sig)
2804 MonoDynamicTable *table;
2808 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2810 if (assembly->save) {
2811 alloc_table (table, table->rows + 1);
2812 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2813 values [MONO_MEMBERREF_CLASS] = original;
2814 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2815 values [MONO_MEMBERREF_SIGNATURE] = sig;
2818 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2825 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2829 guint32 nparams = mono_array_length (mb->generic_params);
2832 if (!assembly->save)
2835 sigbuffer_init (&buf, 32);
2837 sigbuffer_add_value (&buf, 0xa);
2838 sigbuffer_add_value (&buf, nparams);
2840 for (i = 0; i < nparams; i++) {
2841 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2842 sigbuffer_add_value (&buf, i);
2845 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2846 sigbuffer_free (&buf);
2851 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2853 MonoDynamicTable *table;
2855 guint32 token, mtoken = 0;
2857 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2861 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2863 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2864 switch (mono_metadata_token_table (mtoken)) {
2865 case MONO_TABLE_MEMBERREF:
2866 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2868 case MONO_TABLE_METHOD:
2869 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2872 g_assert_not_reached ();
2875 if (assembly->save) {
2876 alloc_table (table, table->rows + 1);
2877 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2878 values [MONO_METHODSPEC_METHOD] = mtoken;
2879 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2882 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2885 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2890 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2894 if (mb->generic_params && create_methodspec)
2895 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2897 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2901 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2902 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2907 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2909 guint32 token, parent, sig;
2910 ReflectionMethodBuilder rmb;
2912 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2914 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2918 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2920 if (tb->generic_params)
2921 parent = create_generic_typespec (assembly, tb);
2923 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2925 name = mono_string_to_utf8 (rmb.name);
2926 sig = method_builder_encode_signature (assembly, &rmb);
2928 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2931 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2937 is_field_on_inst (MonoClassField *field)
2939 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2943 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2946 get_field_on_inst_generic_type (MonoClassField *field)
2948 MonoClass *klass, *gtd;
2949 MonoDynamicGenericClass *dgclass;
2952 g_assert (is_field_on_inst (field));
2954 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2956 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2957 field_index = field - dgclass->fields;
2958 return dgclass->field_generic_types [field_index];
2961 klass = field->parent;
2962 gtd = klass->generic_class->container_class;
2964 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2965 field_index = field - klass->fields;
2966 return gtd->fields [field_index].type;
2969 g_assert_not_reached ();
2973 #ifndef DISABLE_REFLECTION_EMIT
2975 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2981 g_assert (field->parent);
2983 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2987 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2988 int index = field - field->parent->fields;
2989 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2991 if (is_field_on_inst (field))
2992 type = get_field_on_inst_generic_type (field);
2994 type = mono_field_get_type (field);
2996 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2997 mono_field_get_name (field),
2998 fieldref_encode_signature (assembly, field->parent->image, type));
2999 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3004 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3008 MonoGenericClass *gclass;
3012 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3015 if (is_sre_field_builder (mono_object_class (f->fb))) {
3016 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3017 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3018 klass = mono_class_from_mono_type (type);
3019 gclass = type->data.generic_class;
3020 g_assert (gclass->is_dynamic);
3022 name = mono_string_to_utf8 (fb->name);
3023 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3024 field_encode_signature (assembly, fb));
3026 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3028 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3030 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3031 klass = mono_class_from_mono_type (type);
3033 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3034 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3036 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3037 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3040 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3045 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3049 MonoGenericClass *gclass;
3052 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3054 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3058 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3059 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3060 ReflectionMethodBuilder rmb;
3063 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3064 klass = mono_class_from_mono_type (type);
3066 gclass = type->data.generic_class;
3067 g_assert (gclass->is_dynamic);
3069 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3071 name = mono_string_to_utf8 (rmb.name);
3073 sig = method_builder_encode_signature (assembly, &rmb);
3075 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3077 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3078 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3080 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3081 klass = mono_class_from_mono_type (type);
3083 sig = method_encode_signature (assembly, mono_method_signature (mm));
3084 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3086 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3087 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3091 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3096 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3100 MonoGenericContext tmp_context;
3101 MonoType **type_argv;
3102 MonoGenericInst *ginst;
3103 MonoMethod *method, *inflated;
3106 init_type_builder_generics ((MonoObject*)m->inst);
3108 method = inflate_method (m->inst, (MonoObject*)m->mb);
3110 klass = method->klass;
3112 if (m->method_args == NULL)
3115 if (method->is_inflated)
3116 method = ((MonoMethodInflated *) method)->declaring;
3118 count = mono_array_length (m->method_args);
3120 type_argv = g_new0 (MonoType *, count);
3121 for (i = 0; i < count; i++) {
3122 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3123 type_argv [i] = mono_reflection_type_get_handle (garg);
3125 ginst = mono_metadata_get_generic_inst (count, type_argv);
3128 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3129 tmp_context.method_inst = ginst;
3131 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3132 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3137 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3139 guint32 sig, token = 0;
3143 if (m->method_args) {
3144 MonoMethod *inflated;
3146 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3147 if (create_methodspec)
3148 token = mono_image_get_methodspec_token (assembly, inflated);
3150 token = mono_image_get_inflated_method_token (assembly, inflated);
3154 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3158 if (is_sre_method_builder (mono_object_class (m->mb))) {
3159 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3160 MonoGenericClass *gclass;
3161 ReflectionMethodBuilder rmb;
3164 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3165 klass = mono_class_from_mono_type (type);
3166 gclass = type->data.generic_class;
3167 g_assert (gclass->is_dynamic);
3169 reflection_methodbuilder_from_method_builder (&rmb, mb);
3171 name = mono_string_to_utf8 (rmb.name);
3173 sig = method_builder_encode_signature (assembly, &rmb);
3175 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3177 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3178 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3180 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3181 klass = mono_class_from_mono_type (type);
3183 sig = method_encode_signature (assembly, mono_method_signature (mm));
3184 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3186 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3187 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3190 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3195 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3199 guint32 nparams = context->method_inst->type_argc;
3202 if (!assembly->save)
3205 sigbuffer_init (&buf, 32);
3207 * FIXME: vararg, explicit_this, differenc call_conv values...
3209 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3210 sigbuffer_add_value (&buf, nparams);
3212 for (i = 0; i < nparams; i++)
3213 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3215 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3216 sigbuffer_free (&buf);
3221 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3223 MonoDynamicTable *table;
3225 guint32 token, mtoken = 0, sig;
3226 MonoMethodInflated *imethod;
3227 MonoMethod *declaring;
3229 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3231 g_assert (method->is_inflated);
3232 imethod = (MonoMethodInflated *) method;
3233 declaring = imethod->declaring;
3235 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3236 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3238 if (!mono_method_signature (declaring)->generic_param_count)
3241 switch (mono_metadata_token_table (mtoken)) {
3242 case MONO_TABLE_MEMBERREF:
3243 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3245 case MONO_TABLE_METHOD:
3246 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3249 g_assert_not_reached ();
3252 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3254 if (assembly->save) {
3255 alloc_table (table, table->rows + 1);
3256 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3257 values [MONO_METHODSPEC_METHOD] = mtoken;
3258 values [MONO_METHODSPEC_SIGNATURE] = sig;
3261 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3268 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3270 MonoMethodInflated *imethod;
3273 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3277 g_assert (method->is_inflated);
3278 imethod = (MonoMethodInflated *) method;
3280 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3281 token = method_encode_methodspec (assembly, method);
3283 guint32 sig = method_encode_signature (
3284 assembly, mono_method_signature (imethod->declaring));
3285 token = mono_image_get_memberref_token (
3286 assembly, &method->klass->byval_arg, method->name, sig);
3289 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3294 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3296 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3299 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3300 token = mono_image_get_memberref_token (
3301 assembly, &m->klass->byval_arg, m->name, sig);
3307 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3309 MonoDynamicTable *table;
3318 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3319 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3320 * Because of this, we must not insert it into the `typeref' hash table.
3322 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3323 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3327 sigbuffer_init (&buf, 32);
3329 g_assert (tb->generic_params);
3330 klass = mono_class_from_mono_type (type);
3332 if (tb->generic_container)
3333 mono_reflection_create_generic_class (tb);
3335 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3336 g_assert (klass->generic_container);
3337 sigbuffer_add_value (&buf, klass->byval_arg.type);
3338 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3340 count = mono_array_length (tb->generic_params);
3341 sigbuffer_add_value (&buf, count);
3342 for (i = 0; i < count; i++) {
3343 MonoReflectionGenericParam *gparam;
3345 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3347 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3350 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3352 if (assembly->save) {
3353 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3354 alloc_table (table, table->rows + 1);
3355 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3356 values [MONO_TYPESPEC_SIGNATURE] = token;
3358 sigbuffer_free (&buf);
3360 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3361 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3367 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3370 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3372 int i, count, len, pos;
3377 count += mono_array_length (modreq);
3379 count += mono_array_length (modopt);
3382 return mono_metadata_type_dup (NULL, type);
3384 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3385 t = (MonoType *)g_malloc (len);
3386 memcpy (t, type, MONO_SIZEOF_TYPE);
3388 t->num_mods = count;
3391 for (i = 0; i < mono_array_length (modreq); ++i) {
3392 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3393 t->modifiers [pos].required = 1;
3394 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3399 for (i = 0; i < mono_array_length (modopt); ++i) {
3400 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3401 t->modifiers [pos].required = 0;
3402 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3411 init_type_builder_generics (MonoObject *type)
3413 MonoReflectionTypeBuilder *tb;
3415 if (!is_sre_type_builder(mono_object_class (type)))
3417 tb = (MonoReflectionTypeBuilder *)type;
3419 if (tb && tb->generic_container)
3420 mono_reflection_create_generic_class (tb);
3424 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3426 MonoDynamicTable *table;
3427 MonoType *custom = NULL, *type;
3429 guint32 token, pclass, parent, sig;
3432 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3436 /* FIXME: is this call necessary? */
3437 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3438 name = mono_string_to_utf8 (fb->name);
3440 /*FIXME this is one more layer of ugliness due how types are created.*/
3441 init_type_builder_generics (fb->type);
3443 /* fb->type does not include the custom modifiers */
3444 /* FIXME: We should do this in one place when a fieldbuilder is created */
3445 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3446 if (fb->modreq || fb->modopt)
3447 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3449 sig = fieldref_encode_signature (assembly, NULL, type);
3452 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3453 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3455 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3456 parent >>= MONO_TYPEDEFORREF_BITS;
3458 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3460 if (assembly->save) {
3461 alloc_table (table, table->rows + 1);
3462 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3463 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3464 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3465 values [MONO_MEMBERREF_SIGNATURE] = sig;
3468 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3470 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3476 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3482 if (!assembly->save)
3485 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3486 g_assert (helper->type == 2);
3488 if (helper->arguments)
3489 nargs = mono_array_length (helper->arguments);
3493 sigbuffer_init (&buf, 32);
3495 /* Encode calling convention */
3496 /* Change Any to Standard */
3497 if ((helper->call_conv & 0x03) == 0x03)
3498 helper->call_conv = 0x01;
3499 /* explicit_this implies has_this */
3500 if (helper->call_conv & 0x40)
3501 helper->call_conv &= 0x20;
3503 if (helper->call_conv == 0) { /* Unmanaged */
3504 idx = helper->unmanaged_call_conv - 1;
3507 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3508 if (helper->call_conv & 0x02) /* varargs */
3512 sigbuffer_add_byte (&buf, idx);
3513 sigbuffer_add_value (&buf, nargs);
3514 encode_reflection_type (assembly, helper->return_type, &buf);
3515 for (i = 0; i < nargs; ++i) {
3516 MonoArray *modreqs = NULL;
3517 MonoArray *modopts = NULL;
3518 MonoReflectionType *pt;
3520 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3521 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3522 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3523 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3525 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3526 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3527 encode_reflection_type (assembly, pt, &buf);
3529 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3530 sigbuffer_free (&buf);
3536 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3539 MonoDynamicTable *table;
3542 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3543 idx = table->next_idx ++;
3545 alloc_table (table, table->rows);
3546 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3548 values [MONO_STAND_ALONE_SIGNATURE] =
3549 mono_reflection_encode_sighelper (assembly, helper);
3555 reflection_cc_to_file (int call_conv) {
3556 switch (call_conv & 0x3) {
3558 case 1: return MONO_CALL_DEFAULT;
3559 case 2: return MONO_CALL_VARARG;
3561 g_assert_not_reached ();
3565 #endif /* !DISABLE_REFLECTION_EMIT */
3569 MonoMethodSignature *sig;
3574 #ifndef DISABLE_REFLECTION_EMIT
3576 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3581 MonoMethodSignature *sig;
3585 name = mono_string_to_utf8 (m->name);
3586 nparams = mono_array_length (m->parameters);
3587 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3589 sig->sentinelpos = -1;
3590 sig->call_convention = reflection_cc_to_file (m->call_conv);
3591 sig->param_count = nparams;
3592 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3593 mtype = mono_reflection_type_get_handle (m->parent);
3594 for (i = 0; i < nparams; ++i)
3595 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3597 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3598 am = (ArrayMethod *)tmp->data;
3599 if (strcmp (name, am->name) == 0 &&
3600 mono_metadata_type_equal (am->parent, mtype) &&
3601 mono_metadata_signature_equal (am->sig, sig)) {
3604 m->table_idx = am->token & 0xffffff;
3608 am = g_new0 (ArrayMethod, 1);
3612 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3613 method_encode_signature (assembly, sig));
3614 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3615 m->table_idx = am->token & 0xffffff;
3620 * Insert into the metadata tables all the info about the TypeBuilder tb.
3621 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3624 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3626 MonoDynamicTable *table;
3628 int i, is_object = 0, is_system = 0;
3631 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3632 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3633 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3634 n = mono_string_to_utf8 (tb->name);
3635 if (strcmp (n, "Object") == 0)
3637 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3639 n = mono_string_to_utf8 (tb->nspace);
3640 if (strcmp (n, "System") == 0)
3642 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3644 if (tb->parent && !(is_system && is_object) &&
3645 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3646 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3648 values [MONO_TYPEDEF_EXTENDS] = 0;
3650 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3651 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3654 * if we have explicitlayout or sequentiallayouts, output data in the
3655 * ClassLayout table.
3657 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3658 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3659 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3661 alloc_table (table, table->rows);
3662 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3663 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3664 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3665 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3668 /* handle interfaces */
3669 if (tb->interfaces) {
3670 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3672 table->rows += mono_array_length (tb->interfaces);
3673 alloc_table (table, table->rows);
3674 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3675 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3676 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3677 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3678 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3679 values += MONO_INTERFACEIMPL_SIZE;
3685 table = &assembly->tables [MONO_TABLE_FIELD];
3686 table->rows += tb->num_fields;
3687 alloc_table (table, table->rows);
3688 for (i = 0; i < tb->num_fields; ++i)
3689 mono_image_get_field_info (
3690 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3693 /* handle constructors */
3695 table = &assembly->tables [MONO_TABLE_METHOD];
3696 table->rows += mono_array_length (tb->ctors);
3697 alloc_table (table, table->rows);
3698 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3699 mono_image_get_ctor_info (domain,
3700 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3703 /* handle methods */
3705 table = &assembly->tables [MONO_TABLE_METHOD];
3706 table->rows += tb->num_methods;
3707 alloc_table (table, table->rows);
3708 for (i = 0; i < tb->num_methods; ++i)
3709 mono_image_get_method_info (
3710 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3713 /* Do the same with properties etc.. */
3714 if (tb->events && mono_array_length (tb->events)) {
3715 table = &assembly->tables [MONO_TABLE_EVENT];
3716 table->rows += mono_array_length (tb->events);
3717 alloc_table (table, table->rows);
3718 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3720 alloc_table (table, table->rows);
3721 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3722 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3723 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3724 for (i = 0; i < mono_array_length (tb->events); ++i)
3725 mono_image_get_event_info (
3726 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3728 if (tb->properties && mono_array_length (tb->properties)) {
3729 table = &assembly->tables [MONO_TABLE_PROPERTY];
3730 table->rows += mono_array_length (tb->properties);
3731 alloc_table (table, table->rows);
3732 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3734 alloc_table (table, table->rows);
3735 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3736 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3737 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3738 for (i = 0; i < mono_array_length (tb->properties); ++i)
3739 mono_image_get_property_info (
3740 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3743 /* handle generic parameters */
3744 if (tb->generic_params) {
3745 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3746 table->rows += mono_array_length (tb->generic_params);
3747 alloc_table (table, table->rows);
3748 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3749 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3751 mono_image_get_generic_param_info (
3752 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3756 mono_image_add_decl_security (assembly,
3757 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3760 MonoDynamicTable *ntable;
3762 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3763 ntable->rows += mono_array_length (tb->subtypes);
3764 alloc_table (ntable, ntable->rows);
3765 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3767 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3768 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3770 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3771 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3772 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3773 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3774 mono_string_to_utf8 (tb->name), tb->table_idx,
3775 ntable->next_idx, ntable->rows);*/
3776 values += MONO_NESTED_CLASS_SIZE;
3784 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3788 mono_ptr_array_append (*types, type);
3790 if (!type->subtypes)
3793 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3794 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3795 collect_types (types, subtype);
3800 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3802 if ((*type1)->table_idx < (*type2)->table_idx)
3805 if ((*type1)->table_idx > (*type2)->table_idx)
3812 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3817 for (i = 0; i < mono_array_length (pinfo); ++i) {
3818 MonoReflectionParamBuilder *pb;
3819 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3822 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3827 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3830 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3832 for (i = 0; i < tb->num_fields; ++i) {
3833 MonoReflectionFieldBuilder* fb;
3834 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3835 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3839 for (i = 0; i < mono_array_length (tb->events); ++i) {
3840 MonoReflectionEventBuilder* eb;
3841 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3842 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3845 if (tb->properties) {
3846 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3847 MonoReflectionPropertyBuilder* pb;
3848 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3849 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3853 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3854 MonoReflectionCtorBuilder* cb;
3855 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3856 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3857 params_add_cattrs (assembly, cb->pinfo);
3862 for (i = 0; i < tb->num_methods; ++i) {
3863 MonoReflectionMethodBuilder* mb;
3864 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3865 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3866 params_add_cattrs (assembly, mb->pinfo);
3871 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3872 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3877 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3881 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3883 if (moduleb->global_methods) {
3884 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3885 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3886 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3887 params_add_cattrs (assembly, mb->pinfo);
3891 if (moduleb->global_fields) {
3892 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3893 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3894 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3898 if (moduleb->types) {
3899 for (i = 0; i < moduleb->num_types; ++i)
3900 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3905 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3907 MonoDynamicTable *table;
3911 char *b = blob_size;
3914 table = &assembly->tables [MONO_TABLE_FILE];
3916 alloc_table (table, table->rows);
3917 values = table->values + table->next_idx * MONO_FILE_SIZE;
3918 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3919 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3920 if (image_is_dynamic (module->image)) {
3921 /* This depends on the fact that the main module is emitted last */
3922 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3923 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3926 path = g_strdup (module->image->name);
3928 mono_sha1_get_digest_from_file (path, hash);
3931 mono_metadata_encode_value (20, b, &b);
3932 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3933 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3940 MonoDynamicTable *table;
3943 table = &assembly->tables [MONO_TABLE_MODULE];
3944 mb->table_idx = table->next_idx ++;
3945 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3946 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3949 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3950 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3951 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3952 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3956 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3957 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3959 MonoDynamicTable *table;
3963 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3964 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3967 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3969 alloc_table (table, table->rows);
3970 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3972 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3973 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3974 if (klass->nested_in)
3975 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3977 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3978 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3979 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3981 res = table->next_idx;
3985 /* Emit nested types */
3986 if (klass->ext && klass->ext->nested_classes) {
3989 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3990 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3997 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3998 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4003 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4005 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4007 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4008 parent_index, assembly);
4012 * We need to do this ourselves since klass->nested_classes is not set up.
4015 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4016 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4021 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4022 guint32 module_index, MonoDynamicImage *assembly)
4024 MonoImage *image = module->image;
4028 t = &image->tables [MONO_TABLE_TYPEDEF];
4030 for (i = 0; i < t->rows; ++i) {
4032 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4033 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4035 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4036 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4041 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4043 MonoDynamicTable *table;
4045 guint32 scope, scope_idx, impl, current_idx;
4046 gboolean forwarder = TRUE;
4047 gpointer iter = NULL;
4050 if (klass->nested_in) {
4051 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4054 scope = resolution_scope_from_image (assembly, klass->image);
4055 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4056 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4057 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4060 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4063 alloc_table (table, table->rows);
4064 current_idx = table->next_idx;
4065 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4067 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4068 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4069 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4070 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4071 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4075 while ((nested = mono_class_get_nested_types (klass, &iter)))
4076 add_exported_type (assemblyb, assembly, nested, current_idx);
4080 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4085 if (!assemblyb->type_forwarders)
4088 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4089 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4094 type = mono_reflection_type_get_handle (t);
4097 klass = mono_class_from_mono_type (type);
4099 add_exported_type (assemblyb, assembly, klass, 0);
4103 #define align_pointer(base,p)\
4105 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4107 (p) += 4 - (__diff & 3);\
4111 compare_constants (const void *a, const void *b)
4113 const guint32 *a_values = (const guint32 *)a;
4114 const guint32 *b_values = (const guint32 *)b;
4115 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4119 compare_semantics (const void *a, const void *b)
4121 const guint32 *a_values = (const guint32 *)a;
4122 const guint32 *b_values = (const guint32 *)b;
4123 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4126 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4130 compare_custom_attrs (const void *a, const void *b)
4132 const guint32 *a_values = (const guint32 *)a;
4133 const guint32 *b_values = (const guint32 *)b;
4135 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4139 compare_field_marshal (const void *a, const void *b)
4141 const guint32 *a_values = (const guint32 *)a;
4142 const guint32 *b_values = (const guint32 *)b;
4144 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4148 compare_nested (const void *a, const void *b)
4150 const guint32 *a_values = (const guint32 *)a;
4151 const guint32 *b_values = (const guint32 *)b;
4153 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4157 compare_genericparam (const void *a, const void *b)
4159 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4160 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4162 if ((*b_entry)->owner == (*a_entry)->owner)
4164 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4165 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4167 return (*a_entry)->owner - (*b_entry)->owner;
4171 compare_declsecurity_attrs (const void *a, const void *b)
4173 const guint32 *a_values = (const guint32 *)a;
4174 const guint32 *b_values = (const guint32 *)b;
4176 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4180 compare_interface_impl (const void *a, const void *b)
4182 const guint32 *a_values = (const guint32 *)a;
4183 const guint32 *b_values = (const guint32 *)b;
4185 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4189 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4193 pad_heap (MonoDynamicStream *sh)
4195 if (sh->index & 3) {
4196 int sz = 4 - (sh->index & 3);
4197 memset (sh->data + sh->index, 0, sz);
4204 MonoDynamicStream *stream;
4208 * build_compressed_metadata() fills in the blob of data that represents the
4209 * raw metadata as it will be saved in the PE file. The five streams are output
4210 * and the metadata tables are comnpressed from the guint32 array representation,
4211 * to the compressed on-disk format.
4214 build_compressed_metadata (MonoDynamicImage *assembly)
4216 MonoDynamicTable *table;
4218 guint64 valid_mask = 0;
4219 guint64 sorted_mask;
4220 guint32 heapt_size = 0;
4221 guint32 meta_size = 256; /* allow for header and other stuff */
4222 guint32 table_offset;
4223 guint32 ntables = 0;
4229 struct StreamDesc stream_desc [5];
4231 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4232 for (i = 0; i < assembly->gen_params->len; i++){
4233 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4234 write_generic_param_entry (assembly, entry);
4237 stream_desc [0].name = "#~";
4238 stream_desc [0].stream = &assembly->tstream;
4239 stream_desc [1].name = "#Strings";
4240 stream_desc [1].stream = &assembly->sheap;
4241 stream_desc [2].name = "#US";
4242 stream_desc [2].stream = &assembly->us;
4243 stream_desc [3].name = "#Blob";
4244 stream_desc [3].stream = &assembly->blob;
4245 stream_desc [4].name = "#GUID";
4246 stream_desc [4].stream = &assembly->guid;
4248 /* tables that are sorted */
4249 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4250 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4251 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4252 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4253 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4254 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4255 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4257 /* Compute table sizes */
4258 /* the MonoImage has already been created in mono_image_basic_init() */
4259 meta = &assembly->image;
4261 /* sizes should be multiple of 4 */
4262 pad_heap (&assembly->blob);
4263 pad_heap (&assembly->guid);
4264 pad_heap (&assembly->sheap);
4265 pad_heap (&assembly->us);
4267 /* Setup the info used by compute_sizes () */
4268 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4269 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4270 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4272 meta_size += assembly->blob.index;
4273 meta_size += assembly->guid.index;
4274 meta_size += assembly->sheap.index;
4275 meta_size += assembly->us.index;
4277 for (i=0; i < MONO_TABLE_NUM; ++i)
4278 meta->tables [i].rows = assembly->tables [i].rows;
4280 for (i = 0; i < MONO_TABLE_NUM; i++){
4281 if (meta->tables [i].rows == 0)
4283 valid_mask |= (guint64)1 << i;
4285 meta->tables [i].row_size = mono_metadata_compute_size (
4286 meta, i, &meta->tables [i].size_bitfield);
4287 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4289 heapt_size += 24; /* #~ header size */
4290 heapt_size += ntables * 4;
4291 /* make multiple of 4 */
4294 meta_size += heapt_size;
4295 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4296 p = (unsigned char*)meta->raw_metadata;
4297 /* the metadata signature */
4298 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4299 /* version numbers and 4 bytes reserved */
4300 int16val = (guint16*)p;
4301 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4302 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4304 /* version string */
4305 int32val = (guint32*)p;
4306 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4308 memcpy (p, meta->version, strlen (meta->version));
4309 p += GUINT32_FROM_LE (*int32val);
4310 align_pointer (meta->raw_metadata, p);
4311 int16val = (guint16*)p;
4312 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4313 *int16val = GUINT16_TO_LE (5); /* number of streams */
4317 * write the stream info.
4319 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4320 table_offset += 3; table_offset &= ~3;
4322 assembly->tstream.index = heapt_size;
4323 for (i = 0; i < 5; ++i) {
4324 int32val = (guint32*)p;
4325 stream_desc [i].stream->offset = table_offset;
4326 *int32val++ = GUINT32_TO_LE (table_offset);
4327 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4328 table_offset += GUINT32_FROM_LE (*int32val);
4329 table_offset += 3; table_offset &= ~3;
4331 strcpy ((char*)p, stream_desc [i].name);
4332 p += strlen (stream_desc [i].name) + 1;
4333 align_pointer (meta->raw_metadata, p);
4336 * now copy the data, the table stream header and contents goes first.
4338 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4339 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4340 int32val = (guint32*)p;
4341 *int32val = GUINT32_TO_LE (0); /* reserved */
4344 *p++ = 2; /* version */
4347 if (meta->idx_string_wide)
4349 if (meta->idx_guid_wide)
4351 if (meta->idx_blob_wide)
4354 *p++ = 1; /* reserved */
4355 int64val = (guint64*)p;
4356 *int64val++ = GUINT64_TO_LE (valid_mask);
4357 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4359 int32val = (guint32*)p;
4360 for (i = 0; i < MONO_TABLE_NUM; i++){
4361 if (meta->tables [i].rows == 0)
4363 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4365 p = (unsigned char*)int32val;
4367 /* sort the tables that still need sorting */
4368 table = &assembly->tables [MONO_TABLE_CONSTANT];
4370 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4371 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4373 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4374 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4376 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4377 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4379 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4380 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4382 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4383 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4384 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4386 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4387 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4389 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4391 /* compress the tables */
4392 for (i = 0; i < MONO_TABLE_NUM; i++){
4395 guint32 bitfield = meta->tables [i].size_bitfield;
4396 if (!meta->tables [i].rows)
4398 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4399 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4400 meta->tables [i].base = (char*)p;
4401 for (row = 1; row <= meta->tables [i].rows; ++row) {
4402 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4403 for (col = 0; col < assembly->tables [i].columns; ++col) {
4404 switch (mono_metadata_table_size (bitfield, col)) {
4406 *p++ = values [col];
4409 *p++ = values [col] & 0xff;
4410 *p++ = (values [col] >> 8) & 0xff;
4413 *p++ = values [col] & 0xff;
4414 *p++ = (values [col] >> 8) & 0xff;
4415 *p++ = (values [col] >> 16) & 0xff;
4416 *p++ = (values [col] >> 24) & 0xff;
4419 g_assert_not_reached ();
4423 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4426 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4427 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4428 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4429 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4430 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4432 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4436 * Some tables in metadata need to be sorted according to some criteria, but
4437 * when methods and fields are first created with reflection, they may be assigned a token
4438 * that doesn't correspond to the final token they will get assigned after the sorting.
4439 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4440 * with the reflection objects that represent them. Once all the tables are set up, the
4441 * reflection objects will contains the correct table index. fixup_method() will fixup the
4442 * tokens for the method with ILGenerator @ilgen.
4445 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4447 guint32 code_idx = GPOINTER_TO_UINT (value);
4448 MonoReflectionILTokenInfo *iltoken;
4449 MonoReflectionFieldBuilder *field;
4450 MonoReflectionCtorBuilder *ctor;
4451 MonoReflectionMethodBuilder *method;
4452 MonoReflectionTypeBuilder *tb;
4453 MonoReflectionArrayMethod *am;
4455 unsigned char *target;
4457 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4458 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4459 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4460 switch (target [3]) {
4461 case MONO_TABLE_FIELD:
4462 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4463 field = (MonoReflectionFieldBuilder *)iltoken->member;
4464 idx = field->table_idx;
4465 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4466 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4467 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4469 g_assert_not_reached ();
4472 case MONO_TABLE_METHOD:
4473 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4474 method = (MonoReflectionMethodBuilder *)iltoken->member;
4475 idx = method->table_idx;
4476 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4477 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4478 idx = ctor->table_idx;
4479 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4480 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4481 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4482 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4484 g_assert_not_reached ();
4487 case MONO_TABLE_TYPEDEF:
4488 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4489 g_assert_not_reached ();
4490 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4491 idx = tb->table_idx;
4493 case MONO_TABLE_MEMBERREF:
4494 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4495 am = (MonoReflectionArrayMethod*)iltoken->member;
4496 idx = am->table_idx;
4497 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4498 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4499 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4500 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4501 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4502 g_assert (m->klass->generic_class || m->klass->generic_container);
4504 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4506 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4507 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4508 g_assert (is_field_on_inst (f));
4510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4511 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4513 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4517 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4520 g_assert_not_reached ();
4523 case MONO_TABLE_METHODSPEC:
4524 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4525 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4526 g_assert (mono_method_signature (m)->generic_param_count);
4528 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4530 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4533 g_assert_not_reached ();
4537 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4539 target [0] = idx & 0xff;
4540 target [1] = (idx >> 8) & 0xff;
4541 target [2] = (idx >> 16) & 0xff;
4548 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4549 * value is not known when the table is emitted.
4552 fixup_cattrs (MonoDynamicImage *assembly)
4554 MonoDynamicTable *table;
4556 guint32 type, i, idx, token;
4559 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4561 for (i = 0; i < table->rows; ++i) {
4562 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4564 type = values [MONO_CUSTOM_ATTR_TYPE];
4565 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4566 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4567 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4568 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4571 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4572 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4573 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4575 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4576 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4577 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4578 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4585 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4587 MonoDynamicTable *table;
4590 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4592 alloc_table (table, table->rows);
4593 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4594 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4595 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4596 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4597 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4602 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4604 MonoDynamicTable *table;
4608 char *b = blob_size;
4610 guint32 idx, offset;
4612 if (rsrc->filename) {
4613 name = mono_string_to_utf8 (rsrc->filename);
4614 sname = g_path_get_basename (name);
4616 table = &assembly->tables [MONO_TABLE_FILE];
4618 alloc_table (table, table->rows);
4619 values = table->values + table->next_idx * MONO_FILE_SIZE;
4620 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4621 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4624 mono_sha1_get_digest_from_file (name, hash);
4625 mono_metadata_encode_value (20, b, &b);
4626 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4627 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4629 idx = table->next_idx++;
4631 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4637 data = mono_array_addr (rsrc->data, char, 0);
4638 len = mono_array_length (rsrc->data);
4644 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4645 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4646 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4647 mono_image_add_stream_data (&assembly->resources, data, len);
4651 * The entry should be emitted into the MANIFESTRESOURCE table of
4652 * the main module, but that needs to reference the FILE table
4653 * which isn't emitted yet.
4660 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4664 set_version_from_string (MonoString *version, guint32 *values)
4666 gchar *ver, *p, *str;
4669 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4670 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4671 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4672 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4675 ver = str = mono_string_to_utf8 (version);
4676 for (i = 0; i < 4; ++i) {
4677 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4683 /* handle Revision and Build */
4693 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4697 char *b = blob_size;
4702 len = mono_array_length (pkey);
4703 mono_metadata_encode_value (len, b, &b);
4704 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4705 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4707 assembly->public_key = (guint8 *)g_malloc (len);
4708 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4709 assembly->public_key_len = len;
4711 /* Special case: check for ECMA key (16 bytes) */
4712 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4713 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4714 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4715 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4716 /* minimum key size (in 2.0) is 384 bits */
4717 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4719 /* FIXME - verifier */
4720 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4721 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4723 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4729 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4731 MonoDynamicTable *table;
4732 MonoDynamicImage *assembly;
4733 MonoReflectionAssemblyBuilder *assemblyb;
4737 guint32 module_index;
4739 assemblyb = moduleb->assemblyb;
4740 assembly = moduleb->dynamic_image;
4741 domain = mono_object_domain (assemblyb);
4743 /* Emit ASSEMBLY table */
4744 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4745 alloc_table (table, 1);
4746 values = table->values + MONO_ASSEMBLY_SIZE;
4747 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4748 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4749 if (assemblyb->culture) {
4750 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4752 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4754 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4755 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4756 set_version_from_string (assemblyb->version, values);
4758 /* Emit FILE + EXPORTED_TYPE table */
4760 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4762 MonoReflectionModuleBuilder *file_module =
4763 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4764 if (file_module != moduleb) {
4765 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4767 if (file_module->types) {
4768 for (j = 0; j < file_module->num_types; ++j) {
4769 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4775 if (assemblyb->loaded_modules) {
4776 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4777 MonoReflectionModule *file_module =
4778 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4779 mono_image_fill_file_table (domain, file_module, assembly);
4781 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4784 if (assemblyb->type_forwarders)
4785 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4787 /* Emit MANIFESTRESOURCE table */
4789 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4791 MonoReflectionModuleBuilder *file_module =
4792 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4793 /* The table for the main module is emitted later */
4794 if (file_module != moduleb) {
4796 if (file_module->resources) {
4797 int len = mono_array_length (file_module->resources);
4798 for (j = 0; j < len; ++j) {
4799 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4800 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4807 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4810 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4811 * for the modulebuilder @moduleb.
4812 * At the end of the process, method and field tokens are fixed up and the
4813 * on-disk compressed metadata representation is created.
4816 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4818 MonoDynamicTable *table;
4819 MonoDynamicImage *assembly;
4820 MonoReflectionAssemblyBuilder *assemblyb;
4826 assemblyb = moduleb->assemblyb;
4827 assembly = moduleb->dynamic_image;
4828 domain = mono_object_domain (assemblyb);
4830 if (assembly->text_rva)
4833 assembly->text_rva = START_TEXT_RVA;
4835 if (moduleb->is_main) {
4836 mono_image_emit_manifest (moduleb);
4839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840 table->rows = 1; /* .<Module> */
4842 alloc_table (table, table->rows);
4844 * Set the first entry.
4846 values = table->values + table->columns;
4847 values [MONO_TYPEDEF_FLAGS] = 0;
4848 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4849 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4850 values [MONO_TYPEDEF_EXTENDS] = 0;
4851 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4852 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4855 * handle global methods
4856 * FIXME: test what to do when global methods are defined in multiple modules.
4858 if (moduleb->global_methods) {
4859 table = &assembly->tables [MONO_TABLE_METHOD];
4860 table->rows += mono_array_length (moduleb->global_methods);
4861 alloc_table (table, table->rows);
4862 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4863 mono_image_get_method_info (
4864 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4866 if (moduleb->global_fields) {
4867 table = &assembly->tables [MONO_TABLE_FIELD];
4868 table->rows += mono_array_length (moduleb->global_fields);
4869 alloc_table (table, table->rows);
4870 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4871 mono_image_get_field_info (
4872 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4875 table = &assembly->tables [MONO_TABLE_MODULE];
4876 alloc_table (table, 1);
4877 mono_image_fill_module_table (domain, moduleb, assembly);
4879 /* Collect all types into a list sorted by their table_idx */
4880 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4883 for (i = 0; i < moduleb->num_types; ++i) {
4884 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4885 collect_types (&types, type);
4888 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4889 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4890 table->rows += mono_ptr_array_size (types);
4891 alloc_table (table, table->rows);
4894 * Emit type names + namespaces at one place inside the string heap,
4895 * so load_class_names () needs to touch fewer pages.
4897 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4898 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4899 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4901 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4902 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4903 string_heap_insert_mstring (&assembly->sheap, tb->name);
4906 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4907 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4908 mono_image_get_type_info (domain, type, assembly);
4912 * table->rows is already set above and in mono_image_fill_module_table.
4914 /* add all the custom attributes at the end, once all the indexes are stable */
4915 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4917 /* CAS assembly permissions */
4918 if (assemblyb->permissions_minimum)
4919 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4920 if (assemblyb->permissions_optional)
4921 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4922 if (assemblyb->permissions_refused)
4923 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4925 module_add_cattrs (assembly, moduleb);
4928 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4930 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4931 * the final tokens and don't need another fixup pass. */
4933 if (moduleb->global_methods) {
4934 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4935 MonoReflectionMethodBuilder *mb = mono_array_get (
4936 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4937 mono_image_add_methodimpl (assembly, mb);
4941 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4942 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4943 if (type->methods) {
4944 for (j = 0; j < type->num_methods; ++j) {
4945 MonoReflectionMethodBuilder *mb = mono_array_get (
4946 type->methods, MonoReflectionMethodBuilder*, j);
4948 mono_image_add_methodimpl (assembly, mb);
4953 mono_ptr_array_destroy (types);
4955 fixup_cattrs (assembly);
4958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4961 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4963 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4970 guint32 import_lookup_table;
4974 guint32 import_address_table_rva;
4982 #ifndef DISABLE_REFLECTION_EMIT
4985 * mono_image_insert_string:
4986 * @module: module builder object
4989 * Insert @str into the user string stream of @module.
4992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4994 MonoDynamicImage *assembly;
4999 if (!module->dynamic_image)
5000 mono_image_module_basic_init (module);
5002 assembly = module->dynamic_image;
5004 if (assembly->save) {
5005 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5006 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5009 char *swapped = g_malloc (2 * mono_string_length (str));
5010 const char *p = (const char*)mono_string_chars (str);
5012 swap_with_size (swapped, p, 2, mono_string_length (str));
5013 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5017 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5019 mono_image_add_stream_data (&assembly->us, "", 1);
5021 idx = assembly->us.index ++;
5024 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5026 return MONO_TOKEN_STRING | idx;
5030 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5034 MonoMethodSignature *sig;
5036 klass = obj->vtable->klass;
5037 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5038 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5039 MonoMethodSignature *old;
5040 guint32 sig_token, parent;
5043 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5045 nargs = mono_array_length (opt_param_types);
5046 old = mono_method_signature (method);
5047 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5049 sig->hasthis = old->hasthis;
5050 sig->explicit_this = old->explicit_this;
5051 sig->call_convention = old->call_convention;
5052 sig->generic_param_count = old->generic_param_count;
5053 sig->param_count = old->param_count + nargs;
5054 sig->sentinelpos = old->param_count;
5055 sig->ret = old->ret;
5057 for (i = 0; i < old->param_count; i++)
5058 sig->params [i] = old->params [i];
5060 for (i = 0; i < nargs; i++) {
5061 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5062 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5065 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5066 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5067 parent >>= MONO_TYPEDEFORREF_BITS;
5069 parent <<= MONO_MEMBERREF_PARENT_BITS;
5070 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5072 sig_token = method_encode_signature (assembly, sig);
5073 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5074 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5075 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5076 ReflectionMethodBuilder rmb;
5077 guint32 parent, sig_token;
5078 int nopt_args, nparams, ngparams, i;
5081 reflection_methodbuilder_from_method_builder (&rmb, mb);
5082 rmb.opt_types = opt_param_types;
5083 nopt_args = mono_array_length (opt_param_types);
5085 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5086 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5087 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5089 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5090 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5091 sig->call_convention = rmb.call_conv;
5092 sig->generic_param_count = ngparams;
5093 sig->param_count = nparams + nopt_args;
5094 sig->sentinelpos = nparams;
5095 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5097 for (i = 0; i < nparams; i++) {
5098 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5099 sig->params [i] = mono_reflection_type_get_handle (rt);
5102 for (i = 0; i < nopt_args; i++) {
5103 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5104 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5107 sig_token = method_builder_encode_signature (assembly, &rmb);
5109 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5110 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5112 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5113 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5115 name = mono_string_to_utf8 (rmb.name);
5116 token = mono_image_get_varargs_method_token (
5117 assembly, parent, name, sig_token);
5120 g_error ("requested method token for %s\n", klass->name);
5123 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5124 register_dyn_token (assembly, token, obj);
5129 * mono_image_create_token:
5130 * @assembly: a dynamic assembly
5132 * @register_token: Whenever to register the token in the assembly->tokens hash.
5134 * Get a token to insert in the IL code stream for the given MemberInfo.
5135 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5136 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5140 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5141 gboolean create_open_instance, gboolean register_token)
5146 klass = obj->vtable->klass;
5148 /* Check for user defined reflection objects */
5149 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5150 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5151 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5153 if (strcmp (klass->name, "MethodBuilder") == 0) {
5154 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5155 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5157 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5158 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5160 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5161 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5162 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5163 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5164 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5166 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5167 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5169 token = mono_image_get_ctorbuilder_token (assembly, mb);
5170 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5171 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5172 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5173 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5174 if (tb->generic_params) {
5175 token = mono_image_get_generic_field_token (assembly, fb);
5177 if (tb->module->dynamic_image == assembly) {
5178 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5180 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5183 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5185 if (create_open_instance && tb->generic_params) {
5187 init_type_builder_generics (obj);
5188 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5190 token = mono_metadata_token_from_dor (token);
5191 } else if (tb->module->dynamic_image == assembly) {
5192 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5195 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5196 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5198 } else if (strcmp (klass->name, "MonoType") == 0) {
5199 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5200 MonoClass *mc = mono_class_from_mono_type (type);
5201 token = mono_metadata_token_from_dor (
5202 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5203 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5204 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5205 token = mono_metadata_token_from_dor (
5206 mono_image_typedef_or_ref (assembly, type));
5207 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5208 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5209 token = mono_metadata_token_from_dor (
5210 mono_image_typedef_or_ref (assembly, type));
5211 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5212 strcmp (klass->name, "MonoMethod") == 0 ||
5213 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5214 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5215 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5216 if (m->method->is_inflated) {
5217 if (create_open_instance)
5218 token = mono_image_get_methodspec_token (assembly, m->method);
5220 token = mono_image_get_inflated_method_token (assembly, m->method);
5221 } else if ((m->method->klass->image == &assembly->image) &&
5222 !m->method->klass->generic_class) {
5223 static guint32 method_table_idx = 0xffffff;
5224 if (m->method->klass->wastypebuilder) {
5225 /* we use the same token as the one that was assigned
5226 * to the Methodbuilder.
5227 * FIXME: do the equivalent for Fields.
5229 token = m->method->token;
5232 * Each token should have a unique index, but the indexes are
5233 * assigned by managed code, so we don't know about them. An
5234 * easy solution is to count backwards...
5236 method_table_idx --;
5237 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5240 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5242 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5243 } else if (strcmp (klass->name, "MonoField") == 0) {
5244 MonoReflectionField *f = (MonoReflectionField *)obj;
5245 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5246 static guint32 field_table_idx = 0xffffff;
5248 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5250 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5252 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5253 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5254 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5255 token = mono_image_get_array_token (assembly, m);
5256 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5257 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5258 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5259 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5260 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5261 token = mono_metadata_token_from_dor (
5262 mono_image_typedef_or_ref (assembly, type));
5263 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5264 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5265 token = mono_image_get_field_on_inst_token (assembly, f);
5266 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5267 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5268 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5269 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5270 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5271 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5272 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5273 MonoReflectionType *type = (MonoReflectionType *)obj;
5274 token = mono_metadata_token_from_dor (
5275 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5277 g_error ("requested token for %s\n", klass->name);
5281 mono_image_register_token (assembly, token, obj);
5287 * mono_image_register_token:
5289 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5290 * the Module.ResolveXXXToken () methods to work.
5293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5297 dynamic_image_lock (assembly);
5298 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5300 /* There could be multiple MethodInfo objects with the same token */
5301 //g_assert (prev == obj);
5303 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5305 dynamic_image_unlock (assembly);
5308 static MonoDynamicImage*
5309 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5311 static const guchar entrycode [16] = {0xff, 0x25, 0};
5312 MonoDynamicImage *image;
5315 const char *version;
5317 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5318 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5320 version = mono_get_runtime_info ()->runtime_version;
5323 /* The MonoGHashTable's need GC tracking */
5324 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5326 image = g_new0 (MonoDynamicImage, 1);
5329 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5331 /*g_print ("created image %p\n", image);*/
5332 /* keep in sync with image.c */
5333 image->image.name = assembly_name;
5334 image->image.assembly_name = image->image.name; /* they may be different */
5335 image->image.module_name = module_name;
5336 image->image.version = g_strdup (version);
5337 image->image.md_version_major = 1;
5338 image->image.md_version_minor = 1;
5339 image->image.dynamic = TRUE;
5341 image->image.references = g_new0 (MonoAssembly*, 1);
5342 image->image.references [0] = NULL;
5344 mono_image_init (&image->image);
5346 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5347 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5348 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5349 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5350 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5351 image->handleref = g_hash_table_new (NULL, NULL);
5352 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5353 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5354 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5355 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5356 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5357 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5358 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5359 image->gen_params = g_ptr_array_new ();
5360 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5362 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5363 string_heap_init (&image->sheap);
5364 mono_image_add_stream_data (&image->us, "", 1);
5365 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5366 /* import tables... */
5367 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5368 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5369 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5370 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5371 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5372 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5373 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5374 stream_data_align (&image->code);
5376 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5378 for (i=0; i < MONO_TABLE_NUM; ++i) {
5379 image->tables [i].next_idx = 1;
5380 image->tables [i].columns = table_sizes [i];
5383 image->image.assembly = (MonoAssembly*)assembly;
5384 image->run = assembly->run;
5385 image->save = assembly->save;
5386 image->pe_kind = 0x1; /* ILOnly */
5387 image->machine = 0x14c; /* I386 */
5389 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5391 dynamic_images_lock ();
5393 if (!dynamic_images)
5394 dynamic_images = g_ptr_array_new ();
5396 g_ptr_array_add (dynamic_images, image);
5398 dynamic_images_unlock ();
5405 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5411 release_hashtable (MonoGHashTable **hash)
5414 mono_g_hash_table_destroy (*hash);
5420 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5422 release_hashtable (&image->token_fixups);
5423 release_hashtable (&image->handleref_managed);
5424 release_hashtable (&image->tokens);
5425 release_hashtable (&image->remapped_tokens);
5426 release_hashtable (&image->generic_def_objects);
5427 release_hashtable (&image->methodspec);
5430 // Free dynamic image pass one: Free resources but not image itself
5432 mono_dynamic_image_free (MonoDynamicImage *image)
5434 MonoDynamicImage *di = image;
5439 mono_g_hash_table_destroy (di->methodspec);
5441 g_hash_table_destroy (di->typespec);
5443 g_hash_table_destroy (di->typeref);
5445 g_hash_table_destroy (di->handleref);
5446 if (di->handleref_managed)
5447 mono_g_hash_table_destroy (di->handleref_managed);
5449 mono_g_hash_table_destroy (di->tokens);
5450 if (di->remapped_tokens)
5451 mono_g_hash_table_destroy (di->remapped_tokens);
5452 if (di->generic_def_objects)
5453 mono_g_hash_table_destroy (di->generic_def_objects);
5454 if (di->blob_cache) {
5455 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5456 g_hash_table_destroy (di->blob_cache);
5458 if (di->standalonesig_cache)
5459 g_hash_table_destroy (di->standalonesig_cache);
5460 for (list = di->array_methods; list; list = list->next) {
5461 ArrayMethod *am = (ArrayMethod *)list->data;
5466 g_list_free (di->array_methods);
5467 if (di->gen_params) {
5468 for (i = 0; i < di->gen_params->len; i++) {
5469 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5470 mono_gc_deregister_root ((char*) &entry->gparam);
5473 g_ptr_array_free (di->gen_params, TRUE);
5475 if (di->token_fixups)
5476 mono_g_hash_table_destroy (di->token_fixups);
5477 if (di->method_to_table_idx)
5478 g_hash_table_destroy (di->method_to_table_idx);
5479 if (di->field_to_table_idx)
5480 g_hash_table_destroy (di->field_to_table_idx);
5481 if (di->method_aux_hash)
5482 g_hash_table_destroy (di->method_aux_hash);
5483 if (di->vararg_aux_hash)
5484 g_hash_table_destroy (di->vararg_aux_hash);
5485 g_free (di->strong_name);
5486 g_free (di->win32_res);
5488 g_free (di->public_key);
5490 /*g_print ("string heap destroy for image %p\n", di);*/
5491 mono_dynamic_stream_reset (&di->sheap);
5492 mono_dynamic_stream_reset (&di->code);
5493 mono_dynamic_stream_reset (&di->resources);
5494 mono_dynamic_stream_reset (&di->us);
5495 mono_dynamic_stream_reset (&di->blob);
5496 mono_dynamic_stream_reset (&di->tstream);
5497 mono_dynamic_stream_reset (&di->guid);
5498 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5499 g_free (di->tables [i].values);
5502 dynamic_images_lock ();
5505 g_ptr_array_remove (dynamic_images, di);
5507 dynamic_images_unlock ();
5510 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5512 mono_dynamic_image_free_image (MonoDynamicImage *image)
5514 /* See create_dynamic_mono_image () */
5516 /* Allocated using GC_MALLOC */
5522 #ifndef DISABLE_REFLECTION_EMIT
5525 * mono_image_basic_init:
5526 * @assembly: an assembly builder object
5528 * Create the MonoImage that represents the assembly builder and setup some
5529 * of the helper hash table and the basic metadata streams.
5532 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5534 MonoDynamicAssembly *assembly;
5535 MonoDynamicImage *image;
5536 MonoDomain *domain = mono_object_domain (assemblyb);
5538 if (assemblyb->dynamic_assembly)
5542 /* assembly->assembly.image might be GC allocated */
5543 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5545 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5548 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5550 assembly->assembly.ref_count = 1;
5551 assembly->assembly.dynamic = TRUE;
5552 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5553 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5554 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5555 if (assemblyb->culture)
5556 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5558 assembly->assembly.aname.culture = g_strdup ("");
5560 if (assemblyb->version) {
5561 char *vstr = mono_string_to_utf8 (assemblyb->version);
5562 char **version = g_strsplit (vstr, ".", 4);
5563 char **parts = version;
5564 assembly->assembly.aname.major = atoi (*parts++);
5565 assembly->assembly.aname.minor = atoi (*parts++);
5566 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5567 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5569 g_strfreev (version);
5572 assembly->assembly.aname.major = 0;
5573 assembly->assembly.aname.minor = 0;
5574 assembly->assembly.aname.build = 0;
5575 assembly->assembly.aname.revision = 0;
5578 assembly->run = assemblyb->access != 2;
5579 assembly->save = assemblyb->access != 1;
5580 assembly->domain = domain;
5582 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5583 image->initial_image = TRUE;
5584 assembly->assembly.aname.name = image->image.name;
5585 assembly->assembly.image = &image->image;
5586 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5587 /* -1 to correct for the trailing NULL byte */
5588 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5589 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5591 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5594 mono_domain_assemblies_lock (domain);
5595 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5596 mono_domain_assemblies_unlock (domain);
5598 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5600 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5602 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5605 #endif /* !DISABLE_REFLECTION_EMIT */
5607 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5610 calc_section_size (MonoDynamicImage *assembly)
5614 /* alignment constraints */
5615 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5616 g_assert ((assembly->code.index % 4) == 0);
5617 assembly->meta_size += 3;
5618 assembly->meta_size &= ~3;
5619 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5620 g_assert ((assembly->resources.index % 4) == 0);
5622 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5623 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5626 if (assembly->win32_res) {
5627 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5629 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5630 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5634 assembly->sections [MONO_SECTION_RELOC].size = 12;
5635 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5645 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5649 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5651 ResTreeNode *t1 = (ResTreeNode*)a;
5652 ResTreeNode *t2 = (ResTreeNode*)b;
5654 return t1->id - t2->id;
5658 * resource_tree_create:
5660 * Organize the resources into a resource tree.
5662 static ResTreeNode *
5663 resource_tree_create (MonoArray *win32_resources)
5665 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5669 tree = g_new0 (ResTreeNode, 1);
5671 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5672 MonoReflectionWin32Resource *win32_res =
5673 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5677 /* FIXME: BUG: this stores managed references in unmanaged memory */
5678 lang_node = g_new0 (ResTreeNode, 1);
5679 lang_node->id = win32_res->lang_id;
5680 lang_node->win32_res = win32_res;
5682 /* Create type node if neccesary */
5684 for (l = tree->children; l; l = l->next)
5685 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5686 type_node = (ResTreeNode*)l->data;
5691 type_node = g_new0 (ResTreeNode, 1);
5692 type_node->id = win32_res->res_type;
5695 * The resource types have to be sorted otherwise
5696 * Windows Explorer can't display the version information.
5698 tree->children = g_slist_insert_sorted (tree->children,
5699 type_node, resource_tree_compare_by_id);
5702 /* Create res node if neccesary */
5704 for (l = type_node->children; l; l = l->next)
5705 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5706 res_node = (ResTreeNode*)l->data;
5711 res_node = g_new0 (ResTreeNode, 1);
5712 res_node->id = win32_res->res_id;
5713 type_node->children = g_slist_append (type_node->children, res_node);
5716 res_node->children = g_slist_append (res_node->children, lang_node);
5723 * resource_tree_encode:
5725 * Encode the resource tree into the format used in the PE file.
5728 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5731 MonoPEResourceDir dir;
5732 MonoPEResourceDirEntry dir_entry;
5733 MonoPEResourceDataEntry data_entry;
5735 guint32 res_id_entries;
5738 * For the format of the resource directory, see the article
5739 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5743 memset (&dir, 0, sizeof (dir));
5744 memset (&dir_entry, 0, sizeof (dir_entry));
5745 memset (&data_entry, 0, sizeof (data_entry));
5747 g_assert (sizeof (dir) == 16);
5748 g_assert (sizeof (dir_entry) == 8);
5749 g_assert (sizeof (data_entry) == 16);
5751 node->offset = p - begin;
5753 /* IMAGE_RESOURCE_DIRECTORY */
5754 res_id_entries = g_slist_length (node->children);
5755 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5757 memcpy (p, &dir, sizeof (dir));
5760 /* Reserve space for entries */
5762 p += sizeof (dir_entry) * res_id_entries;
5764 /* Write children */
5765 for (l = node->children; l; l = l->next) {
5766 ResTreeNode *child = (ResTreeNode*)l->data;
5768 if (child->win32_res) {
5771 child->offset = p - begin;
5773 /* IMAGE_RESOURCE_DATA_ENTRY */
5774 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5775 size = mono_array_length (child->win32_res->res_data);
5776 data_entry.rde_size = GUINT32_TO_LE (size);
5778 memcpy (p, &data_entry, sizeof (data_entry));
5779 p += sizeof (data_entry);
5781 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5784 resource_tree_encode (child, begin, p, &p);
5788 /* IMAGE_RESOURCE_ENTRY */
5789 for (l = node->children; l; l = l->next) {
5790 ResTreeNode *child = (ResTreeNode*)l->data;
5792 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5793 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5795 memcpy (entries, &dir_entry, sizeof (dir_entry));
5796 entries += sizeof (dir_entry);
5803 resource_tree_free (ResTreeNode * node)
5806 for (list = node->children; list; list = list->next)
5807 resource_tree_free ((ResTreeNode*)list->data);
5808 g_slist_free(node->children);
5813 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5818 MonoReflectionWin32Resource *win32_res;
5821 if (!assemblyb->win32_resources)
5825 * Resources are stored in a three level tree inside the PE file.
5826 * - level one contains a node for each type of resource
5827 * - level two contains a node for each resource
5828 * - level three contains a node for each instance of a resource for a
5829 * specific language.
5832 tree = resource_tree_create (assemblyb->win32_resources);
5834 /* Estimate the size of the encoded tree */
5836 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5837 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5838 size += mono_array_length (win32_res->res_data);
5840 /* Directory structure */
5841 size += mono_array_length (assemblyb->win32_resources) * 256;
5842 p = buf = (char *)g_malloc (size);
5844 resource_tree_encode (tree, p, p, &p);
5846 g_assert (p - buf <= size);
5848 assembly->win32_res = (char *)g_malloc (p - buf);
5849 assembly->win32_res_size = p - buf;
5850 memcpy (assembly->win32_res, buf, p - buf);
5853 resource_tree_free (tree);
5857 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5859 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5862 p += sizeof (MonoPEResourceDir);
5863 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5864 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5865 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5866 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5867 fixup_resource_directory (res_section, child, rva);
5869 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5870 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5873 p += sizeof (MonoPEResourceDirEntry);
5878 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5881 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5882 g_error ("WriteFile returned %d\n", GetLastError ());
5886 * mono_image_create_pefile:
5887 * @mb: a module builder object
5889 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5890 * assembly->pefile where it can be easily retrieved later in chunks.
5893 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5895 MonoMSDOSHeader *msdos;
5896 MonoDotNetHeader *header;
5897 MonoSectionTable *section;
5898 MonoCLIHeader *cli_header;
5899 guint32 size, image_size, virtual_base, text_offset;
5900 guint32 header_start, section_start, file_offset, virtual_offset;
5901 MonoDynamicImage *assembly;
5902 MonoReflectionAssemblyBuilder *assemblyb;
5903 MonoDynamicStream pefile_stream = {0};
5904 MonoDynamicStream *pefile = &pefile_stream;
5906 guint32 *rva, value;
5908 static const unsigned char msheader[] = {
5909 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5910 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5913 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5914 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5915 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5916 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5919 assemblyb = mb->assemblyb;
5921 mono_image_basic_init (assemblyb);
5922 assembly = mb->dynamic_image;
5924 assembly->pe_kind = assemblyb->pe_kind;
5925 assembly->machine = assemblyb->machine;
5926 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5927 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5929 mono_image_build_metadata (mb);
5931 if (mb->is_main && assemblyb->resources) {
5932 int len = mono_array_length (assemblyb->resources);
5933 for (i = 0; i < len; ++i)
5934 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5937 if (mb->resources) {
5938 int len = mono_array_length (mb->resources);
5939 for (i = 0; i < len; ++i)
5940 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5943 build_compressed_metadata (assembly);
5946 assembly_add_win32_resources (assembly, assemblyb);
5948 nsections = calc_section_size (assembly);
5950 /* The DOS header and stub */
5951 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5952 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5954 /* the dotnet header */
5955 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5957 /* the section tables */
5958 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5960 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5961 virtual_offset = VIRT_ALIGN;
5964 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5965 if (!assembly->sections [i].size)
5968 file_offset += FILE_ALIGN - 1;
5969 file_offset &= ~(FILE_ALIGN - 1);
5970 virtual_offset += VIRT_ALIGN - 1;
5971 virtual_offset &= ~(VIRT_ALIGN - 1);
5973 assembly->sections [i].offset = file_offset;
5974 assembly->sections [i].rva = virtual_offset;
5976 file_offset += assembly->sections [i].size;
5977 virtual_offset += assembly->sections [i].size;
5978 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5981 file_offset += FILE_ALIGN - 1;
5982 file_offset &= ~(FILE_ALIGN - 1);
5984 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5986 /* back-patch info */
5987 msdos = (MonoMSDOSHeader*)pefile->data;
5988 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5990 header = (MonoDotNetHeader*)(pefile->data + header_start);
5991 header->pesig [0] = 'P';
5992 header->pesig [1] = 'E';
5994 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5995 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5996 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5997 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5998 if (assemblyb->pekind == 1) {
6000 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6003 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6006 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6008 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6009 header->pe.pe_major = 6;
6010 header->pe.pe_minor = 0;
6011 size = assembly->sections [MONO_SECTION_TEXT].size;
6012 size += FILE_ALIGN - 1;
6013 size &= ~(FILE_ALIGN - 1);
6014 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6015 size = assembly->sections [MONO_SECTION_RSRC].size;
6016 size += FILE_ALIGN - 1;
6017 size &= ~(FILE_ALIGN - 1);
6018 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6019 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6020 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6021 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6022 /* pe_rva_entry_point always at the beginning of the text section */
6023 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6025 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6026 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6027 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6028 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6029 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6030 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6031 size = section_start;
6032 size += FILE_ALIGN - 1;
6033 size &= ~(FILE_ALIGN - 1);
6034 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6036 size += VIRT_ALIGN - 1;
6037 size &= ~(VIRT_ALIGN - 1);
6038 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6041 // Translate the PEFileKind value to the value expected by the Windows loader
6047 // PEFileKinds.Dll == 1
6048 // PEFileKinds.ConsoleApplication == 2
6049 // PEFileKinds.WindowApplication == 3
6052 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6053 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6055 if (assemblyb->pekind == 3)
6060 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6062 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6063 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6064 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6065 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6066 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6067 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6069 /* fill data directory entries */
6071 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6072 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6074 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6075 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6077 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6078 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6079 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6080 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6081 /* patch entrypoint name */
6082 if (assemblyb->pekind == 1)
6083 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6085 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6086 /* patch imported function RVA name */
6087 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6088 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6090 /* the import table */
6091 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6092 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6093 /* patch imported dll RVA name and other entries in the dir */
6094 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6095 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6096 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6097 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6098 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6099 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6101 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6102 value = (assembly->text_rva + assembly->imp_names_offset);
6103 *p++ = (value) & 0xff;
6104 *p++ = (value >> 8) & (0xff);
6105 *p++ = (value >> 16) & (0xff);
6106 *p++ = (value >> 24) & (0xff);
6108 /* the CLI header info */
6109 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6110 cli_header->ch_size = GUINT32_FROM_LE (72);
6111 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6112 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6113 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6114 if (assemblyb->entry_point) {
6115 guint32 table_idx = 0;
6116 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6117 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6118 table_idx = methodb->table_idx;
6120 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6122 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6124 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6126 /* The embedded managed resources */
6127 text_offset = assembly->text_rva + assembly->code.index;
6128 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6129 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6130 text_offset += assembly->resources.index;
6131 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6132 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6133 text_offset += assembly->meta_size;
6134 if (assembly->strong_name_size) {
6135 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6136 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6137 text_offset += assembly->strong_name_size;
6140 /* write the section tables and section content */
6141 section = (MonoSectionTable*)(pefile->data + section_start);
6142 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6143 static const char section_names [][7] = {
6144 ".text", ".rsrc", ".reloc"
6146 if (!assembly->sections [i].size)
6148 strcpy (section->st_name, section_names [i]);
6149 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6150 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6151 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6152 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6153 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6154 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6155 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6159 checked_write_file (file, pefile->data, pefile->index);
6161 mono_dynamic_stream_reset (pefile);
6163 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6164 if (!assembly->sections [i].size)
6167 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6168 g_error ("SetFilePointer returned %d\n", GetLastError ());
6171 case MONO_SECTION_TEXT:
6172 /* patch entry point */
6173 p = (guchar*)(assembly->code.data + 2);
6174 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6175 *p++ = (value) & 0xff;
6176 *p++ = (value >> 8) & 0xff;
6177 *p++ = (value >> 16) & 0xff;
6178 *p++ = (value >> 24) & 0xff;
6180 checked_write_file (file, assembly->code.data, assembly->code.index);
6181 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6182 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6183 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6186 g_free (assembly->image.raw_metadata);
6188 case MONO_SECTION_RELOC: {
6192 guint16 type_and_offset;
6196 g_assert (sizeof (reloc) == 12);
6198 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6199 reloc.block_size = GUINT32_FROM_LE (12);
6202 * the entrypoint is always at the start of the text section
6203 * 3 is IMAGE_REL_BASED_HIGHLOW
6204 * 2 is patch_size_rva - text_rva
6206 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6209 checked_write_file (file, &reloc, sizeof (reloc));
6213 case MONO_SECTION_RSRC:
6214 if (assembly->win32_res) {
6216 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6217 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6218 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6222 g_assert_not_reached ();
6226 /* check that the file is properly padded */
6227 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6228 g_error ("SetFilePointer returned %d\n", GetLastError ());
6229 if (! SetEndOfFile (file))
6230 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6232 mono_dynamic_stream_reset (&assembly->code);
6233 mono_dynamic_stream_reset (&assembly->us);
6234 mono_dynamic_stream_reset (&assembly->blob);
6235 mono_dynamic_stream_reset (&assembly->guid);
6236 mono_dynamic_stream_reset (&assembly->sheap);
6238 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6239 g_hash_table_destroy (assembly->blob_cache);
6240 assembly->blob_cache = NULL;
6243 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6246 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6248 g_assert_not_reached ();
6251 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6253 #ifndef DISABLE_REFLECTION_EMIT
6255 MonoReflectionModule *
6256 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6260 MonoImageOpenStatus status;
6261 MonoDynamicAssembly *assembly;
6262 guint32 module_count;
6263 MonoImage **new_modules;
6264 gboolean *new_modules_loaded;
6266 name = mono_string_to_utf8 (fileName);
6268 image = mono_image_open (name, &status);
6271 if (status == MONO_IMAGE_ERROR_ERRNO)
6272 exc = mono_get_exception_file_not_found (fileName);
6274 exc = mono_get_exception_bad_image_format (name);
6276 mono_raise_exception (exc);
6281 assembly = ab->dynamic_assembly;
6282 image->assembly = (MonoAssembly*)assembly;
6284 module_count = image->assembly->image->module_count;
6285 new_modules = g_new0 (MonoImage *, module_count + 1);
6286 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6288 if (image->assembly->image->modules)
6289 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6290 if (image->assembly->image->modules_loaded)
6291 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6292 new_modules [module_count] = image;
6293 new_modules_loaded [module_count] = TRUE;
6294 mono_image_addref (image);
6296 g_free (image->assembly->image->modules);
6297 image->assembly->image->modules = new_modules;
6298 image->assembly->image->modules_loaded = new_modules_loaded;
6299 image->assembly->image->module_count ++;
6301 mono_assembly_load_references (image, &status);
6303 mono_image_close (image);
6304 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6307 return mono_module_get_object (mono_domain_get (), image);
6310 #endif /* DISABLE_REFLECTION_EMIT */
6313 * We need to return always the same object for MethodInfo, FieldInfo etc..
6314 * but we need to consider the reflected type.
6315 * type uses a different hash, since it uses custom hash/equal functions.
6320 MonoClass *refclass;
6324 reflected_equal (gconstpointer a, gconstpointer b) {
6325 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6326 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6328 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6332 reflected_hash (gconstpointer a) {
6333 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6334 return mono_aligned_addr_hash (ea->item);
6337 #define CHECK_OBJECT(t,p,k) \
6343 mono_domain_lock (domain); \
6344 if (!domain->refobject_hash) \
6345 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6346 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6347 mono_domain_unlock (domain); \
6350 mono_domain_unlock (domain); \
6353 #ifdef HAVE_BOEHM_GC
6354 /* ReflectedEntry doesn't need to be GC tracked */
6355 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6356 #define FREE_REFENTRY(entry) g_free ((entry))
6357 #define REFENTRY_REQUIRES_CLEANUP
6359 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6361 #define FREE_REFENTRY(entry)
6364 #define CACHE_OBJECT(t,p,o,k) \
6367 ReflectedEntry pe; \
6369 pe.refclass = (k); \
6370 mono_domain_lock (domain); \
6371 if (!domain->refobject_hash) \
6372 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6373 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6375 ReflectedEntry *e = ALLOC_REFENTRY; \
6377 e->refclass = (k); \
6378 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6381 mono_domain_unlock (domain); \
6386 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6388 mono_domain_lock (domain);
6389 if (domain->refobject_hash) {
6391 gpointer orig_pe, orig_value;
6394 pe.refclass = klass;
6395 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6396 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6397 FREE_REFENTRY (orig_pe);
6400 mono_domain_unlock (domain);
6403 #ifdef REFENTRY_REQUIRES_CLEANUP
6405 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6407 FREE_REFENTRY (key);
6412 mono_reflection_cleanup_domain (MonoDomain *domain)
6414 if (domain->refobject_hash) {
6415 /*let's avoid scanning the whole hashtable if not needed*/
6416 #ifdef REFENTRY_REQUIRES_CLEANUP
6417 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6419 mono_g_hash_table_destroy (domain->refobject_hash);
6420 domain->refobject_hash = NULL;
6424 #ifndef DISABLE_REFLECTION_EMIT
6426 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6428 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6432 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6434 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6438 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6440 MonoDynamicImage *image = moduleb->dynamic_image;
6441 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6445 MonoImage **new_modules;
6447 char *name, *fqname;
6449 * FIXME: we already created an image in mono_image_basic_init (), but
6450 * we don't know which module it belongs to, since that is only
6451 * determined at assembly save time.
6453 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6454 name = mono_string_to_utf8 (ab->name);
6455 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6456 if (!mono_error_ok (&error)) {
6458 mono_error_raise_exception (&error);
6460 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6462 moduleb->module.image = &image->image;
6463 moduleb->dynamic_image = image;
6464 register_module (mono_object_domain (moduleb), moduleb, image);
6466 /* register the module with the assembly */
6467 ass = ab->dynamic_assembly->assembly.image;
6468 module_count = ass->module_count;
6469 new_modules = g_new0 (MonoImage *, module_count + 1);
6472 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6473 new_modules [module_count] = &image->image;
6474 mono_image_addref (&image->image);
6476 g_free (ass->modules);
6477 ass->modules = new_modules;
6478 ass->module_count ++;
6483 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6485 MonoDynamicImage *image = moduleb->dynamic_image;
6487 g_assert (type->type);
6488 image->wrappers_type = mono_class_from_mono_type (type->type);
6494 * mono_assembly_get_object:
6495 * @domain: an app domain
6496 * @assembly: an assembly
6498 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6500 MonoReflectionAssembly*
6501 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6503 static MonoClass *assembly_type;
6504 MonoReflectionAssembly *res;
6506 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6507 if (!assembly_type) {
6508 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6510 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6512 assembly_type = klass;
6514 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6515 res->assembly = assembly;
6517 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6522 MonoReflectionModule*
6523 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6525 static MonoClass *module_type;
6526 MonoReflectionModule *res;
6529 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6531 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6533 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6535 module_type = klass;
6537 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6540 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6542 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6543 basename = g_path_get_basename (image->name);
6544 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6545 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6549 if (image->assembly->image == image) {
6550 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6554 if (image->assembly->image->modules) {
6555 for (i = 0; i < image->assembly->image->module_count; i++) {
6556 if (image->assembly->image->modules [i] == image)
6557 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6559 g_assert (res->token);
6563 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6566 MonoReflectionModule*
6567 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6569 static MonoClass *module_type;
6570 MonoReflectionModule *res;
6571 MonoTableInfo *table;
6572 guint32 cols [MONO_FILE_SIZE];
6574 guint32 i, name_idx;
6578 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6580 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6582 module_type = klass;
6584 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6586 table = &image->tables [MONO_TABLE_FILE];
6587 g_assert (table_index < table->rows);
6588 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6591 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6592 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6594 /* Check whenever the row has a corresponding row in the moduleref table */
6595 table = &image->tables [MONO_TABLE_MODULEREF];
6596 for (i = 0; i < table->rows; ++i) {
6597 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6598 val = mono_metadata_string_heap (image, name_idx);
6599 if (strcmp (val, name) == 0)
6600 res->image = image->modules [i];
6603 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6604 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6605 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6606 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6607 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6613 verify_safe_for_managed_space (MonoType *type)
6615 switch (type->type) {
6617 case MONO_TYPE_ARRAY:
6618 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6620 return verify_safe_for_managed_space (type->data.type);
6621 case MONO_TYPE_SZARRAY:
6622 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6623 case MONO_TYPE_GENERICINST: {
6624 MonoGenericInst *inst = type->data.generic_class->inst;
6628 for (i = 0; i < inst->type_argc; ++i)
6629 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6635 case MONO_TYPE_MVAR:
6643 mono_type_normalize (MonoType *type)
6646 MonoGenericClass *gclass;
6647 MonoGenericInst *ginst;
6649 MonoGenericContainer *gcontainer;
6650 MonoType **argv = NULL;
6651 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6653 if (type->type != MONO_TYPE_GENERICINST)
6656 gclass = type->data.generic_class;
6657 ginst = gclass->context.class_inst;
6658 if (!ginst->is_open)
6661 gtd = gclass->container_class;
6662 gcontainer = gtd->generic_container;
6663 argv = g_newa (MonoType*, ginst->type_argc);
6665 for (i = 0; i < ginst->type_argc; ++i) {
6666 MonoType *t = ginst->type_argv [i], *norm;
6667 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6668 is_denorm_gtd = FALSE;
6669 norm = mono_type_normalize (t);
6672 requires_rebind = TRUE;
6676 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6678 if (requires_rebind) {
6679 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6680 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6686 * mono_type_get_object:
6687 * @domain: an app domain
6690 * Return an System.MonoType object representing the type @type.
6693 mono_type_get_object (MonoDomain *domain, MonoType *type)
6696 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6697 mono_error_raise_exception (&error);
6703 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6705 MonoType *norm_type;
6706 MonoReflectionType *res;
6709 mono_error_init (error);
6711 klass = mono_class_from_mono_type (type);
6713 /*we must avoid using @type as it might have come
6714 * from a mono_metadata_type_dup and the caller
6715 * expects that is can be freed.
6716 * Using the right type from
6718 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6720 /* void is very common */
6721 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6722 return (MonoReflectionType*)domain->typeof_void;
6725 * If the vtable of the given class was already created, we can use
6726 * the MonoType from there and avoid all locking and hash table lookups.
6728 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6729 * that the resulting object is different.
6731 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6732 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6733 if (vtable && vtable->type)
6734 return (MonoReflectionType *)vtable->type;
6737 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6738 mono_domain_lock (domain);
6739 if (!domain->type_hash)
6740 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6741 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6742 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6743 mono_domain_unlock (domain);
6744 mono_loader_unlock ();
6748 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6749 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6750 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6751 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6752 * artifact of how generics are encoded and should be transparent to managed code so we
6753 * need to weed out this diference when retrieving managed System.Type objects.
6755 norm_type = mono_type_normalize (type);
6756 if (norm_type != type) {
6757 res = mono_type_get_object_checked (domain, norm_type, error);
6758 if (!mono_error_ok (error))
6760 mono_g_hash_table_insert (domain->type_hash, type, res);
6761 mono_domain_unlock (domain);
6762 mono_loader_unlock ();
6766 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6767 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6770 if (!verify_safe_for_managed_space (type)) {
6771 mono_domain_unlock (domain);
6772 mono_loader_unlock ();
6773 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6776 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6777 gboolean is_type_done = TRUE;
6778 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6779 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6780 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6782 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6783 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6785 if (gparam->owner && gparam->owner->is_method) {
6786 MonoMethod *method = gparam->owner->owner.method;
6787 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6788 is_type_done = FALSE;
6789 } else if (gparam->owner && !gparam->owner->is_method) {
6790 MonoClass *klass = gparam->owner->owner.klass;
6791 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6792 is_type_done = FALSE;
6796 /* g_assert_not_reached (); */
6797 /* should this be considered an error condition? */
6798 if (is_type_done && !type->byref) {
6799 mono_domain_unlock (domain);
6800 mono_loader_unlock ();
6801 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6804 /* This is stored in vtables/JITted code so it has to be pinned */
6805 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6806 if (!mono_error_ok (error))
6810 mono_g_hash_table_insert (domain->type_hash, type, res);
6812 if (type->type == MONO_TYPE_VOID)
6813 domain->typeof_void = (MonoObject*)res;
6815 mono_domain_unlock (domain);
6816 mono_loader_unlock ();
6821 * mono_method_get_object:
6822 * @domain: an app domain
6824 * @refclass: the reflected type (can be NULL)
6826 * Return an System.Reflection.MonoMethod object representing the method @method.
6828 MonoReflectionMethod*
6829 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6832 * We use the same C representation for methods and constructors, but the type
6833 * name in C# is different.
6835 static MonoClass *System_Reflection_MonoMethod = NULL;
6836 static MonoClass *System_Reflection_MonoCMethod = NULL;
6837 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6838 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6840 MonoReflectionType *rt;
6842 MonoReflectionMethod *ret;
6844 if (method->is_inflated) {
6845 MonoReflectionGenericMethod *gret;
6848 refclass = method->klass;
6849 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6850 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6851 if (!System_Reflection_MonoGenericCMethod)
6852 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6853 klass = System_Reflection_MonoGenericCMethod;
6855 if (!System_Reflection_MonoGenericMethod)
6856 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6857 klass = System_Reflection_MonoGenericMethod;
6859 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6860 gret->method.method = method;
6862 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6864 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6865 mono_error_raise_exception (&error); /* FIXME don't raise here */
6867 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6869 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6873 refclass = method->klass;
6875 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6876 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6877 if (!System_Reflection_MonoCMethod)
6878 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6879 klass = System_Reflection_MonoCMethod;
6882 if (!System_Reflection_MonoMethod)
6883 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6884 klass = System_Reflection_MonoMethod;
6886 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6887 ret->method = method;
6889 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6890 mono_error_raise_exception (&error); /* FIXME don't raise here */;
6892 MONO_OBJECT_SETREF (ret, reftype, rt);
6894 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6898 * mono_method_clear_object:
6900 * Clear the cached reflection objects for the dynamic method METHOD.
6903 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6906 g_assert (method_is_dynamic (method));
6908 klass = method->klass;
6910 clear_cached_object (domain, method, klass);
6911 klass = klass->parent;
6913 /* Added by mono_param_get_objects () */
6914 clear_cached_object (domain, &(method->signature), NULL);
6915 klass = method->klass;
6917 clear_cached_object (domain, &(method->signature), klass);
6918 klass = klass->parent;
6923 * mono_field_get_object:
6924 * @domain: an app domain
6928 * Return an System.Reflection.MonoField object representing the field @field
6931 MonoReflectionField*
6932 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6935 MonoReflectionType *rt;
6936 MonoReflectionField *res;
6937 static MonoClass *monofield_klass;
6939 CHECK_OBJECT (MonoReflectionField *, field, klass);
6940 if (!monofield_klass)
6941 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6942 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6945 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6947 if (is_field_on_inst (field)) {
6948 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6950 rt = mono_type_get_object_checked (domain, field->type, &error);
6951 mono_error_raise_exception (&error); /* FIXME don't raise here */
6953 MONO_OBJECT_SETREF (res, type, rt);
6956 rt = mono_type_get_object_checked (domain, field->type, &error);
6957 mono_error_raise_exception (&error); /* FIXME don't raise here */
6959 MONO_OBJECT_SETREF (res, type, rt);
6961 res->attrs = mono_field_get_flags (field);
6963 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6967 * mono_property_get_object:
6968 * @domain: an app domain
6970 * @property: a property
6972 * Return an System.Reflection.MonoProperty object representing the property @property
6975 MonoReflectionProperty*
6976 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6978 MonoReflectionProperty *res;
6979 static MonoClass *monoproperty_klass;
6981 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6982 if (!monoproperty_klass)
6983 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6984 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6986 res->property = property;
6987 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6991 * mono_event_get_object:
6992 * @domain: an app domain
6996 * Return an System.Reflection.MonoEvent object representing the event @event
6999 MonoReflectionEvent*
7000 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7002 MonoReflectionEvent *res;
7003 MonoReflectionMonoEvent *mono_event;
7004 static MonoClass *monoevent_klass;
7006 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7007 if (!monoevent_klass)
7008 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7009 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
7010 mono_event->klass = klass;
7011 mono_event->event = event;
7012 res = (MonoReflectionEvent*)mono_event;
7013 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7017 * mono_get_reflection_missing_object:
7018 * @domain: Domain where the object lives
7020 * Returns the System.Reflection.Missing.Value singleton object
7021 * (of type System.Reflection.Missing).
7023 * Used as the value for ParameterInfo.DefaultValue when Optional
7027 mono_get_reflection_missing_object (MonoDomain *domain)
7030 static MonoClassField *missing_value_field = NULL;
7032 if (!missing_value_field) {
7033 MonoClass *missing_klass;
7034 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7035 mono_class_init (missing_klass);
7036 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7037 g_assert (missing_value_field);
7039 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7045 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7048 *dbnull = mono_get_dbnull_object (domain);
7053 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7055 if (!*reflection_missing)
7056 *reflection_missing = mono_get_reflection_missing_object (domain);
7057 return *reflection_missing;
7061 * mono_param_get_objects:
7062 * @domain: an app domain
7065 * Return an System.Reflection.ParameterInfo array object representing the parameters
7066 * in the method @method.
7069 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7071 static MonoClass *System_Reflection_ParameterInfo;
7072 static MonoClass *System_Reflection_ParameterInfo_array;
7074 MonoArray *res = NULL;
7075 MonoReflectionMethod *member = NULL;
7076 MonoReflectionParameter *param = NULL;
7077 char **names, **blobs = NULL;
7078 guint32 *types = NULL;
7079 MonoType *type = NULL;
7080 MonoObject *dbnull = NULL;
7081 MonoObject *missing = NULL;
7082 MonoMarshalSpec **mspecs;
7083 MonoMethodSignature *sig;
7084 MonoVTable *pinfo_vtable;
7085 MonoReflectionType *rt;
7088 if (!System_Reflection_ParameterInfo_array) {
7091 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7093 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7095 mono_memory_barrier ();
7096 System_Reflection_ParameterInfo = klass;
7099 klass = mono_array_class_get (klass, 1);
7100 mono_memory_barrier ();
7101 System_Reflection_ParameterInfo_array = klass;
7104 sig = mono_method_signature_checked (method, &error);
7105 if (!mono_error_ok (&error))
7106 mono_error_raise_exception (&error);
7108 if (!sig->param_count) {
7109 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7110 mono_error_raise_exception (&error); /* FIXME don't raise here */
7115 /* Note: the cache is based on the address of the signature into the method
7116 * since we already cache MethodInfos with the method as keys.
7118 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7120 member = mono_method_get_object (domain, method, refclass);
7121 names = g_new (char *, sig->param_count);
7122 mono_method_get_param_names (method, (const char **) names);
7124 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7125 mono_method_get_marshal_info (method, mspecs);
7127 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7128 mono_error_raise_exception (&error); /* FIXME don't raise here */
7130 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7131 for (i = 0; i < sig->param_count; ++i) {
7132 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7133 mono_error_raise_exception (&error); /* FIXME don't raise here */
7135 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7136 mono_error_raise_exception (&error); /* FIXME don't raise here */
7138 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7140 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7142 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7144 param->PositionImpl = i;
7145 param->AttrsImpl = sig->params [i]->attrs;
7147 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7148 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7149 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7151 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7155 blobs = g_new0 (char *, sig->param_count);
7156 types = g_new0 (guint32, sig->param_count);
7157 get_default_param_value_blobs (method, blobs, types);
7160 /* Build MonoType for the type from the Constant Table */
7162 type = g_new0 (MonoType, 1);
7163 type->type = (MonoTypeEnum)types [i];
7164 type->data.klass = NULL;
7165 if (types [i] == MONO_TYPE_CLASS)
7166 type->data.klass = mono_defaults.object_class;
7167 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7168 /* For enums, types [i] contains the base type */
7170 type->type = MONO_TYPE_VALUETYPE;
7171 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7173 type->data.klass = mono_class_from_mono_type (type);
7175 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7177 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7178 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7179 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7180 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7182 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7188 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7190 mono_array_setref (res, i, param);
7197 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7199 mono_metadata_free_marshal_spec (mspecs [i]);
7202 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7206 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7208 return mono_param_get_objects_internal (domain, method, NULL);
7212 * mono_method_body_get_object:
7213 * @domain: an app domain
7216 * Return an System.Reflection.MethodBody object representing the method @method.
7218 MonoReflectionMethodBody*
7219 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7221 static MonoClass *System_Reflection_MethodBody = NULL;
7222 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7223 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7225 MonoReflectionMethodBody *ret;
7226 MonoMethodHeader *header;
7228 MonoReflectionType *rt;
7229 guint32 method_rva, local_var_sig_token;
7231 unsigned char format, flags;
7234 /* for compatibility with .net */
7235 if (method_is_dynamic (method))
7236 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7238 if (!System_Reflection_MethodBody)
7239 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7240 if (!System_Reflection_LocalVariableInfo)
7241 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7242 if (!System_Reflection_ExceptionHandlingClause)
7243 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7245 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7247 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7248 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7249 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7250 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7251 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7254 image = method->klass->image;
7255 header = mono_method_get_header (method);
7257 if (!image_is_dynamic (image)) {
7258 /* Obtain local vars signature token */
7259 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7260 ptr = mono_image_rva_map (image, method_rva);
7261 flags = *(const unsigned char *) ptr;
7262 format = flags & METHOD_HEADER_FORMAT_MASK;
7264 case METHOD_HEADER_TINY_FORMAT:
7265 local_var_sig_token = 0;
7267 case METHOD_HEADER_FAT_FORMAT:
7271 local_var_sig_token = read32 (ptr);
7274 g_assert_not_reached ();
7277 local_var_sig_token = 0; //FIXME
7279 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7281 ret->init_locals = header->init_locals;
7282 ret->max_stack = header->max_stack;
7283 ret->local_var_sig_token = local_var_sig_token;
7284 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7285 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7288 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7289 for (i = 0; i < header->num_locals; ++i) {
7290 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7292 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7293 mono_error_raise_exception (&error); /* FIXME don't raise here */
7295 MONO_OBJECT_SETREF (info, local_type, rt);
7297 info->is_pinned = header->locals [i]->pinned;
7298 info->local_index = i;
7299 mono_array_setref (ret->locals, i, info);
7303 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7304 for (i = 0; i < header->num_clauses; ++i) {
7305 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7306 MonoExceptionClause *clause = &header->clauses [i];
7308 info->flags = clause->flags;
7309 info->try_offset = clause->try_offset;
7310 info->try_length = clause->try_len;
7311 info->handler_offset = clause->handler_offset;
7312 info->handler_length = clause->handler_len;
7313 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7314 info->filter_offset = clause->data.filter_offset;
7315 else if (clause->data.catch_class) {
7316 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7317 mono_error_raise_exception (&error); /* FIXME don't raise here */
7319 MONO_OBJECT_SETREF (info, catch_type, rt);
7322 mono_array_setref (ret->clauses, i, info);
7325 mono_metadata_free_mh (header);
7326 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7331 * mono_get_dbnull_object:
7332 * @domain: Domain where the object lives
7334 * Returns the System.DBNull.Value singleton object
7336 * Used as the value for ParameterInfo.DefaultValue
7339 mono_get_dbnull_object (MonoDomain *domain)
7342 static MonoClassField *dbnull_value_field = NULL;
7344 if (!dbnull_value_field) {
7345 MonoClass *dbnull_klass;
7346 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7347 mono_class_init (dbnull_klass);
7348 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7349 g_assert (dbnull_value_field);
7351 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7357 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7359 guint32 param_index, i, lastp, crow = 0;
7360 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7363 MonoClass *klass = method->klass;
7364 MonoImage *image = klass->image;
7365 MonoMethodSignature *methodsig = mono_method_signature (method);
7367 MonoTableInfo *constt;
7368 MonoTableInfo *methodt;
7369 MonoTableInfo *paramt;
7371 if (!methodsig->param_count)
7374 mono_class_init (klass);
7376 if (image_is_dynamic (klass->image)) {
7377 MonoReflectionMethodAux *aux;
7378 if (method->is_inflated)
7379 method = ((MonoMethodInflated*)method)->declaring;
7380 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7381 if (aux && aux->param_defaults) {
7382 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7383 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7388 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7389 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7390 constt = &image->tables [MONO_TABLE_CONSTANT];
7392 idx = mono_method_get_index (method) - 1;
7393 g_assert (idx != -1);
7395 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7396 if (idx + 1 < methodt->rows)
7397 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7399 lastp = paramt->rows + 1;
7401 for (i = param_index; i < lastp; ++i) {
7404 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7405 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7407 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7410 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7415 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7416 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7417 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7424 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7429 MonoType *basetype = type;
7434 klass = mono_class_from_mono_type (type);
7435 if (klass->valuetype) {
7436 object = mono_object_new (domain, klass);
7437 retval = ((gchar *) object + sizeof (MonoObject));
7438 if (klass->enumtype)
7439 basetype = mono_class_enum_basetype (klass);
7444 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7451 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7454 gboolean quoted = FALSE;
7456 memset (assembly, 0, sizeof (MonoAssemblyName));
7457 assembly->culture = "";
7458 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7465 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7476 /* Remove trailing whitespace */
7478 while (*s && g_ascii_isspace (*s))
7481 while (g_ascii_isspace (*p))
7484 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7486 assembly->major = strtoul (p, &s, 10);
7487 if (s == p || *s != '.')
7490 assembly->minor = strtoul (p, &s, 10);
7491 if (s == p || *s != '.')
7494 assembly->build = strtoul (p, &s, 10);
7495 if (s == p || *s != '.')
7498 assembly->revision = strtoul (p, &s, 10);
7502 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7504 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7505 assembly->culture = "";
7508 assembly->culture = p;
7509 while (*p && *p != ',') {
7513 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7515 if (strncmp (p, "null", 4) == 0) {
7520 while (*p && *p != ',') {
7523 len = (p - start + 1);
7524 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7525 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7526 g_strlcpy ((char*)assembly->public_key_token, start, len);
7529 while (*p && *p != ',')
7533 while (g_ascii_isspace (*p) || *p == ',') {
7547 * mono_reflection_parse_type:
7550 * Parse a type name as accepted by the GetType () method and output the info
7551 * extracted in the info structure.
7552 * the name param will be mangled, so, make a copy before passing it to this function.
7553 * The fields in info will be valid until the memory pointed to by name is valid.
7555 * See also mono_type_get_name () below.
7557 * Returns: 0 on parse error.
7560 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7561 MonoTypeNameParse *info)
7563 char *start, *p, *w, *last_point, *startn;
7564 int in_modifiers = 0;
7565 int isbyref = 0, rank = 0, isptr = 0;
7567 start = p = w = name;
7569 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7570 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7571 info->name = info->name_space = NULL;
7572 info->nested = NULL;
7573 info->modifiers = NULL;
7574 info->type_arguments = NULL;
7576 /* last_point separates the namespace from the name */
7579 while (*p == ' ') p++, start++, w++, name++;
7584 *p = 0; /* NULL terminate the name */
7586 info->nested = g_list_append (info->nested, startn);
7587 /* we have parsed the nesting namespace + name */
7591 info->name_space = start;
7593 info->name = last_point + 1;
7595 info->name_space = (char *)"";
7623 info->name_space = start;
7625 info->name = last_point + 1;
7627 info->name_space = (char *)"";
7634 if (isbyref) /* only one level allowed by the spec */
7638 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7642 if (isbyref) /* pointer to ref not okay */
7644 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7649 if (isbyref) /* array of ref and generic ref are not okay */
7651 //Decide if it's an array of a generic argument list
7656 if (*p == ',' || *p == '*' || *p == ']') { //array
7664 else if (*p == '*') /* '*' means unknown lower bound */
7665 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7672 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7674 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7677 info->type_arguments = g_ptr_array_new ();
7679 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7680 gboolean fqname = FALSE;
7682 g_ptr_array_add (info->type_arguments, subinfo);
7684 while (*p == ' ') p++;
7690 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7693 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7694 if (fqname && (*p != ']')) {
7702 while (*p && (*p != ']'))
7710 if (g_ascii_isspace (*aname)) {
7717 !assembly_name_to_aname (&subinfo->assembly, aname))
7719 } else if (fqname && (*p == ']')) {
7741 if (g_ascii_isspace (*p)) {
7748 return 0; /* missing assembly name */
7749 if (!assembly_name_to_aname (&info->assembly, p))
7755 if (info->assembly.name)
7758 // *w = 0; /* terminate class name */
7760 if (!info->name || !*info->name)
7764 /* add other consistency checks */
7770 * mono_identifier_unescape_type_name_chars:
7771 * @identifier: the display name of a mono type
7774 * The name in internal form, that is without escaping backslashes.
7776 * The string is modified in place!
7779 mono_identifier_unescape_type_name_chars(char* identifier)
7784 for (w = r = identifier; *r != 0; r++)
7802 mono_identifier_unescape_info (MonoTypeNameParse* info);
7805 unescape_each_type_argument(void* data, void* user_data)
7807 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7808 mono_identifier_unescape_info (info);
7812 unescape_each_nested_name (void* data, void* user_data)
7814 char* nested_name = (char*) data;
7815 mono_identifier_unescape_type_name_chars(nested_name);
7819 * mono_identifier_unescape_info:
7821 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7825 * Destructively updates the info by unescaping the identifiers that
7826 * comprise the type namespace, name, nested types (if any) and
7827 * generic type arguments (if any).
7829 * The resulting info has the names in internal form.
7833 mono_identifier_unescape_info (MonoTypeNameParse *info)
7837 mono_identifier_unescape_type_name_chars(info->name_space);
7838 mono_identifier_unescape_type_name_chars(info->name);
7839 // but don't escape info->assembly
7840 if (info->type_arguments)
7841 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7843 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7847 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7849 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7851 mono_identifier_unescape_info (info);
7857 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7859 gboolean type_resolve = FALSE;
7861 MonoImage *rootimage = image;
7863 if (info->assembly.name) {
7864 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7865 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7867 * This could happen in the AOT compiler case when the search hook is not
7870 assembly = image->assembly;
7872 /* then we must load the assembly ourselve - see #60439 */
7873 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7877 image = assembly->image;
7878 } else if (!image) {
7879 image = mono_defaults.corlib;
7882 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7883 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7884 image = mono_defaults.corlib;
7885 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7892 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7898 gboolean bounded = FALSE;
7901 image = mono_defaults.corlib;
7904 rootimage = mono_defaults.corlib;
7908 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7909 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7911 klass = mono_class_from_name (image, info->name_space, info->name);
7915 for (mod = info->nested; mod; mod = mod->next) {
7916 gpointer iter = NULL;
7920 mono_class_init (parent);
7922 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7924 char *nested_name, *nested_nspace;
7925 gboolean match = TRUE;
7927 lastp = strrchr ((const char *)mod->data, '.');
7929 /* Nested classes can have namespaces */
7932 nested_name = g_strdup (lastp + 1);
7933 nspace_len = lastp - (char*)mod->data;
7934 nested_nspace = (char *)g_malloc (nspace_len + 1);
7935 memcpy (nested_nspace, mod->data, nspace_len);
7936 nested_nspace [nspace_len] = '\0';
7939 nested_name = (char *)mod->data;
7940 nested_nspace = NULL;
7943 if (nested_nspace) {
7945 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7948 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7954 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7957 if (strcmp (klass->name, nested_name) != 0)
7962 g_free (nested_name);
7963 g_free (nested_nspace);
7975 if (info->type_arguments) {
7976 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7977 MonoReflectionType *the_type;
7981 for (i = 0; i < info->type_arguments->len; i++) {
7982 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
7984 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7985 if (!type_args [i]) {
7991 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7992 mono_error_raise_exception (&error); /* FIXME don't raise here */
7994 instance = mono_reflection_bind_generic_parameters (
7995 the_type, info->type_arguments->len, type_args);
8001 klass = mono_class_from_mono_type (instance);
8004 for (mod = info->modifiers; mod; mod = mod->next) {
8005 modval = GPOINTER_TO_UINT (mod->data);
8006 if (!modval) { /* byref: must be last modifier */
8007 return &klass->this_arg;
8008 } else if (modval == -1) {
8009 klass = mono_ptr_class_get (&klass->byval_arg);
8010 } else if (modval == -2) {
8012 } else { /* array rank */
8013 klass = mono_bounded_array_class_get (klass, modval, bounded);
8017 return &klass->byval_arg;
8021 * mono_reflection_get_type:
8022 * @image: a metadata context
8023 * @info: type description structure
8024 * @ignorecase: flag for case-insensitive string compares
8025 * @type_resolve: whenever type resolve was already tried
8027 * Build a MonoType from the type description in @info.
8032 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8033 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8037 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8039 MonoReflectionAssemblyBuilder *abuilder;
8043 g_assert (assembly_is_dynamic (assembly));
8044 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8046 /* Enumerate all modules */
8049 if (abuilder->modules) {
8050 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8051 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8052 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8058 if (!type && abuilder->loaded_modules) {
8059 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8060 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8061 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8071 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8074 MonoReflectionAssembly *assembly;
8078 if (image && image_is_dynamic (image))
8079 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8081 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8084 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8091 *type_resolve = TRUE;
8094 /* Reconstruct the type name */
8095 fullName = g_string_new ("");
8096 if (info->name_space && (info->name_space [0] != '\0'))
8097 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8099 g_string_printf (fullName, "%s", info->name);
8100 for (mod = info->nested; mod; mod = mod->next)
8101 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8103 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8105 if (assembly_is_dynamic (assembly->assembly))
8106 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8108 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8111 g_string_free (fullName, TRUE);
8116 mono_reflection_free_type_info (MonoTypeNameParse *info)
8118 g_list_free (info->modifiers);
8119 g_list_free (info->nested);
8121 if (info->type_arguments) {
8124 for (i = 0; i < info->type_arguments->len; i++) {
8125 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8127 mono_reflection_free_type_info (subinfo);
8128 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8132 g_ptr_array_free (info->type_arguments, TRUE);
8137 * mono_reflection_type_from_name:
8139 * @image: a metadata context (can be NULL).
8141 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8142 * it defaults to get the type from @image or, if @image is NULL or loading
8143 * from it fails, uses corlib.
8147 mono_reflection_type_from_name (char *name, MonoImage *image)
8149 MonoType *type = NULL;
8150 MonoTypeNameParse info;
8153 /* Make a copy since parse_type modifies its argument */
8154 tmp = g_strdup (name);
8156 /*g_print ("requested type %s\n", str);*/
8157 if (mono_reflection_parse_type (tmp, &info)) {
8158 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8162 mono_reflection_free_type_info (&info);
8167 * mono_reflection_get_token:
8169 * Return the metadata token of OBJ which should be an object
8170 * representing a metadata element.
8173 mono_reflection_get_token (MonoObject *obj)
8178 klass = obj->vtable->klass;
8180 if (strcmp (klass->name, "MethodBuilder") == 0) {
8181 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8183 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8184 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8185 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8187 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8188 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8189 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8191 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8192 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8193 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8194 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8195 } else if (strcmp (klass->name, "MonoType") == 0) {
8196 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8197 MonoClass *mc = mono_class_from_mono_type (type);
8198 if (!mono_class_init (mc))
8199 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8201 token = mc->type_token;
8202 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8203 strcmp (klass->name, "MonoMethod") == 0 ||
8204 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8205 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8206 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8207 if (m->method->is_inflated) {
8208 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8209 return inflated->declaring->token;
8211 token = m->method->token;
8213 } else if (strcmp (klass->name, "MonoField") == 0) {
8214 MonoReflectionField *f = (MonoReflectionField*)obj;
8216 if (is_field_on_inst (f->field)) {
8217 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8219 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8220 int field_index = f->field - dgclass->fields;
8223 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8224 obj = dgclass->field_objects [field_index];
8225 return mono_reflection_get_token (obj);
8228 token = mono_class_get_field_token (f->field);
8229 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8230 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8232 token = mono_class_get_property_token (p->property);
8233 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8234 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8236 token = mono_class_get_event_token (p->event);
8237 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8238 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8239 MonoClass *member_class = mono_object_class (p->MemberImpl);
8240 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8242 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8243 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8244 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8247 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8248 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8250 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8251 MonoException *ex = mono_get_exception_not_implemented (msg);
8253 mono_raise_exception (ex);
8260 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8264 int slen = mono_metadata_decode_value (p, &p);
8266 mono_error_init (error);
8268 n = (char *)g_memdup (p, slen + 1);
8270 t = mono_reflection_type_from_name (n, image);
8272 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8273 /* We don't free n, it's consumed by mono_error */
8274 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8280 return mono_class_from_mono_type (t);
8284 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8286 int slen, type = t->type;
8287 MonoClass *tklass = t->data.klass;
8289 mono_error_init (error);
8295 case MONO_TYPE_BOOLEAN: {
8296 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8301 case MONO_TYPE_CHAR:
8303 case MONO_TYPE_I2: {
8304 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8309 #if SIZEOF_VOID_P == 4
8315 case MONO_TYPE_I4: {
8316 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8321 #if SIZEOF_VOID_P == 8
8322 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8326 case MONO_TYPE_I8: {
8327 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8332 case MONO_TYPE_R8: {
8333 double *val = (double *)g_malloc (sizeof (double));
8338 case MONO_TYPE_VALUETYPE:
8339 if (t->data.klass->enumtype) {
8340 type = mono_class_enum_basetype (t->data.klass)->type;
8343 MonoClass *k = t->data.klass;
8345 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8346 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8352 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8355 case MONO_TYPE_STRING:
8356 if (*p == (char)0xFF) {
8360 slen = mono_metadata_decode_value (p, &p);
8362 return mono_string_new_len (mono_domain_get (), p, slen);
8363 case MONO_TYPE_CLASS: {
8364 MonoReflectionType *rt;
8367 if (*p == (char)0xFF) {
8372 slen = mono_metadata_decode_value (p, &p);
8373 n = (char *)g_memdup (p, slen + 1);
8375 t = mono_reflection_type_from_name (n, image);
8377 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8378 /* We don't free n, it's consumed by mono_error */
8379 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8385 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8386 if (!mono_error_ok (error))
8391 case MONO_TYPE_OBJECT: {
8394 MonoClass *subc = NULL;
8399 } else if (subt == 0x0E) {
8400 type = MONO_TYPE_STRING;
8402 } else if (subt == 0x1D) {
8403 MonoType simple_type = {{0}};
8407 type = MONO_TYPE_SZARRAY;
8408 if (etype == 0x50) {
8409 tklass = mono_defaults.systemtype_class;
8410 } else if (etype == 0x55) {
8411 tklass = load_cattr_enum_type (image, p, &p, error);
8412 if (!mono_error_ok (error))
8416 /* See Partition II, Appendix B3 */
8417 etype = MONO_TYPE_OBJECT;
8418 simple_type.type = (MonoTypeEnum)etype;
8419 tklass = mono_class_from_mono_type (&simple_type);
8422 } else if (subt == 0x55) {
8425 slen = mono_metadata_decode_value (p, &p);
8426 n = (char *)g_memdup (p, slen + 1);
8428 t = mono_reflection_type_from_name (n, image);
8430 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8431 /* We don't free n, it's consumed by mono_error */
8432 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8437 subc = mono_class_from_mono_type (t);
8438 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8439 MonoType simple_type = {{0}};
8440 simple_type.type = (MonoTypeEnum)subt;
8441 subc = mono_class_from_mono_type (&simple_type);
8443 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8445 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8447 if (mono_error_ok (error)) {
8448 obj = mono_object_new (mono_domain_get (), subc);
8449 g_assert (!subc->has_references);
8450 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8456 case MONO_TYPE_SZARRAY: {
8458 guint32 i, alen, basetype;
8461 if (alen == 0xffffffff) {
8465 arr = mono_array_new (mono_domain_get(), tklass, alen);
8466 basetype = tklass->byval_arg.type;
8467 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8468 basetype = mono_class_enum_basetype (tklass)->type;
8473 case MONO_TYPE_BOOLEAN:
8474 for (i = 0; i < alen; i++) {
8475 MonoBoolean val = *p++;
8476 mono_array_set (arr, MonoBoolean, i, val);
8479 case MONO_TYPE_CHAR:
8482 for (i = 0; i < alen; i++) {
8483 guint16 val = read16 (p);
8484 mono_array_set (arr, guint16, i, val);
8491 for (i = 0; i < alen; i++) {
8492 guint32 val = read32 (p);
8493 mono_array_set (arr, guint32, i, val);
8498 for (i = 0; i < alen; i++) {
8501 mono_array_set (arr, double, i, val);
8507 for (i = 0; i < alen; i++) {
8508 guint64 val = read64 (p);
8509 mono_array_set (arr, guint64, i, val);
8513 case MONO_TYPE_CLASS:
8514 case MONO_TYPE_OBJECT:
8515 case MONO_TYPE_STRING:
8516 case MONO_TYPE_SZARRAY:
8517 for (i = 0; i < alen; i++) {
8518 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8519 if (!mono_error_ok (error))
8521 mono_array_setref (arr, i, item);
8525 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8531 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8537 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8539 static MonoClass *klass;
8540 static MonoMethod *ctor;
8543 void *params [2], *unboxed;
8546 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8548 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8550 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8551 mono_error_raise_exception (&error); /* FIXME don't raise here */
8554 retval = mono_object_new (mono_domain_get (), klass);
8555 unboxed = mono_object_unbox (retval);
8556 mono_runtime_invoke (ctor, unboxed, params, NULL);
8562 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8564 static MonoClass *klass;
8565 static MonoMethod *ctor;
8567 void *unboxed, *params [2];
8570 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8572 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8575 params [1] = typedarg;
8576 retval = mono_object_new (mono_domain_get (), klass);
8577 unboxed = mono_object_unbox (retval);
8578 mono_runtime_invoke (ctor, unboxed, params, NULL);
8584 type_is_reference (MonoType *type)
8586 switch (type->type) {
8587 case MONO_TYPE_BOOLEAN:
8588 case MONO_TYPE_CHAR:
8601 case MONO_TYPE_VALUETYPE:
8609 free_param_data (MonoMethodSignature *sig, void **params) {
8611 for (i = 0; i < sig->param_count; ++i) {
8612 if (!type_is_reference (sig->params [i]))
8613 g_free (params [i]);
8618 * Find the field index in the metadata FieldDef table.
8621 find_field_index (MonoClass *klass, MonoClassField *field) {
8624 for (i = 0; i < klass->field.count; ++i) {
8625 if (field == &klass->fields [i])
8626 return klass->field.first + 1 + i;
8632 * Find the property index in the metadata Property table.
8635 find_property_index (MonoClass *klass, MonoProperty *property) {
8638 for (i = 0; i < klass->ext->property.count; ++i) {
8639 if (property == &klass->ext->properties [i])
8640 return klass->ext->property.first + 1 + i;
8646 * Find the event index in the metadata Event table.
8649 find_event_index (MonoClass *klass, MonoEvent *event) {
8652 for (i = 0; i < klass->ext->event.count; ++i) {
8653 if (event == &klass->ext->events [i])
8654 return klass->ext->event.first + 1 + i;
8660 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8662 const char *p = (const char*)data;
8664 guint32 i, j, num_named;
8666 void *params_buf [32];
8667 void **params = NULL;
8668 MonoMethodSignature *sig;
8669 MonoObject *exc = NULL;
8671 mono_error_init (error);
8673 mono_class_init (method->klass);
8675 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8676 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8681 attr = mono_object_new (mono_domain_get (), method->klass);
8682 mono_runtime_invoke (method, attr, NULL, NULL);
8686 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8689 /*g_print ("got attr %s\n", method->klass->name);*/
8691 sig = mono_method_signature (method);
8692 if (sig->param_count < 32) {
8693 params = params_buf;
8694 memset (params, 0, sizeof (void*) * sig->param_count);
8696 /* Allocate using GC so it gets GC tracking */
8697 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8702 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8703 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8704 if (!mono_error_ok (error))
8709 attr = mono_object_new (mono_domain_get (), method->klass);
8711 mono_runtime_invoke (method, attr, params, &exc);
8714 num_named = read16 (named);
8716 for (j = 0; j < num_named; j++) {
8718 char *name, named_type, data_type;
8719 named_type = *named++;
8720 data_type = *named++; /* type of data */
8721 if (data_type == MONO_TYPE_SZARRAY)
8722 data_type = *named++;
8723 if (data_type == MONO_TYPE_ENUM) {
8726 type_len = mono_metadata_decode_blob_size (named, &named);
8727 type_name = (char *)g_malloc (type_len + 1);
8728 memcpy (type_name, named, type_len);
8729 type_name [type_len] = 0;
8731 /* FIXME: lookup the type and check type consistency */
8734 name_len = mono_metadata_decode_blob_size (named, &named);
8735 name = (char *)g_malloc (name_len + 1);
8736 memcpy (name, named, name_len);
8737 name [name_len] = 0;
8739 if (named_type == 0x53) {
8740 MonoClassField *field;
8743 /* how this fail is a blackbox */
8744 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8746 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8751 val = load_cattr_value (image, field->type, named, &named, error);
8752 if (!mono_error_ok (error)) {
8754 if (!type_is_reference (field->type))
8759 mono_field_set_value (attr, field, val);
8760 if (!type_is_reference (field->type))
8762 } else if (named_type == 0x54) {
8765 MonoType *prop_type;
8767 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8770 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8776 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8781 /* can we have more that 1 arg in a custom attr named property? */
8782 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8783 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8785 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8786 if (!mono_error_ok (error)) {
8788 if (!type_is_reference (prop_type))
8789 g_free (pparams [0]);
8794 mono_property_set_value (prop, attr, pparams, NULL);
8795 if (!type_is_reference (prop_type))
8796 g_free (pparams [0]);
8801 free_param_data (method->signature, params);
8802 if (params != params_buf)
8803 mono_gc_free_fixed (params);
8808 free_param_data (method->signature, params);
8809 if (params != params_buf)
8810 mono_gc_free_fixed (params);
8812 mono_raise_exception ((MonoException*)exc);
8817 * mono_reflection_create_custom_attr_data_args:
8819 * Create an array of typed and named arguments from the cattr blob given by DATA.
8820 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8821 * NAMED_ARG_INFO will contain information about the named arguments.
8824 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)
8826 MonoArray *typedargs, *namedargs;
8827 MonoClass *attrklass;
8829 const char *p = (const char*)data;
8831 guint32 i, j, num_named;
8832 CattrNamedArg *arginfo = NULL;
8836 *named_arg_info = NULL;
8838 mono_error_init (error);
8840 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8841 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8845 mono_class_init (method->klass);
8847 domain = mono_domain_get ();
8849 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8852 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8856 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8860 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8861 if (!mono_error_ok (error)) {
8862 if (!type_is_reference (mono_method_signature (method)->params [i]))
8867 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8868 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8869 mono_array_setref (typedargs, i, obj);
8871 if (!type_is_reference (mono_method_signature (method)->params [i]))
8876 num_named = read16 (named);
8877 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8879 attrklass = method->klass;
8881 arginfo = g_new0 (CattrNamedArg, num_named);
8882 *named_arg_info = arginfo;
8884 for (j = 0; j < num_named; j++) {
8886 char *name, named_type, data_type;
8887 named_type = *named++;
8888 data_type = *named++; /* type of data */
8889 if (data_type == MONO_TYPE_SZARRAY)
8890 data_type = *named++;
8891 if (data_type == MONO_TYPE_ENUM) {
8894 type_len = mono_metadata_decode_blob_size (named, &named);
8895 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8898 type_name = (char *)g_malloc (type_len + 1);
8899 memcpy (type_name, named, type_len);
8900 type_name [type_len] = 0;
8902 /* FIXME: lookup the type and check type consistency */
8905 name_len = mono_metadata_decode_blob_size (named, &named);
8906 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8908 name = (char *)g_malloc (name_len + 1);
8909 memcpy (name, named, name_len);
8910 name [name_len] = 0;
8912 if (named_type == 0x53) {
8914 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8922 arginfo [j].type = field->type;
8923 arginfo [j].field = field;
8925 val = load_cattr_value (image, field->type, named, &named, error);
8926 if (!mono_error_ok (error)) {
8927 if (!type_is_reference (field->type))
8933 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8934 mono_array_setref (namedargs, j, obj);
8935 if (!type_is_reference (field->type))
8937 } else if (named_type == 0x54) {
8939 MonoType *prop_type;
8940 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8943 if (!prop || !prop->set) {
8948 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8949 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8951 arginfo [j].type = prop_type;
8952 arginfo [j].prop = prop;
8954 val = load_cattr_value (image, prop_type, named, &named, error);
8955 if (!mono_error_ok (error)) {
8956 if (!type_is_reference (prop_type))
8962 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8963 mono_array_setref (namedargs, j, obj);
8964 if (!type_is_reference (prop_type))
8970 *typed_args = typedargs;
8971 *named_args = namedargs;
8974 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8976 *named_arg_info = NULL;
8980 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8983 MonoArray *typedargs, *namedargs;
8986 CattrNamedArg *arginfo = NULL;
8996 image = assembly->assembly->image;
8997 method = ref_method->method;
8998 domain = mono_object_domain (ref_method);
9000 if (!mono_class_init (method->klass))
9001 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9003 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9004 if (!mono_error_ok (&error))
9005 mono_error_raise_exception (&error);
9006 if (mono_loader_get_last_error ())
9007 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
9009 if (!typedargs || !namedargs) {
9014 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9015 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9016 MonoObject *typedarg;
9018 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9019 mono_array_setref (typedargs, i, typedarg);
9022 for (i = 0; i < mono_array_length (namedargs); ++i) {
9023 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9024 MonoObject *typedarg, *namedarg, *minfo;
9026 if (arginfo [i].prop)
9027 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9029 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
9031 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9032 namedarg = create_cattr_named_arg (minfo, typedarg);
9034 mono_array_setref (namedargs, i, namedarg);
9037 *ctor_args = typedargs;
9038 *named_args = namedargs;
9043 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9045 static MonoMethod *ctor;
9050 g_assert (image->assembly);
9053 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9055 domain = mono_domain_get ();
9056 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
9057 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
9058 params [1] = mono_assembly_get_object (domain, image->assembly);
9059 params [2] = (gpointer)&cattr->data;
9060 params [3] = &cattr->data_size;
9061 mono_runtime_invoke (ctor, attr, params, NULL);
9066 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9072 mono_error_init (error);
9075 for (i = 0; i < cinfo->num_attrs; ++i) {
9076 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9080 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9082 for (i = 0; i < cinfo->num_attrs; ++i) {
9083 if (!cinfo->attrs [i].ctor)
9084 /* The cattr type is not finished yet */
9085 /* We should include the type name but cinfo doesn't contain it */
9086 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9087 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9088 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9089 if (!mono_error_ok (error))
9091 mono_array_setref (result, n, attr);
9099 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9102 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9103 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9109 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9115 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9116 for (i = 0; i < cinfo->num_attrs; ++i) {
9117 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9118 mono_array_setref (result, i, attr);
9124 * mono_custom_attrs_from_index:
9126 * Returns: NULL if no attributes are found or if a loading error occurs.
9129 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9131 guint32 mtoken, i, len;
9132 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9134 MonoCustomAttrInfo *ainfo;
9135 GList *tmp, *list = NULL;
9137 MonoCustomAttrEntry* attr;
9139 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9141 i = mono_metadata_custom_attrs_from_index (image, idx);
9145 while (i < ca->rows) {
9146 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9148 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9151 len = g_list_length (list);
9154 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9155 ainfo->num_attrs = len;
9156 ainfo->image = image;
9157 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9159 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9160 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9161 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9162 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9163 mtoken |= MONO_TOKEN_METHOD_DEF;
9165 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9166 mtoken |= MONO_TOKEN_MEMBER_REF;
9169 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9172 attr = &ainfo->attrs [i - 1];
9173 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9175 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9176 mono_loader_set_error_from_mono_error (&error);
9182 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9183 /*FIXME raising an exception here doesn't make any sense*/
9184 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9189 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9190 attr->data_size = mono_metadata_decode_value (data, &data);
9191 attr->data = (guchar*)data;
9199 mono_custom_attrs_from_method (MonoMethod *method)
9204 * An instantiated method has the same cattrs as the generic method definition.
9206 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9207 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9209 if (method->is_inflated)
9210 method = ((MonoMethodInflated *) method)->declaring;
9212 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9213 return lookup_custom_attr (method->klass->image, method);
9216 /* Synthetic methods */
9219 idx = mono_method_get_index (method);
9220 idx <<= MONO_CUSTOM_ATTR_BITS;
9221 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9222 return mono_custom_attrs_from_index (method->klass->image, idx);
9226 mono_custom_attrs_from_class (MonoClass *klass)
9230 if (klass->generic_class)
9231 klass = klass->generic_class->container_class;
9233 if (image_is_dynamic (klass->image))
9234 return lookup_custom_attr (klass->image, klass);
9236 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9237 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9238 idx <<= MONO_CUSTOM_ATTR_BITS;
9239 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9241 idx = mono_metadata_token_index (klass->type_token);
9242 idx <<= MONO_CUSTOM_ATTR_BITS;
9243 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9245 return mono_custom_attrs_from_index (klass->image, idx);
9249 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9253 if (image_is_dynamic (assembly->image))
9254 return lookup_custom_attr (assembly->image, assembly);
9255 idx = 1; /* there is only one assembly */
9256 idx <<= MONO_CUSTOM_ATTR_BITS;
9257 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9258 return mono_custom_attrs_from_index (assembly->image, idx);
9261 static MonoCustomAttrInfo*
9262 mono_custom_attrs_from_module (MonoImage *image)
9266 if (image_is_dynamic (image))
9267 return lookup_custom_attr (image, image);
9268 idx = 1; /* there is only one module */
9269 idx <<= MONO_CUSTOM_ATTR_BITS;
9270 idx |= MONO_CUSTOM_ATTR_MODULE;
9271 return mono_custom_attrs_from_index (image, idx);
9275 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9279 if (image_is_dynamic (klass->image)) {
9280 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9281 return lookup_custom_attr (klass->image, property);
9283 idx = find_property_index (klass, property);
9284 idx <<= MONO_CUSTOM_ATTR_BITS;
9285 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9286 return mono_custom_attrs_from_index (klass->image, idx);
9290 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9294 if (image_is_dynamic (klass->image)) {
9295 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9296 return lookup_custom_attr (klass->image, event);
9298 idx = find_event_index (klass, event);
9299 idx <<= MONO_CUSTOM_ATTR_BITS;
9300 idx |= MONO_CUSTOM_ATTR_EVENT;
9301 return mono_custom_attrs_from_index (klass->image, idx);
9305 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9308 if (image_is_dynamic (klass->image)) {
9309 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9310 return lookup_custom_attr (klass->image, field);
9312 idx = find_field_index (klass, field);
9313 idx <<= MONO_CUSTOM_ATTR_BITS;
9314 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9315 return mono_custom_attrs_from_index (klass->image, idx);
9319 * mono_custom_attrs_from_param:
9320 * @method: handle to the method that we want to retrieve custom parameter information from
9321 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9323 * The result must be released with mono_custom_attrs_free().
9325 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9328 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9331 guint32 i, idx, method_index;
9332 guint32 param_list, param_last, param_pos, found;
9334 MonoReflectionMethodAux *aux;
9337 * An instantiated method has the same cattrs as the generic method definition.
9339 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9340 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9342 if (method->is_inflated)
9343 method = ((MonoMethodInflated *) method)->declaring;
9345 if (image_is_dynamic (method->klass->image)) {
9346 MonoCustomAttrInfo *res, *ainfo;
9349 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9350 if (!aux || !aux->param_cattr)
9353 /* Need to copy since it will be freed later */
9354 ainfo = aux->param_cattr [param];
9357 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9358 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9359 memcpy (res, ainfo, size);
9363 image = method->klass->image;
9364 method_index = mono_method_get_index (method);
9367 ca = &image->tables [MONO_TABLE_METHOD];
9369 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9370 if (method_index == ca->rows) {
9371 ca = &image->tables [MONO_TABLE_PARAM];
9372 param_last = ca->rows + 1;
9374 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9375 ca = &image->tables [MONO_TABLE_PARAM];
9378 for (i = param_list; i < param_last; ++i) {
9379 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9380 if (param_pos == param) {
9388 idx <<= MONO_CUSTOM_ATTR_BITS;
9389 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9390 return mono_custom_attrs_from_index (image, idx);
9394 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9398 for (i = 0; i < ainfo->num_attrs; ++i) {
9399 klass = ainfo->attrs [i].ctor->klass;
9400 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9407 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9410 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9411 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9416 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9422 mono_error_init (error);
9425 for (i = 0; i < ainfo->num_attrs; ++i) {
9426 klass = ainfo->attrs [i].ctor->klass;
9427 if (mono_class_has_parent (klass, attr_klass)) {
9432 if (attr_index == -1)
9435 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9436 if (!mono_error_ok (error))
9438 return mono_array_get (attrs, MonoObject*, attr_index);
9442 * mono_reflection_get_custom_attrs_info:
9443 * @obj: a reflection object handle
9445 * Return the custom attribute info for attributes defined for the
9446 * reflection handle @obj. The objects.
9448 * FIXME this function leaks like a sieve for SRE objects.
9451 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9454 MonoCustomAttrInfo *cinfo = NULL;
9456 klass = obj->vtable->klass;
9457 if (klass == mono_defaults.monotype_class) {
9458 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9459 klass = mono_class_from_mono_type (type);
9460 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9461 cinfo = mono_custom_attrs_from_class (klass);
9462 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9463 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9464 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9465 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9466 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9467 cinfo = mono_custom_attrs_from_module (module->image);
9468 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9469 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9470 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9471 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9472 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9473 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9474 } else if (strcmp ("MonoField", klass->name) == 0) {
9475 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9476 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9477 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9478 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9479 cinfo = mono_custom_attrs_from_method (rmethod->method);
9480 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9481 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9482 cinfo = mono_custom_attrs_from_method (rmethod->method);
9483 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9484 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9485 MonoClass *member_class = mono_object_class (param->MemberImpl);
9486 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9487 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9488 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9489 } else if (is_sr_mono_property (member_class)) {
9490 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9492 if (!(method = prop->property->get))
9493 method = prop->property->set;
9496 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9498 #ifndef DISABLE_REFLECTION_EMIT
9499 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9500 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9501 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9502 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9503 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9504 MonoMethod *method = NULL;
9505 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9506 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9507 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9508 method = ((MonoReflectionMethod *)c->cb)->method;
9510 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));
9512 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9516 char *type_name = mono_type_get_full_name (member_class);
9517 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9518 MonoException *ex = mono_get_exception_not_supported (msg);
9521 mono_raise_exception (ex);
9523 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9524 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9525 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9526 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9527 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9528 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9529 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9530 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9531 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9532 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9533 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9534 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9535 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9536 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9537 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9538 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9539 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9540 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9541 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9542 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9543 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9544 } else { /* handle other types here... */
9545 g_error ("get custom attrs not yet supported for %s", klass->name);
9552 * mono_reflection_get_custom_attrs_by_type:
9553 * @obj: a reflection object handle
9555 * Return an array with all the custom attributes defined of the
9556 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9557 * of that type are returned. The objects are fully build. Return NULL if a loading error
9561 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9564 MonoCustomAttrInfo *cinfo;
9566 mono_error_init (error);
9568 cinfo = mono_reflection_get_custom_attrs_info (obj);
9570 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9572 mono_custom_attrs_free (cinfo);
9574 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9575 if (mono_loader_get_last_error ())
9577 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9584 * mono_reflection_get_custom_attrs:
9585 * @obj: a reflection object handle
9587 * Return an array with all the custom attributes defined of the
9588 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9592 mono_reflection_get_custom_attrs (MonoObject *obj)
9596 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9600 * mono_reflection_get_custom_attrs_data:
9601 * @obj: a reflection obj handle
9603 * Returns an array of System.Reflection.CustomAttributeData,
9604 * which include information about attributes reflected on
9605 * types loaded using the Reflection Only methods
9608 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9611 MonoCustomAttrInfo *cinfo;
9613 cinfo = mono_reflection_get_custom_attrs_info (obj);
9615 result = mono_custom_attrs_data_construct (cinfo);
9617 mono_custom_attrs_free (cinfo);
9619 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9624 static MonoReflectionType*
9625 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9627 static MonoMethod *method_get_underlying_system_type = NULL;
9628 MonoMethod *usertype_method;
9630 if (!method_get_underlying_system_type)
9631 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9632 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9633 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9638 is_corlib_type (MonoClass *klass)
9640 return klass->image == mono_defaults.corlib;
9643 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9644 static MonoClass *cached_class; \
9646 return cached_class == _class; \
9647 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9648 cached_class = _class; \
9655 #ifndef DISABLE_REFLECTION_EMIT
9657 is_sre_array (MonoClass *klass)
9659 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9663 is_sre_byref (MonoClass *klass)
9665 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9669 is_sre_pointer (MonoClass *klass)
9671 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9675 is_sre_generic_instance (MonoClass *klass)
9677 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9681 is_sre_type_builder (MonoClass *klass)
9683 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9687 is_sre_method_builder (MonoClass *klass)
9689 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9693 is_sre_ctor_builder (MonoClass *klass)
9695 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9699 is_sre_field_builder (MonoClass *klass)
9701 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9705 is_sre_method_on_tb_inst (MonoClass *klass)
9707 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9711 is_sre_ctor_on_tb_inst (MonoClass *klass)
9713 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9717 mono_reflection_type_get_handle (MonoReflectionType* ref)
9725 if (is_usertype (ref)) {
9726 ref = mono_reflection_type_get_underlying_system_type (ref);
9727 if (ref == NULL || is_usertype (ref))
9733 klass = mono_object_class (ref);
9735 if (is_sre_array (klass)) {
9737 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9738 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9740 if (sre_array->rank == 0) //single dimentional array
9741 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9743 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9744 sre_array->type.type = res;
9746 } else if (is_sre_byref (klass)) {
9748 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9749 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9751 res = &mono_class_from_mono_type (base)->this_arg;
9752 sre_byref->type.type = res;
9754 } else if (is_sre_pointer (klass)) {
9756 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9757 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9759 res = &mono_ptr_class_get (base)->byval_arg;
9760 sre_pointer->type.type = res;
9762 } else if (is_sre_generic_instance (klass)) {
9763 MonoType *res, **types;
9764 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9767 count = mono_array_length (gclass->type_arguments);
9768 types = g_new0 (MonoType*, count);
9769 for (i = 0; i < count; ++i) {
9770 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9771 types [i] = mono_reflection_type_get_handle (t);
9778 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9781 gclass->type.type = res;
9785 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9792 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9794 mono_reflection_type_get_handle (type);
9798 mono_reflection_register_with_runtime (MonoReflectionType *type)
9800 MonoType *res = mono_reflection_type_get_handle (type);
9801 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9805 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9807 klass = mono_class_from_mono_type (res);
9809 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9810 mono_domain_lock (domain);
9812 if (!image_is_dynamic (klass->image)) {
9813 mono_class_setup_supertypes (klass);
9815 if (!domain->type_hash)
9816 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9817 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9818 mono_g_hash_table_insert (domain->type_hash, res, type);
9820 mono_domain_unlock (domain);
9821 mono_loader_unlock ();
9825 * LOCKING: Assumes the loader lock is held.
9827 static MonoMethodSignature*
9828 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9829 MonoMethodSignature *sig;
9832 count = parameters? mono_array_length (parameters): 0;
9834 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9835 sig->param_count = count;
9836 sig->sentinelpos = -1; /* FIXME */
9837 for (i = 0; i < count; ++i)
9838 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9843 * LOCKING: Assumes the loader lock is held.
9845 static MonoMethodSignature*
9846 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9847 MonoMethodSignature *sig;
9849 sig = parameters_to_signature (image, ctor->parameters);
9850 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9851 sig->ret = &mono_defaults.void_class->byval_arg;
9856 * LOCKING: Assumes the loader lock is held.
9858 static MonoMethodSignature*
9859 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9860 MonoMethodSignature *sig;
9862 sig = parameters_to_signature (image, method->parameters);
9863 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9864 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9865 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9869 static MonoMethodSignature*
9870 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9871 MonoMethodSignature *sig;
9873 sig = parameters_to_signature (NULL, method->parameters);
9874 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9875 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9876 sig->generic_param_count = 0;
9881 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9883 MonoClass *klass = mono_object_class (prop);
9884 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9885 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9886 *name = mono_string_to_utf8 (pb->name);
9887 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9889 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9890 *name = g_strdup (p->property->name);
9891 if (p->property->get)
9892 *type = mono_method_signature (p->property->get)->ret;
9894 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9899 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9901 MonoClass *klass = mono_object_class (field);
9902 if (strcmp (klass->name, "FieldBuilder") == 0) {
9903 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9904 *name = mono_string_to_utf8 (fb->name);
9905 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9907 MonoReflectionField *f = (MonoReflectionField *)field;
9908 *name = g_strdup (mono_field_get_name (f->field));
9909 *type = f->field->type;
9913 #else /* DISABLE_REFLECTION_EMIT */
9916 mono_reflection_register_with_runtime (MonoReflectionType *type)
9922 is_sre_type_builder (MonoClass *klass)
9928 is_sre_generic_instance (MonoClass *klass)
9934 init_type_builder_generics (MonoObject *type)
9938 #endif /* !DISABLE_REFLECTION_EMIT */
9942 is_sr_mono_field (MonoClass *klass)
9944 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9948 is_sr_mono_property (MonoClass *klass)
9950 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9954 is_sr_mono_method (MonoClass *klass)
9956 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9960 is_sr_mono_cmethod (MonoClass *klass)
9962 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9966 is_sr_mono_generic_method (MonoClass *klass)
9968 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9972 is_sr_mono_generic_cmethod (MonoClass *klass)
9974 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9978 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9980 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9984 is_usertype (MonoReflectionType *ref)
9986 MonoClass *klass = mono_object_class (ref);
9987 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9990 static MonoReflectionType*
9991 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
9993 mono_error_init (error);
9994 if (!type || type->type)
9997 if (is_usertype (type)) {
9998 type = mono_reflection_type_get_underlying_system_type (type);
9999 if (is_usertype (type)) {
10000 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10008 * Encode a value in a custom attribute stream of bytes.
10009 * The value to encode is either supplied as an object in argument val
10010 * (valuetypes are boxed), or as a pointer to the data in the
10012 * @type represents the type of the value
10013 * @buffer is the start of the buffer
10014 * @p the current position in the buffer
10015 * @buflen contains the size of the buffer and is used to return the new buffer size
10016 * if this needs to be realloced.
10017 * @retbuffer and @retp return the start and the position of the buffer
10020 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10022 MonoTypeEnum simple_type;
10024 if ((p-buffer) + 10 >= *buflen) {
10027 newbuf = (char *)g_realloc (buffer, *buflen);
10028 p = newbuf + (p-buffer);
10032 argval = ((char*)arg + sizeof (MonoObject));
10033 simple_type = type->type;
10035 switch (simple_type) {
10036 case MONO_TYPE_BOOLEAN:
10041 case MONO_TYPE_CHAR:
10044 swap_with_size (p, argval, 2, 1);
10050 swap_with_size (p, argval, 4, 1);
10054 swap_with_size (p, argval, 8, 1);
10059 swap_with_size (p, argval, 8, 1);
10062 case MONO_TYPE_VALUETYPE:
10063 if (type->data.klass->enumtype) {
10064 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10067 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10070 case MONO_TYPE_STRING: {
10077 str = mono_string_to_utf8 ((MonoString*)arg);
10078 slen = strlen (str);
10079 if ((p-buffer) + 10 + slen >= *buflen) {
10083 newbuf = (char *)g_realloc (buffer, *buflen);
10084 p = newbuf + (p-buffer);
10087 mono_metadata_encode_value (slen, p, &p);
10088 memcpy (p, str, slen);
10093 case MONO_TYPE_CLASS: {
10101 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10102 slen = strlen (str);
10103 if ((p-buffer) + 10 + slen >= *buflen) {
10107 newbuf = (char *)g_realloc (buffer, *buflen);
10108 p = newbuf + (p-buffer);
10111 mono_metadata_encode_value (slen, p, &p);
10112 memcpy (p, str, slen);
10117 case MONO_TYPE_SZARRAY: {
10119 MonoClass *eclass, *arg_eclass;
10122 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10125 len = mono_array_length ((MonoArray*)arg);
10127 *p++ = (len >> 8) & 0xff;
10128 *p++ = (len >> 16) & 0xff;
10129 *p++ = (len >> 24) & 0xff;
10131 *retbuffer = buffer;
10132 eclass = type->data.klass;
10133 arg_eclass = mono_object_class (arg)->element_class;
10136 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10137 eclass = mono_defaults.object_class;
10139 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10140 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10141 int elsize = mono_class_array_element_size (arg_eclass);
10142 for (i = 0; i < len; ++i) {
10143 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10146 } else if (eclass->valuetype && arg_eclass->valuetype) {
10147 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10148 int elsize = mono_class_array_element_size (eclass);
10149 for (i = 0; i < len; ++i) {
10150 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10154 for (i = 0; i < len; ++i) {
10155 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10160 case MONO_TYPE_OBJECT: {
10166 * The parameter type is 'object' but the type of the actual
10167 * argument is not. So we have to add type information to the blob
10168 * too. This is completely undocumented in the spec.
10172 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10177 klass = mono_object_class (arg);
10179 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10182 } else if (klass->enumtype) {
10184 } else if (klass == mono_defaults.string_class) {
10185 simple_type = MONO_TYPE_STRING;
10188 } else if (klass->rank == 1) {
10190 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10191 /* See Partition II, Appendix B3 */
10194 *p++ = klass->element_class->byval_arg.type;
10195 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10197 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10198 *p++ = simple_type = klass->byval_arg.type;
10201 g_error ("unhandled type in custom attr");
10203 str = type_get_qualified_name (mono_class_get_type(klass), 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);
10217 simple_type = mono_class_enum_basetype (klass)->type;
10221 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10224 *retbuffer = buffer;
10228 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10230 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10231 char *str = type_get_qualified_name (type, NULL);
10232 int slen = strlen (str);
10236 * This seems to be optional...
10239 mono_metadata_encode_value (slen, p, &p);
10240 memcpy (p, str, slen);
10243 } else if (type->type == MONO_TYPE_OBJECT) {
10245 } else if (type->type == MONO_TYPE_CLASS) {
10246 /* it should be a type: encode_cattr_value () has the check */
10249 mono_metadata_encode_value (type->type, p, &p);
10250 if (type->type == MONO_TYPE_SZARRAY)
10251 /* See the examples in Partition VI, Annex B */
10252 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10258 #ifndef DISABLE_REFLECTION_EMIT
10260 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10263 /* Preallocate a large enough buffer */
10264 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10265 char *str = type_get_qualified_name (type, NULL);
10266 len = strlen (str);
10268 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10269 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10270 len = strlen (str);
10275 len += strlen (name);
10277 if ((p-buffer) + 20 + len >= *buflen) {
10281 newbuf = (char *)g_realloc (buffer, *buflen);
10282 p = newbuf + (p-buffer);
10286 encode_field_or_prop_type (type, p, &p);
10288 len = strlen (name);
10289 mono_metadata_encode_value (len, p, &p);
10290 memcpy (p, name, len);
10292 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10294 *retbuffer = buffer;
10298 * mono_reflection_get_custom_attrs_blob:
10299 * @ctor: custom attribute constructor
10300 * @ctorArgs: arguments o the constructor
10306 * Creates the blob of data that needs to be saved in the metadata and that represents
10307 * the custom attributed described by @ctor, @ctorArgs etc.
10308 * Returns: a Byte array representing the blob of data.
10311 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10314 MonoMethodSignature *sig;
10319 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10320 /* sig is freed later so allocate it in the heap */
10321 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10323 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10326 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10328 p = buffer = (char *)g_malloc (buflen);
10329 /* write the prolog */
10332 for (i = 0; i < sig->param_count; ++i) {
10333 arg = mono_array_get (ctorArgs, MonoObject*, i);
10334 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10338 i += mono_array_length (properties);
10340 i += mono_array_length (fields);
10342 *p++ = (i >> 8) & 0xff;
10345 for (i = 0; i < mono_array_length (properties); ++i) {
10349 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10350 get_prop_name_and_type (prop, &pname, &ptype);
10351 *p++ = 0x54; /* PROPERTY signature */
10352 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10359 for (i = 0; i < mono_array_length (fields); ++i) {
10363 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10364 get_field_name_and_type (field, &fname, &ftype);
10365 *p++ = 0x53; /* FIELD signature */
10366 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10371 g_assert (p - buffer <= buflen);
10372 buflen = p - buffer;
10373 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10374 p = mono_array_addr (result, char, 0);
10375 memcpy (p, buffer, buflen);
10377 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10383 * mono_reflection_setup_internal_class:
10384 * @tb: a TypeBuilder object
10386 * Creates a MonoClass that represents the TypeBuilder.
10387 * This is a trick that lets us simplify a lot of reflection code
10388 * (and will allow us to support Build and Run assemblies easier).
10391 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10394 MonoClass *klass, *parent;
10396 RESOLVE_TYPE (tb->parent, &error);
10397 mono_error_raise_exception (&error); /* FIXME don't raise here */
10399 mono_loader_lock ();
10402 /* check so we can compile corlib correctly */
10403 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10404 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10405 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10407 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10413 /* the type has already being created: it means we just have to change the parent */
10414 if (tb->type.type) {
10415 klass = mono_class_from_mono_type (tb->type.type);
10416 klass->parent = NULL;
10417 /* fool mono_class_setup_parent */
10418 klass->supertypes = NULL;
10419 mono_class_setup_parent (klass, parent);
10420 mono_class_setup_mono_type (klass);
10421 mono_loader_unlock ();
10425 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10427 klass->image = &tb->module->dynamic_image->image;
10429 klass->inited = 1; /* we lie to the runtime */
10430 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10431 if (!mono_error_ok (&error))
10433 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10434 if (!mono_error_ok (&error))
10436 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10437 klass->flags = tb->attrs;
10439 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10441 klass->element_class = klass;
10443 if (mono_class_get_ref_info (klass) == NULL) {
10445 mono_class_set_ref_info (klass, tb);
10447 /* Put into cache so mono_class_get_checked () will find it.
10448 Skip nested types as those should not be available on the global scope. */
10449 if (!tb->nesting_type)
10450 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10453 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10454 by performing a mono_class_get which does the full resolution.
10456 Working around this semantics would require us to write a lot of code for no clear advantage.
10458 mono_image_append_class_to_reflection_info_set (klass);
10460 g_assert (mono_class_get_ref_info (klass) == tb);
10463 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10465 if (parent != NULL) {
10466 mono_class_setup_parent (klass, parent);
10467 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10468 const char *old_n = klass->name;
10469 /* trick to get relative numbering right when compiling corlib */
10470 klass->name = "BuildingObject";
10471 mono_class_setup_parent (klass, mono_defaults.object_class);
10472 klass->name = old_n;
10475 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10476 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10477 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10478 klass->instance_size = sizeof (MonoObject);
10479 klass->size_inited = 1;
10480 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10483 mono_class_setup_mono_type (klass);
10485 mono_class_setup_supertypes (klass);
10488 * FIXME: handle interfaces.
10491 tb->type.type = &klass->byval_arg;
10493 if (tb->nesting_type) {
10494 g_assert (tb->nesting_type->type);
10495 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10498 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10500 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10502 mono_loader_unlock ();
10506 mono_loader_unlock ();
10507 mono_error_raise_exception (&error);
10511 * mono_reflection_setup_generic_class:
10512 * @tb: a TypeBuilder object
10514 * Setup the generic class before adding the first generic parameter.
10517 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10522 * mono_reflection_create_generic_class:
10523 * @tb: a TypeBuilder object
10525 * Creates the generic class after all generic parameters have been added.
10528 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10533 klass = mono_class_from_mono_type (tb->type.type);
10535 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10537 if (klass->generic_container || (count == 0))
10540 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10542 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10544 klass->generic_container->owner.klass = klass;
10545 klass->generic_container->type_argc = count;
10546 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10548 klass->is_generic = 1;
10550 for (i = 0; i < count; i++) {
10551 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10552 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10553 klass->generic_container->type_params [i] = *param;
10554 /*Make sure we are a diferent type instance */
10555 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10556 klass->generic_container->type_params [i].info.pklass = NULL;
10557 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10559 g_assert (klass->generic_container->type_params [i].param.owner);
10562 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10566 * mono_reflection_create_internal_class:
10567 * @tb: a TypeBuilder object
10569 * Actually create the MonoClass that is associated with the TypeBuilder.
10572 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10576 klass = mono_class_from_mono_type (tb->type.type);
10578 mono_loader_lock ();
10579 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10580 MonoReflectionFieldBuilder *fb;
10582 MonoType *enum_basetype;
10584 g_assert (tb->fields != NULL);
10585 g_assert (mono_array_length (tb->fields) >= 1);
10587 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10589 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10590 mono_loader_unlock ();
10594 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10595 klass->element_class = mono_class_from_mono_type (enum_basetype);
10596 if (!klass->element_class)
10597 klass->element_class = mono_class_from_mono_type (enum_basetype);
10600 * get the element_class from the current corlib.
10602 ec = default_class_from_mono_type (enum_basetype);
10603 klass->instance_size = ec->instance_size;
10604 klass->size_inited = 1;
10606 * this is almost safe to do with enums and it's needed to be able
10607 * to create objects of the enum type (for use in SetConstant).
10609 /* FIXME: Does this mean enums can't have method overrides ? */
10610 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10612 mono_loader_unlock ();
10615 static MonoMarshalSpec*
10616 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10617 MonoReflectionMarshal *minfo)
10619 MonoMarshalSpec *res;
10621 res = image_g_new0 (image, MonoMarshalSpec, 1);
10622 res->native = (MonoMarshalNative)minfo->type;
10624 switch (minfo->type) {
10625 case MONO_NATIVE_LPARRAY:
10626 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10627 if (minfo->has_size) {
10628 res->data.array_data.param_num = minfo->param_num;
10629 res->data.array_data.num_elem = minfo->count;
10630 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10633 res->data.array_data.param_num = -1;
10634 res->data.array_data.num_elem = -1;
10635 res->data.array_data.elem_mult = -1;
10639 case MONO_NATIVE_BYVALTSTR:
10640 case MONO_NATIVE_BYVALARRAY:
10641 res->data.array_data.num_elem = minfo->count;
10644 case MONO_NATIVE_CUSTOM:
10645 if (minfo->marshaltyperef)
10646 res->data.custom_data.custom_name =
10647 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10648 if (minfo->mcookie)
10649 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10658 #endif /* !DISABLE_REFLECTION_EMIT */
10660 MonoReflectionMarshalAsAttribute*
10661 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10662 MonoMarshalSpec *spec)
10664 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10666 MonoReflectionType *rt;
10667 MonoReflectionMarshalAsAttribute *minfo;
10670 if (!System_Reflection_Emit_MarshalAsAttribute) {
10671 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10672 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10673 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10676 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10677 minfo->utype = spec->native;
10679 switch (minfo->utype) {
10680 case MONO_NATIVE_LPARRAY:
10681 minfo->array_subtype = spec->data.array_data.elem_type;
10682 minfo->size_const = spec->data.array_data.num_elem;
10683 if (spec->data.array_data.param_num != -1)
10684 minfo->size_param_index = spec->data.array_data.param_num;
10687 case MONO_NATIVE_BYVALTSTR:
10688 case MONO_NATIVE_BYVALARRAY:
10689 minfo->size_const = spec->data.array_data.num_elem;
10692 case MONO_NATIVE_CUSTOM:
10693 if (spec->data.custom_data.custom_name) {
10694 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10696 rt = mono_type_get_object_checked (domain, mtype, &error);
10697 mono_error_raise_exception (&error); /* FIXME don't raise here */
10699 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10702 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10704 if (spec->data.custom_data.cookie)
10705 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10715 #ifndef DISABLE_REFLECTION_EMIT
10717 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10718 ReflectionMethodBuilder *rmb,
10719 MonoMethodSignature *sig)
10723 MonoMethodWrapper *wrapperm;
10724 MonoMarshalSpec **specs;
10725 MonoReflectionMethodAux *method_aux;
10730 mono_error_init (&error);
10732 * Methods created using a MethodBuilder should have their memory allocated
10733 * inside the image mempool, while dynamic methods should have their memory
10736 dynamic = rmb->refs != NULL;
10737 image = dynamic ? NULL : klass->image;
10740 g_assert (!klass->generic_class);
10742 mono_loader_lock ();
10744 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10745 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10746 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10748 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10750 wrapperm = (MonoMethodWrapper*)m;
10752 m->dynamic = dynamic;
10754 m->flags = rmb->attrs;
10755 m->iflags = rmb->iattrs;
10756 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10758 m->signature = sig;
10759 m->sre_method = TRUE;
10760 m->skip_visibility = rmb->skip_visibility;
10761 if (rmb->table_idx)
10762 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10764 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10765 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10766 m->string_ctor = 1;
10768 m->signature->pinvoke = 1;
10769 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10770 m->signature->pinvoke = 1;
10772 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10774 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10775 g_assert (mono_error_ok (&error));
10776 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10777 g_assert (mono_error_ok (&error));
10779 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10781 if (image_is_dynamic (klass->image))
10782 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10784 mono_loader_unlock ();
10787 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10788 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10789 MonoMethodHeader *header;
10791 gint32 max_stack, i;
10792 gint32 num_locals = 0;
10793 gint32 num_clauses = 0;
10797 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10798 code_size = rmb->ilgen->code_len;
10799 max_stack = rmb->ilgen->max_stack;
10800 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10801 if (rmb->ilgen->ex_handlers)
10802 num_clauses = method_count_clauses (rmb->ilgen);
10805 code = mono_array_addr (rmb->code, guint8, 0);
10806 code_size = mono_array_length (rmb->code);
10807 /* we probably need to run a verifier on the code... */
10817 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10818 header->code_size = code_size;
10819 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10820 memcpy ((char*)header->code, code, code_size);
10821 header->max_stack = max_stack;
10822 header->init_locals = rmb->init_locals;
10823 header->num_locals = num_locals;
10825 for (i = 0; i < num_locals; ++i) {
10826 MonoReflectionLocalBuilder *lb =
10827 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10829 header->locals [i] = image_g_new0 (image, MonoType, 1);
10830 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10833 header->num_clauses = num_clauses;
10835 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10836 rmb->ilgen, num_clauses);
10839 wrapperm->header = header;
10842 if (rmb->generic_params) {
10843 int count = mono_array_length (rmb->generic_params);
10844 MonoGenericContainer *container = rmb->generic_container;
10846 g_assert (container);
10848 container->type_argc = count;
10849 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10850 container->owner.method = m;
10851 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10853 m->is_generic = TRUE;
10854 mono_method_set_generic_container (m, container);
10856 for (i = 0; i < count; i++) {
10857 MonoReflectionGenericParam *gp =
10858 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10859 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10860 container->type_params [i] = *param;
10864 * The method signature might have pointers to generic parameters that belong to other methods.
10865 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10866 * generic parameters.
10868 for (i = 0; i < m->signature->param_count; ++i) {
10869 MonoType *t = m->signature->params [i];
10870 if (t->type == MONO_TYPE_MVAR) {
10871 MonoGenericParam *gparam = t->data.generic_param;
10872 if (gparam->num < count) {
10873 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10874 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10880 if (klass->generic_container) {
10881 container->parent = klass->generic_container;
10882 container->context.class_inst = klass->generic_container->context.class_inst;
10884 container->context.method_inst = mono_get_shared_generic_inst (container);
10888 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10892 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10894 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10895 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10896 for (i = 0; i < rmb->nrefs; ++i)
10897 data [i + 1] = rmb->refs [i];
10902 /* Parameter info */
10905 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10906 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10907 for (i = 0; i <= m->signature->param_count; ++i) {
10908 MonoReflectionParamBuilder *pb;
10909 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10910 if ((i > 0) && (pb->attrs)) {
10911 /* Make a copy since it might point to a shared type structure */
10912 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10913 m->signature->params [i - 1]->attrs = pb->attrs;
10916 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10917 MonoDynamicImage *assembly;
10919 MonoTypeEnum def_type;
10923 if (!method_aux->param_defaults) {
10924 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10925 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10927 assembly = (MonoDynamicImage*)klass->image;
10928 idx = encode_constant (assembly, pb->def_value, &def_type);
10929 /* Copy the data from the blob since it might get realloc-ed */
10930 p = assembly->blob.data + idx;
10931 len = mono_metadata_decode_blob_size (p, &p2);
10933 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10934 method_aux->param_default_types [i] = def_type;
10935 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10939 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10940 g_assert (mono_error_ok (&error));
10943 if (!method_aux->param_cattr)
10944 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10945 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10951 /* Parameter marshalling */
10954 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10955 MonoReflectionParamBuilder *pb;
10956 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10957 if (pb->marshal_info) {
10959 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10960 specs [pb->position] =
10961 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10965 if (specs != NULL) {
10967 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10968 method_aux->param_marshall = specs;
10971 if (image_is_dynamic (klass->image) && method_aux)
10972 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10974 mono_loader_unlock ();
10980 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10982 ReflectionMethodBuilder rmb;
10983 MonoMethodSignature *sig;
10985 mono_loader_lock ();
10986 sig = ctor_builder_to_signature (klass->image, mb);
10987 mono_loader_unlock ();
10989 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10991 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10992 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10994 /* If we are in a generic class, we might be called multiple times from inflate_method */
10995 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10996 /* ilgen is no longer needed */
11000 return mb->mhandle;
11004 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11006 ReflectionMethodBuilder rmb;
11007 MonoMethodSignature *sig;
11009 mono_loader_lock ();
11010 sig = method_builder_to_signature (klass->image, mb);
11011 mono_loader_unlock ();
11013 reflection_methodbuilder_from_method_builder (&rmb, mb);
11015 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11016 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11018 /* If we are in a generic class, we might be called multiple times from inflate_method */
11019 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11020 /* ilgen is no longer needed */
11023 return mb->mhandle;
11026 static MonoClassField*
11027 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11029 MonoClassField *field;
11033 field = g_new0 (MonoClassField, 1);
11035 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11036 g_assert (mono_error_ok (&error));
11037 if (fb->attrs || fb->modreq || fb->modopt) {
11038 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11039 field->type->attrs = fb->attrs;
11041 g_assert (image_is_dynamic (klass->image));
11042 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11043 g_free (field->type);
11044 field->type = mono_metadata_type_dup (klass->image, custom);
11047 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11049 if (fb->offset != -1)
11050 field->offset = fb->offset;
11051 field->parent = klass;
11052 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11054 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11061 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11064 MonoReflectionTypeBuilder *tb = NULL;
11065 gboolean is_dynamic = FALSE;
11066 MonoClass *geninst;
11068 mono_loader_lock ();
11070 if (is_sre_type_builder (mono_object_class (type))) {
11071 tb = (MonoReflectionTypeBuilder *) type;
11074 } else if (is_sre_generic_instance (mono_object_class (type))) {
11075 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11076 MonoReflectionType *gtd = rgi->generic_type;
11078 if (is_sre_type_builder (mono_object_class (gtd))) {
11079 tb = (MonoReflectionTypeBuilder *)gtd;
11084 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11085 if (tb && tb->generic_container)
11086 mono_reflection_create_generic_class (tb);
11088 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11089 if (!klass->generic_container) {
11090 mono_loader_unlock ();
11094 if (klass->wastypebuilder) {
11095 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11100 mono_loader_unlock ();
11102 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11104 return &geninst->byval_arg;
11108 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11110 MonoGenericClass *gclass;
11111 MonoGenericInst *inst;
11113 g_assert (klass->generic_container);
11115 inst = mono_metadata_get_generic_inst (type_argc, types);
11116 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11118 return mono_generic_class_get_class (gclass);
11121 MonoReflectionMethod*
11122 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11126 MonoMethod *method, *inflated;
11127 MonoMethodInflated *imethod;
11128 MonoGenericContext tmp_context;
11129 MonoGenericInst *ginst;
11130 MonoType **type_argv;
11133 /*FIXME but this no longer should happen*/
11134 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11135 #ifndef DISABLE_REFLECTION_EMIT
11136 MonoReflectionMethodBuilder *mb = NULL;
11137 MonoReflectionTypeBuilder *tb;
11140 mb = (MonoReflectionMethodBuilder *) rmethod;
11141 tb = (MonoReflectionTypeBuilder *) mb->type;
11142 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11144 method = methodbuilder_to_mono_method (klass, mb);
11146 g_assert_not_reached ();
11150 method = rmethod->method;
11153 klass = method->klass;
11155 if (method->is_inflated)
11156 method = ((MonoMethodInflated *) method)->declaring;
11158 count = mono_method_signature (method)->generic_param_count;
11159 if (count != mono_array_length (types))
11162 type_argv = g_new0 (MonoType *, count);
11163 for (i = 0; i < count; i++) {
11164 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11165 type_argv [i] = mono_reflection_type_get_handle (garg);
11167 ginst = mono_metadata_get_generic_inst (count, type_argv);
11168 g_free (type_argv);
11170 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11171 tmp_context.method_inst = ginst;
11173 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11174 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11175 imethod = (MonoMethodInflated *) inflated;
11177 /*FIXME but I think this is no longer necessary*/
11178 if (image_is_dynamic (method->klass->image)) {
11179 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11181 * This table maps metadata structures representing inflated methods/fields
11182 * to the reflection objects representing their generic definitions.
11184 mono_image_lock ((MonoImage*)image);
11185 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11186 mono_image_unlock ((MonoImage*)image);
11189 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11190 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11192 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11195 #ifndef DISABLE_REFLECTION_EMIT
11197 static MonoMethod *
11198 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11200 MonoMethodInflated *imethod;
11201 MonoGenericContext *context;
11205 * With generic code sharing the klass might not be inflated.
11206 * This can happen because classes inflated with their own
11207 * type arguments are "normalized" to the uninflated class.
11209 if (!klass->generic_class)
11212 context = mono_class_get_context (klass);
11214 if (klass->method.count && klass->methods) {
11215 /* Find the already created inflated method */
11216 for (i = 0; i < klass->method.count; ++i) {
11217 g_assert (klass->methods [i]->is_inflated);
11218 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11221 g_assert (i < klass->method.count);
11222 imethod = (MonoMethodInflated*)klass->methods [i];
11225 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11226 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11229 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11230 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11232 mono_image_lock ((MonoImage*)image);
11233 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11234 mono_image_unlock ((MonoImage*)image);
11236 return (MonoMethod *) imethod;
11239 static MonoMethod *
11240 inflate_method (MonoReflectionType *type, MonoObject *obj)
11242 MonoMethod *method;
11245 MonoClass *type_class = mono_object_class (type);
11247 if (is_sre_generic_instance (type_class)) {
11248 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11249 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11250 } else if (is_sre_type_builder (type_class)) {
11251 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11252 } else if (type->type) {
11253 gklass = mono_class_from_mono_type (type->type);
11254 gklass = mono_class_get_generic_type_definition (gklass);
11256 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11259 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11260 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11261 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11263 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11264 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11265 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11266 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11267 method = ((MonoReflectionMethod *) obj)->method;
11269 method = NULL; /* prevent compiler warning */
11270 g_error ("can't handle type %s", obj->vtable->klass->name);
11273 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11276 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11278 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11280 MonoGenericClass *gclass;
11281 MonoDynamicGenericClass *dgclass;
11282 MonoClass *klass, *gklass;
11286 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11287 klass = mono_class_from_mono_type (gtype);
11288 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11289 gclass = gtype->data.generic_class;
11291 if (!gclass->is_dynamic)
11294 dgclass = (MonoDynamicGenericClass *) gclass;
11296 if (dgclass->initialized)
11299 gklass = gclass->container_class;
11300 mono_class_init (gklass);
11302 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11304 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11305 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11306 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11308 for (i = 0; i < dgclass->count_fields; i++) {
11309 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11310 MonoClassField *field, *inflated_field = NULL;
11312 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11313 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11314 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11315 field = ((MonoReflectionField *) obj)->field;
11317 field = NULL; /* prevent compiler warning */
11318 g_assert_not_reached ();
11321 dgclass->fields [i] = *field;
11322 dgclass->fields [i].parent = klass;
11323 dgclass->fields [i].type = mono_class_inflate_generic_type (
11324 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11325 dgclass->field_generic_types [i] = field->type;
11326 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11327 dgclass->field_objects [i] = obj;
11329 if (inflated_field) {
11330 g_free (inflated_field);
11332 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11336 dgclass->initialized = TRUE;
11340 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11342 MonoDynamicGenericClass *dgclass;
11345 g_assert (gclass->is_dynamic);
11347 dgclass = (MonoDynamicGenericClass *)gclass;
11349 for (i = 0; i < dgclass->count_fields; ++i) {
11350 MonoClassField *field = dgclass->fields + i;
11351 mono_metadata_free_type (field->type);
11352 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11357 fix_partial_generic_class (MonoClass *klass)
11359 MonoClass *gklass = klass->generic_class->container_class;
11360 MonoDynamicGenericClass *dgclass;
11363 if (klass->wastypebuilder)
11366 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11367 if (klass->parent != gklass->parent) {
11369 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11370 if (mono_error_ok (&error)) {
11371 MonoClass *parent = mono_class_from_mono_type (parent_type);
11372 mono_metadata_free_type (parent_type);
11373 if (parent != klass->parent) {
11374 /*fool mono_class_setup_parent*/
11375 klass->supertypes = NULL;
11376 mono_class_setup_parent (klass, parent);
11379 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11380 mono_error_cleanup (&error);
11381 if (gklass->wastypebuilder)
11382 klass->wastypebuilder = TRUE;
11387 if (!dgclass->initialized)
11390 if (klass->method.count != gklass->method.count) {
11391 klass->method.count = gklass->method.count;
11392 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11394 for (i = 0; i < klass->method.count; i++) {
11396 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11397 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11398 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11402 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11403 klass->interface_count = gklass->interface_count;
11404 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11405 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11407 for (i = 0; i < gklass->interface_count; ++i) {
11408 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11409 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11410 mono_metadata_free_type (iface_type);
11412 ensure_runtime_vtable (klass->interfaces [i]);
11414 klass->interfaces_inited = 1;
11417 if (klass->field.count != gklass->field.count) {
11418 klass->field.count = gklass->field.count;
11419 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11421 for (i = 0; i < klass->field.count; i++) {
11422 klass->fields [i] = gklass->fields [i];
11423 klass->fields [i].parent = klass;
11424 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11428 /*We can only finish with this klass once it's parent has as well*/
11429 if (gklass->wastypebuilder)
11430 klass->wastypebuilder = TRUE;
11435 ensure_generic_class_runtime_vtable (MonoClass *klass)
11437 MonoClass *gklass = klass->generic_class->container_class;
11439 ensure_runtime_vtable (gklass);
11441 fix_partial_generic_class (klass);
11445 ensure_runtime_vtable (MonoClass *klass)
11447 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11450 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11453 ensure_runtime_vtable (klass->parent);
11456 num = tb->ctors? mono_array_length (tb->ctors): 0;
11457 num += tb->num_methods;
11458 klass->method.count = num;
11459 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11460 num = tb->ctors? mono_array_length (tb->ctors): 0;
11461 for (i = 0; i < num; ++i)
11462 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11463 num = tb->num_methods;
11465 for (i = 0; i < num; ++i)
11466 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11468 if (tb->interfaces) {
11469 klass->interface_count = mono_array_length (tb->interfaces);
11470 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11471 for (i = 0; i < klass->interface_count; ++i) {
11472 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11473 klass->interfaces [i] = mono_class_from_mono_type (iface);
11474 ensure_runtime_vtable (klass->interfaces [i]);
11476 klass->interfaces_inited = 1;
11478 } else if (klass->generic_class){
11479 ensure_generic_class_runtime_vtable (klass);
11482 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11484 for (i = 0; i < klass->method.count; ++i) {
11485 MonoMethod *im = klass->methods [i];
11486 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11487 im->slot = slot_num++;
11490 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11491 mono_class_setup_interface_offsets (klass);
11492 mono_class_setup_interface_id (klass);
11496 * The generic vtable is needed even if image->run is not set since some
11497 * runtime code like ves_icall_Type_GetMethodsByName depends on
11498 * method->slot being defined.
11502 * tb->methods could not be freed since it is used for determining
11503 * overrides during dynamic vtable construction.
11508 mono_reflection_method_get_handle (MonoObject *method)
11510 MonoClass *klass = mono_object_class (method);
11511 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11512 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11513 return sr_method->method;
11515 if (is_sre_method_builder (klass)) {
11516 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11517 return mb->mhandle;
11519 if (is_sre_method_on_tb_inst (klass)) {
11520 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11521 MonoMethod *result;
11522 /*FIXME move this to a proper method and unify with resolve_object*/
11523 if (m->method_args) {
11524 result = mono_reflection_method_on_tb_inst_get_handle (m);
11526 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11527 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11528 MonoMethod *mono_method;
11530 if (is_sre_method_builder (mono_object_class (m->mb)))
11531 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11532 else if (is_sr_mono_method (mono_object_class (m->mb)))
11533 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11535 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)));
11537 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11542 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11547 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11549 MonoReflectionTypeBuilder *tb;
11551 MonoReflectionMethod *m;
11554 *num_overrides = 0;
11556 g_assert (image_is_dynamic (klass->image));
11558 if (!mono_class_get_ref_info (klass))
11561 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11563 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11567 for (i = 0; i < tb->num_methods; ++i) {
11568 MonoReflectionMethodBuilder *mb =
11569 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11570 if (mb->override_methods)
11571 onum += mono_array_length (mb->override_methods);
11576 *overrides = g_new0 (MonoMethod*, onum * 2);
11579 for (i = 0; i < tb->num_methods; ++i) {
11580 MonoReflectionMethodBuilder *mb =
11581 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11582 if (mb->override_methods) {
11583 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11584 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11586 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11587 (*overrides) [onum * 2 + 1] = mb->mhandle;
11589 g_assert (mb->mhandle);
11597 *num_overrides = onum;
11601 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11603 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11604 MonoReflectionFieldBuilder *fb;
11605 MonoClassField *field;
11606 MonoImage *image = klass->image;
11607 const char *p, *p2;
11609 guint32 len, idx, real_size = 0;
11611 klass->field.count = tb->num_fields;
11612 klass->field.first = 0;
11614 mono_error_init (error);
11616 if (tb->class_size) {
11617 if ((tb->packing_size & 0xffffff00) != 0) {
11618 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11619 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11622 klass->packing_size = tb->packing_size;
11623 real_size = klass->instance_size + tb->class_size;
11626 if (!klass->field.count) {
11627 klass->instance_size = MAX (klass->instance_size, real_size);
11631 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11632 mono_class_alloc_ext (klass);
11633 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11635 This is, guess what, a hack.
11636 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11637 On the static path no field class is resolved, only types are built. This is the right thing to do
11639 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11641 klass->size_inited = 1;
11643 for (i = 0; i < klass->field.count; ++i) {
11644 MonoArray *rva_data;
11645 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11646 field = &klass->fields [i];
11647 field->name = mono_string_to_utf8_image (image, fb->name, error);
11648 if (!mono_error_ok (error))
11651 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11652 field->type->attrs = fb->attrs;
11654 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11657 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11658 char *base = mono_array_addr (rva_data, char, 0);
11659 size_t size = mono_array_length (rva_data);
11660 char *data = (char *)mono_image_alloc (klass->image, size);
11661 memcpy (data, base, size);
11662 klass->ext->field_def_values [i].data = data;
11664 if (fb->offset != -1)
11665 field->offset = fb->offset;
11666 field->parent = klass;
11667 fb->handle = field;
11668 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11670 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11671 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11673 if (fb->def_value) {
11674 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11675 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11676 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11677 /* Copy the data from the blob since it might get realloc-ed */
11678 p = assembly->blob.data + idx;
11679 len = mono_metadata_decode_blob_size (p, &p2);
11681 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11682 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11686 klass->instance_size = MAX (klass->instance_size, real_size);
11687 mono_class_layout_fields (klass);
11691 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11693 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11694 MonoReflectionPropertyBuilder *pb;
11695 MonoImage *image = klass->image;
11696 MonoProperty *properties;
11699 mono_error_init (error);
11702 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11704 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11705 klass->ext->property.first = 0;
11707 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11708 klass->ext->properties = properties;
11709 for (i = 0; i < klass->ext->property.count; ++i) {
11710 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11711 properties [i].parent = klass;
11712 properties [i].attrs = pb->attrs;
11713 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11714 if (!mono_error_ok (error))
11716 if (pb->get_method)
11717 properties [i].get = pb->get_method->mhandle;
11718 if (pb->set_method)
11719 properties [i].set = pb->set_method->mhandle;
11721 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11722 if (pb->def_value) {
11724 const char *p, *p2;
11725 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11726 if (!klass->ext->prop_def_values)
11727 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11728 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11729 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11730 /* Copy the data from the blob since it might get realloc-ed */
11731 p = assembly->blob.data + idx;
11732 len = mono_metadata_decode_blob_size (p, &p2);
11734 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11735 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11740 MonoReflectionEvent *
11741 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11743 MonoEvent *event = g_new0 (MonoEvent, 1);
11746 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11748 event->parent = klass;
11749 event->attrs = eb->attrs;
11750 event->name = mono_string_to_utf8 (eb->name);
11751 if (eb->add_method)
11752 event->add = eb->add_method->mhandle;
11753 if (eb->remove_method)
11754 event->remove = eb->remove_method->mhandle;
11755 if (eb->raise_method)
11756 event->raise = eb->raise_method->mhandle;
11758 #ifndef MONO_SMALL_CONFIG
11759 if (eb->other_methods) {
11761 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11762 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11763 MonoReflectionMethodBuilder *mb =
11764 mono_array_get (eb->other_methods,
11765 MonoReflectionMethodBuilder*, j);
11766 event->other [j] = mb->mhandle;
11771 return mono_event_get_object (mono_object_domain (tb), klass, event);
11775 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11777 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11778 MonoReflectionEventBuilder *eb;
11779 MonoImage *image = klass->image;
11783 mono_error_init (error);
11786 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11788 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11789 klass->ext->event.first = 0;
11791 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11792 klass->ext->events = events;
11793 for (i = 0; i < klass->ext->event.count; ++i) {
11794 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11795 events [i].parent = klass;
11796 events [i].attrs = eb->attrs;
11797 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11798 if (!mono_error_ok (error))
11800 if (eb->add_method)
11801 events [i].add = eb->add_method->mhandle;
11802 if (eb->remove_method)
11803 events [i].remove = eb->remove_method->mhandle;
11804 if (eb->raise_method)
11805 events [i].raise = eb->raise_method->mhandle;
11807 #ifndef MONO_SMALL_CONFIG
11808 if (eb->other_methods) {
11810 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11811 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11812 MonoReflectionMethodBuilder *mb =
11813 mono_array_get (eb->other_methods,
11814 MonoReflectionMethodBuilder*, j);
11815 events [i].other [j] = mb->mhandle;
11819 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11824 remove_instantiations_of_and_ensure_contents (gpointer key,
11826 gpointer user_data)
11828 MonoType *type = (MonoType*)key;
11829 MonoClass *klass = (MonoClass*)user_data;
11831 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11832 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11839 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11841 mono_error_init (error);
11847 for (i = 0; i < mono_array_length (arr); ++i) {
11848 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11849 if (!mono_error_ok (error))
11854 MonoReflectionType*
11855 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11859 MonoDomain* domain;
11860 MonoReflectionType* res;
11863 domain = mono_object_domain (tb);
11864 klass = mono_class_from_mono_type (tb->type.type);
11867 * Check for user defined Type subclasses.
11869 RESOLVE_TYPE (tb->parent, &error);
11870 mono_error_raise_exception (&error); /* FIXME don't raise here */
11871 check_array_for_usertypes (tb->interfaces, &error);
11872 mono_error_raise_exception (&error); /*FIXME don't raise here */
11874 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11875 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11877 RESOLVE_TYPE (fb->type, &error);
11878 mono_error_raise_exception (&error); /* FIXME don't raise here */
11879 check_array_for_usertypes (fb->modreq, &error);
11880 mono_error_raise_exception (&error); /*FIXME don't raise here */
11881 check_array_for_usertypes (fb->modopt, &error);
11882 mono_error_raise_exception (&error); /*FIXME don't raise here */
11883 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11884 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11885 mono_error_raise_exception (&error); /* FIXME don't raise here */
11891 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11892 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11894 RESOLVE_TYPE (mb->rtype, &error);
11895 mono_error_raise_exception (&error); /* FIXME don't raise here */
11896 check_array_for_usertypes (mb->return_modreq, &error);
11897 mono_error_raise_exception (&error); /*FIXME don't raise here */
11898 check_array_for_usertypes (mb->return_modopt, &error);
11899 mono_error_raise_exception (&error); /*FIXME don't raise here */
11900 check_array_for_usertypes (mb->parameters, &error);
11901 mono_error_raise_exception (&error); /*FIXME don't raise here */
11902 if (mb->param_modreq)
11903 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11904 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11905 mono_error_raise_exception (&error); /*FIXME don't raise here */
11907 if (mb->param_modopt)
11908 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11909 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11910 mono_error_raise_exception (&error); /*FIXME don't raise here */
11916 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11917 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11919 check_array_for_usertypes (mb->parameters, &error);
11920 mono_error_raise_exception (&error); /*FIXME don't raise here */
11921 if (mb->param_modreq)
11922 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11923 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11924 mono_error_raise_exception (&error); /*FIXME don't raise here */
11926 if (mb->param_modopt)
11927 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11928 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11929 mono_error_raise_exception (&error); /*FIXME don't raise here */
11935 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11938 * we need to lock the domain because the lock will be taken inside
11939 * So, we need to keep the locking order correct.
11941 mono_loader_lock ();
11942 mono_domain_lock (domain);
11943 if (klass->wastypebuilder) {
11944 mono_domain_unlock (domain);
11945 mono_loader_unlock ();
11947 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11948 mono_error_raise_exception (&error); /* FIXME don't raise here */
11953 * Fields to set in klass:
11954 * the various flags: delegate/unicode/contextbound etc.
11956 klass->flags = tb->attrs;
11957 klass->has_cctor = 1;
11958 klass->has_finalize = 1;
11959 klass->has_finalize_inited = 1;
11961 mono_class_setup_parent (klass, klass->parent);
11962 /* fool mono_class_setup_supertypes */
11963 klass->supertypes = NULL;
11964 mono_class_setup_supertypes (klass);
11965 mono_class_setup_mono_type (klass);
11968 if (!((MonoDynamicImage*)klass->image)->run) {
11969 if (klass->generic_container) {
11970 /* FIXME: The code below can't handle generic classes */
11971 klass->wastypebuilder = TRUE;
11972 mono_loader_unlock ();
11973 mono_domain_unlock (domain);
11975 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11976 mono_error_raise_exception (&error); /* FIXME don't raise here */
11983 /* enums are done right away */
11984 if (!klass->enumtype)
11985 ensure_runtime_vtable (klass);
11987 if (tb->subtypes) {
11988 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11989 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11990 mono_class_alloc_ext (klass);
11991 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)));
11995 klass->nested_classes_inited = TRUE;
11997 /* fields and object layout */
11998 if (klass->parent) {
11999 if (!klass->parent->size_inited)
12000 mono_class_init (klass->parent);
12001 klass->instance_size = klass->parent->instance_size;
12002 klass->sizes.class_size = 0;
12003 klass->min_align = klass->parent->min_align;
12004 /* if the type has no fields we won't call the field_setup
12005 * routine which sets up klass->has_references.
12007 klass->has_references |= klass->parent->has_references;
12009 klass->instance_size = sizeof (MonoObject);
12010 klass->min_align = 1;
12013 /* FIXME: handle packing_size and instance_size */
12014 typebuilder_setup_fields (klass, &error);
12015 if (!mono_error_ok (&error))
12017 typebuilder_setup_properties (klass, &error);
12018 if (!mono_error_ok (&error))
12021 typebuilder_setup_events (klass, &error);
12022 if (!mono_error_ok (&error))
12025 klass->wastypebuilder = TRUE;
12028 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12029 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12030 * we want to return normal System.MonoType objects, so clear these out from the cache.
12032 * Together with this we must ensure the contents of all instances to match the created type.
12034 if (domain->type_hash && klass->generic_container)
12035 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12037 mono_domain_unlock (domain);
12038 mono_loader_unlock ();
12040 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12041 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12042 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12045 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12046 mono_error_raise_exception (&error); /* FIXME don't raise here */
12048 g_assert (res != (MonoReflectionType*)tb);
12053 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12054 klass->wastypebuilder = TRUE;
12055 mono_domain_unlock (domain);
12056 mono_loader_unlock ();
12057 mono_error_raise_exception (&error);
12062 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12064 MonoGenericParamFull *param;
12069 image = &gparam->tbuilder->module->dynamic_image->image;
12071 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12073 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12074 g_assert (mono_error_ok (&error));
12075 param->param.num = gparam->index;
12077 if (gparam->mbuilder) {
12078 if (!gparam->mbuilder->generic_container) {
12079 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12080 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12081 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12082 gparam->mbuilder->generic_container->is_method = TRUE;
12084 * Cannot set owner.method, since the MonoMethod is not created yet.
12085 * Set the image field instead, so type_in_image () works.
12087 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12088 gparam->mbuilder->generic_container->owner.image = klass->image;
12090 param->param.owner = gparam->mbuilder->generic_container;
12091 } else if (gparam->tbuilder) {
12092 if (!gparam->tbuilder->generic_container) {
12093 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12094 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12095 gparam->tbuilder->generic_container->owner.klass = klass;
12097 param->param.owner = gparam->tbuilder->generic_container;
12100 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12102 gparam->type.type = &pklass->byval_arg;
12104 mono_class_set_ref_info (pklass, gparam);
12105 mono_image_append_class_to_reflection_info_set (pklass);
12109 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12112 MonoReflectionModuleBuilder *module = sig->module;
12113 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12114 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12119 check_array_for_usertypes (sig->arguments, &error);
12120 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12122 sigbuffer_init (&buf, 32);
12124 sigbuffer_add_value (&buf, 0x07);
12125 sigbuffer_add_value (&buf, na);
12126 if (assembly != NULL){
12127 for (i = 0; i < na; ++i) {
12128 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12129 encode_reflection_type (assembly, type, &buf);
12133 buflen = buf.p - buf.buf;
12134 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12135 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12136 sigbuffer_free (&buf);
12142 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12145 MonoDynamicImage *assembly = sig->module->dynamic_image;
12146 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12151 check_array_for_usertypes (sig->arguments, &error);
12152 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12154 sigbuffer_init (&buf, 32);
12156 sigbuffer_add_value (&buf, 0x06);
12157 for (i = 0; i < na; ++i) {
12158 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12159 encode_reflection_type (assembly, type, &buf);
12162 buflen = buf.p - buf.buf;
12163 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12164 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12165 sigbuffer_free (&buf);
12171 MonoMethod *handle;
12172 MonoDomain *domain;
12173 } DynamicMethodReleaseData;
12176 * The runtime automatically clean up those after finalization.
12178 static MonoReferenceQueue *dynamic_method_queue;
12181 free_dynamic_method (void *dynamic_method)
12183 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12184 MonoDomain *domain = data->domain;
12185 MonoMethod *method = data->handle;
12188 mono_domain_lock (domain);
12189 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12190 g_hash_table_remove (domain->method_to_dyn_method, method);
12191 mono_domain_unlock (domain);
12192 g_assert (dis_link);
12193 mono_gchandle_free (dis_link);
12195 mono_runtime_free_method (domain, method);
12200 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12202 MonoReferenceQueue *queue;
12203 MonoMethod *handle;
12204 DynamicMethodReleaseData *release_data;
12205 ReflectionMethodBuilder rmb;
12206 MonoMethodSignature *sig;
12208 MonoDomain *domain;
12212 if (mono_runtime_is_shutting_down ())
12213 mono_raise_exception (mono_get_exception_invalid_operation (""));
12215 if (!(queue = dynamic_method_queue)) {
12216 mono_loader_lock ();
12217 if (!(queue = dynamic_method_queue))
12218 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12219 mono_loader_unlock ();
12222 sig = dynamic_method_to_signature (mb);
12224 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12227 * Resolve references.
12230 * Every second entry in the refs array is reserved for storing handle_class,
12231 * which is needed by the ldtoken implementation in the JIT.
12233 rmb.nrefs = mb->nrefs;
12234 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12235 for (i = 0; i < mb->nrefs; i += 2) {
12236 MonoClass *handle_class;
12238 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12240 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12241 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12243 * The referenced DynamicMethod should already be created by the managed
12244 * code, except in the case of circular references. In that case, we store
12245 * method in the refs array, and fix it up later when the referenced
12246 * DynamicMethod is created.
12248 if (method->mhandle) {
12249 ref = method->mhandle;
12251 /* FIXME: GC object stored in unmanaged memory */
12254 /* FIXME: GC object stored in unmanaged memory */
12255 method->referenced_by = g_slist_append (method->referenced_by, mb);
12257 handle_class = mono_defaults.methodhandle_class;
12259 MonoException *ex = NULL;
12260 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12262 ex = mono_get_exception_type_load (NULL, NULL);
12263 else if (mono_security_core_clr_enabled ())
12264 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12268 mono_raise_exception (ex);
12273 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12274 rmb.refs [i + 1] = handle_class;
12277 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12279 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12280 release_data = g_new (DynamicMethodReleaseData, 1);
12281 release_data->handle = handle;
12282 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12283 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12284 g_free (release_data);
12286 /* Fix up refs entries pointing at us */
12287 for (l = mb->referenced_by; l; l = l->next) {
12288 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12289 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12292 g_assert (method->mhandle);
12294 data = (gpointer*)wrapper->method_data;
12295 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12296 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12297 data [i + 1] = mb->mhandle;
12300 g_slist_free (mb->referenced_by);
12304 /* ilgen is no longer needed */
12307 domain = mono_domain_get ();
12308 mono_domain_lock (domain);
12309 if (!domain->method_to_dyn_method)
12310 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12311 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12312 mono_domain_unlock (domain);
12315 #endif /* DISABLE_REFLECTION_EMIT */
12319 * mono_reflection_is_valid_dynamic_token:
12321 * Returns TRUE if token is valid.
12325 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12327 return lookup_dyn_token (image, token) != NULL;
12330 MonoMethodSignature *
12331 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12333 MonoMethodSignature *sig;
12334 g_assert (image_is_dynamic (image));
12336 mono_error_init (error);
12338 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12342 return mono_method_signature_checked (method, error);
12345 #ifndef DISABLE_REFLECTION_EMIT
12348 * mono_reflection_lookup_dynamic_token:
12350 * Finish the Builder object pointed to by TOKEN and return the corresponding
12351 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12352 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12355 * LOCKING: Take the loader lock
12358 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12360 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12364 obj = lookup_dyn_token (assembly, token);
12367 g_error ("Could not find required dynamic token 0x%08x", token);
12373 handle_class = &klass;
12374 return resolve_object (image, obj, handle_class, context);
12378 * ensure_complete_type:
12380 * Ensure that KLASS is completed if it is a dynamic type, or references
12384 ensure_complete_type (MonoClass *klass)
12386 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12387 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12389 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12391 // Asserting here could break a lot of code
12392 //g_assert (klass->wastypebuilder);
12395 if (klass->generic_class) {
12396 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12399 for (i = 0; i < inst->type_argc; ++i) {
12400 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12406 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12408 gpointer result = NULL;
12410 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12411 result = mono_string_intern ((MonoString*)obj);
12412 *handle_class = mono_defaults.string_class;
12414 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12415 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12416 MonoClass *mc = mono_class_from_mono_type (type);
12417 if (!mono_class_init (mc))
12418 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12421 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12422 result = mono_class_from_mono_type (inflated);
12423 mono_metadata_free_type (inflated);
12425 result = mono_class_from_mono_type (type);
12427 *handle_class = mono_defaults.typehandle_class;
12429 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12430 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12431 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12432 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12433 result = ((MonoReflectionMethod*)obj)->method;
12436 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12437 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12439 *handle_class = mono_defaults.methodhandle_class;
12441 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12442 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12443 result = mb->mhandle;
12445 /* Type is not yet created */
12446 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12448 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12451 * Hopefully this has been filled in by calling CreateType() on the
12455 * TODO: This won't work if the application finishes another
12456 * TypeBuilder instance instead of this one.
12458 result = mb->mhandle;
12462 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12463 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12465 *handle_class = mono_defaults.methodhandle_class;
12466 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12467 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12469 result = cb->mhandle;
12471 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12473 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12474 result = cb->mhandle;
12478 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12479 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12481 *handle_class = mono_defaults.methodhandle_class;
12482 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12483 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12485 ensure_complete_type (field->parent);
12487 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12488 MonoClass *klass = mono_class_from_mono_type (inflated);
12489 MonoClassField *inflated_field;
12490 gpointer iter = NULL;
12491 mono_metadata_free_type (inflated);
12492 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12493 if (!strcmp (field->name, inflated_field->name))
12496 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12497 result = inflated_field;
12501 *handle_class = mono_defaults.fieldhandle_class;
12503 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12504 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12505 result = fb->handle;
12508 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12510 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12511 result = fb->handle;
12514 if (fb->handle && fb->handle->parent->generic_container) {
12515 MonoClass *klass = fb->handle->parent;
12516 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12517 MonoClass *inflated = mono_class_from_mono_type (type);
12519 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12521 mono_metadata_free_type (type);
12523 *handle_class = mono_defaults.fieldhandle_class;
12524 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12525 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12526 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12529 klass = type->data.klass;
12530 if (klass->wastypebuilder) {
12531 /* Already created */
12535 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12536 result = type->data.klass;
12539 *handle_class = mono_defaults.typehandle_class;
12540 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12541 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12542 MonoMethodSignature *sig;
12545 if (helper->arguments)
12546 nargs = mono_array_length (helper->arguments);
12550 sig = mono_metadata_signature_alloc (image, nargs);
12551 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12552 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12554 if (helper->unmanaged_call_conv) { /* unmanaged */
12555 sig->call_convention = helper->unmanaged_call_conv - 1;
12556 sig->pinvoke = TRUE;
12557 } else if (helper->call_conv & 0x02) {
12558 sig->call_convention = MONO_CALL_VARARG;
12560 sig->call_convention = MONO_CALL_DEFAULT;
12563 sig->param_count = nargs;
12564 /* TODO: Copy type ? */
12565 sig->ret = helper->return_type->type;
12566 for (i = 0; i < nargs; ++i)
12567 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12570 *handle_class = NULL;
12571 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12572 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12573 /* Already created by the managed code */
12574 g_assert (method->mhandle);
12575 result = method->mhandle;
12576 *handle_class = mono_defaults.methodhandle_class;
12577 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12578 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12579 type = mono_class_inflate_generic_type (type, context);
12580 result = mono_class_from_mono_type (type);
12581 *handle_class = mono_defaults.typehandle_class;
12583 mono_metadata_free_type (type);
12584 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12585 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12586 type = mono_class_inflate_generic_type (type, context);
12587 result = mono_class_from_mono_type (type);
12588 *handle_class = mono_defaults.typehandle_class;
12590 mono_metadata_free_type (type);
12591 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12592 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12593 MonoClass *inflated;
12595 MonoClassField *field;
12597 if (is_sre_field_builder (mono_object_class (f->fb)))
12598 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12599 else if (is_sr_mono_field (mono_object_class (f->fb)))
12600 field = ((MonoReflectionField*)f->fb)->field;
12602 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)));
12604 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12605 inflated = mono_class_from_mono_type (type);
12607 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12608 ensure_complete_type (field->parent);
12610 mono_metadata_free_type (type);
12611 *handle_class = mono_defaults.fieldhandle_class;
12612 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12613 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12614 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12615 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12616 MonoMethod *method;
12618 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12619 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12620 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12621 method = ((MonoReflectionMethod *)c->cb)->method;
12623 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)));
12625 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12626 *handle_class = mono_defaults.methodhandle_class;
12627 mono_metadata_free_type (type);
12628 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12629 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12630 if (m->method_args) {
12631 result = mono_reflection_method_on_tb_inst_get_handle (m);
12634 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12635 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12638 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12639 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12640 MonoMethod *method;
12642 if (is_sre_method_builder (mono_object_class (m->mb)))
12643 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12644 else if (is_sr_mono_method (mono_object_class (m->mb)))
12645 method = ((MonoReflectionMethod *)m->mb)->method;
12647 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)));
12649 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12650 mono_metadata_free_type (type);
12652 *handle_class = mono_defaults.methodhandle_class;
12653 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12654 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12657 MonoMethod *method;
12661 mtype = mono_reflection_type_get_handle (m->parent);
12662 klass = mono_class_from_mono_type (mtype);
12664 /* Find the method */
12666 name = mono_string_to_utf8 (m->name);
12668 while ((method = mono_class_get_methods (klass, &iter))) {
12669 if (!strcmp (method->name, name))
12676 // FIXME: Check parameters/return value etc. match
12679 *handle_class = mono_defaults.methodhandle_class;
12680 } else if (is_sre_array (mono_object_get_class(obj)) ||
12681 is_sre_byref (mono_object_get_class(obj)) ||
12682 is_sre_pointer (mono_object_get_class(obj))) {
12683 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12684 MonoType *type = mono_reflection_type_get_handle (ref_type);
12687 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12688 result = mono_class_from_mono_type (inflated);
12689 mono_metadata_free_type (inflated);
12691 result = mono_class_from_mono_type (type);
12693 *handle_class = mono_defaults.typehandle_class;
12695 g_print ("%s\n", obj->vtable->klass->name);
12696 g_assert_not_reached ();
12701 #else /* DISABLE_REFLECTION_EMIT */
12704 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12706 g_assert_not_reached ();
12711 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12713 g_assert_not_reached ();
12717 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12719 g_assert_not_reached ();
12723 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12725 g_assert_not_reached ();
12729 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12731 g_assert_not_reached ();
12735 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12737 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12741 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12743 g_assert_not_reached ();
12747 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12749 g_assert_not_reached ();
12752 MonoReflectionModule *
12753 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12755 g_assert_not_reached ();
12760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12762 g_assert_not_reached ();
12767 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12769 g_assert_not_reached ();
12774 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12775 gboolean create_open_instance, gboolean register_token)
12777 g_assert_not_reached ();
12782 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12787 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12789 g_assert_not_reached ();
12793 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12796 *num_overrides = 0;
12799 MonoReflectionEvent *
12800 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12802 g_assert_not_reached ();
12806 MonoReflectionType*
12807 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12809 g_assert_not_reached ();
12814 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12816 g_assert_not_reached ();
12820 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12822 g_assert_not_reached ();
12827 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12829 g_assert_not_reached ();
12834 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12839 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12845 mono_reflection_type_get_handle (MonoReflectionType* ref)
12853 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12855 g_assert_not_reached ();
12858 #endif /* DISABLE_REFLECTION_EMIT */
12860 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12861 const static guint32 declsec_flags_map[] = {
12862 0x00000000, /* empty */
12863 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12864 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12865 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12866 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12867 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12868 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12869 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12870 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12871 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12872 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12873 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12874 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12875 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12876 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12877 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12878 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12879 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12880 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12884 * Returns flags that includes all available security action associated to the handle.
12885 * @token: metadata token (either for a class or a method)
12886 * @image: image where resides the metadata.
12889 mono_declsec_get_flags (MonoImage *image, guint32 token)
12891 int index = mono_metadata_declsec_from_index (image, token);
12892 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12893 guint32 result = 0;
12897 /* HasSecurity can be present for other, not specially encoded, attributes,
12898 e.g. SuppressUnmanagedCodeSecurityAttribute */
12902 for (i = index; i < t->rows; i++) {
12903 guint32 cols [MONO_DECL_SECURITY_SIZE];
12905 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12906 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12909 action = cols [MONO_DECL_SECURITY_ACTION];
12910 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12911 result |= declsec_flags_map [action];
12913 g_assert_not_reached ();
12920 * Get the security actions (in the form of flags) associated with the specified method.
12922 * @method: The method for which we want the declarative security flags.
12923 * Return the declarative security flags for the method (only).
12925 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12926 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12929 mono_declsec_flags_from_method (MonoMethod *method)
12931 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12932 /* FIXME: No cache (for the moment) */
12933 guint32 idx = mono_method_get_index (method);
12934 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12935 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12936 return mono_declsec_get_flags (method->klass->image, idx);
12942 * Get the security actions (in the form of flags) associated with the specified class.
12944 * @klass: The class for which we want the declarative security flags.
12945 * Return the declarative security flags for the class.
12947 * Note: We cache the flags inside the MonoClass structure as this will get
12948 * called very often (at least for each method).
12951 mono_declsec_flags_from_class (MonoClass *klass)
12953 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12954 if (!klass->ext || !klass->ext->declsec_flags) {
12957 idx = mono_metadata_token_index (klass->type_token);
12958 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12959 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12960 mono_loader_lock ();
12961 mono_class_alloc_ext (klass);
12962 mono_loader_unlock ();
12963 /* we cache the flags on classes */
12964 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12966 return klass->ext->declsec_flags;
12972 * Get the security actions (in the form of flags) associated with the specified assembly.
12974 * @assembly: The assembly for which we want the declarative security flags.
12975 * Return the declarative security flags for the assembly.
12978 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12980 guint32 idx = 1; /* there is only one assembly */
12981 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12982 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12983 return mono_declsec_get_flags (assembly->image, idx);
12988 * Fill actions for the specific index (which may either be an encoded class token or
12989 * an encoded method token) from the metadata image.
12990 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12993 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12994 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12996 MonoBoolean result = FALSE;
12998 guint32 cols [MONO_DECL_SECURITY_SIZE];
12999 int index = mono_metadata_declsec_from_index (image, token);
13002 t = &image->tables [MONO_TABLE_DECLSECURITY];
13003 for (i = index; i < t->rows; i++) {
13004 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13006 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13009 /* if present only replace (class) permissions with method permissions */
13010 /* if empty accept either class or method permissions */
13011 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13012 if (!actions->demand.blob) {
13013 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13014 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13015 actions->demand.blob = (char*) (blob + 2);
13016 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13019 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13020 if (!actions->noncasdemand.blob) {
13021 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13022 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13023 actions->noncasdemand.blob = (char*) (blob + 2);
13024 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13027 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13028 if (!actions->demandchoice.blob) {
13029 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13030 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13031 actions->demandchoice.blob = (char*) (blob + 2);
13032 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13042 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13043 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13045 guint32 idx = mono_metadata_token_index (klass->type_token);
13046 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13047 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13048 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13052 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13053 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13055 guint32 idx = mono_method_get_index (method);
13056 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13057 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13058 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13062 * Collect all actions (that requires to generate code in mini) assigned for
13063 * the specified method.
13064 * Note: Don't use the content of actions if the function return FALSE.
13067 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13069 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13070 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13071 MonoBoolean result = FALSE;
13074 /* quick exit if no declarative security is present in the metadata */
13075 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13078 /* we want the original as the wrapper is "free" of the security informations */
13079 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13080 method = mono_marshal_method_from_wrapper (method);
13085 /* First we look for method-level attributes */
13086 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13087 mono_class_init (method->klass);
13088 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13090 result = mono_declsec_get_method_demands_params (method, demands,
13091 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13094 /* Here we use (or create) the class declarative cache to look for demands */
13095 flags = mono_declsec_flags_from_class (method->klass);
13096 if (flags & mask) {
13098 mono_class_init (method->klass);
13099 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13101 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13102 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13105 /* The boolean return value is used as a shortcut in case nothing needs to
13106 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13112 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13114 * Note: Don't use the content of actions if the function return FALSE.
13117 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13119 MonoBoolean result = FALSE;
13122 /* quick exit if no declarative security is present in the metadata */
13123 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13126 /* we want the original as the wrapper is "free" of the security informations */
13127 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13128 method = mono_marshal_method_from_wrapper (method);
13133 /* results are independant - zeroize both */
13134 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13135 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13137 /* First we look for method-level attributes */
13138 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13139 mono_class_init (method->klass);
13141 result = mono_declsec_get_method_demands_params (method, cmethod,
13142 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13145 /* Here we use (or create) the class declarative cache to look for demands */
13146 flags = mono_declsec_flags_from_class (method->klass);
13147 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13148 mono_class_init (method->klass);
13150 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13151 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13158 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13160 * @klass The inherited class - this is the class that provides the security check (attributes)
13162 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13164 * Note: Don't use the content of actions if the function return FALSE.
13167 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13169 MonoBoolean result = FALSE;
13172 /* quick exit if no declarative security is present in the metadata */
13173 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13176 /* Here we use (or create) the class declarative cache to look for demands */
13177 flags = mono_declsec_flags_from_class (klass);
13178 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13179 mono_class_init (klass);
13180 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13182 result |= mono_declsec_get_class_demands_params (klass, demands,
13183 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13190 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13192 * Note: Don't use the content of actions if the function return FALSE.
13195 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13197 /* quick exit if no declarative security is present in the metadata */
13198 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13201 /* we want the original as the wrapper is "free" of the security informations */
13202 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13203 method = mono_marshal_method_from_wrapper (method);
13208 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13209 mono_class_init (method->klass);
13210 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13212 return mono_declsec_get_method_demands_params (method, demands,
13213 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13220 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13222 guint32 cols [MONO_DECL_SECURITY_SIZE];
13226 int index = mono_metadata_declsec_from_index (image, token);
13230 t = &image->tables [MONO_TABLE_DECLSECURITY];
13231 for (i = index; i < t->rows; i++) {
13232 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13234 /* shortcut - index are ordered */
13235 if (token != cols [MONO_DECL_SECURITY_PARENT])
13238 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13239 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13240 entry->blob = (char*) (metadata + 2);
13241 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13250 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13252 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13253 guint32 idx = mono_method_get_index (method);
13254 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13255 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13256 return get_declsec_action (method->klass->image, idx, action, entry);
13262 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13265 guint32 flags = mono_declsec_flags_from_class (klass);
13266 if (declsec_flags_map [action] & flags) {
13267 guint32 idx = mono_metadata_token_index (klass->type_token);
13268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13269 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13270 return get_declsec_action (klass->image, idx, action, entry);
13276 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13278 guint32 idx = 1; /* there is only one assembly */
13279 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13280 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13282 return get_declsec_action (assembly->image, idx, action, entry);
13286 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13289 MonoObject *res, *exc;
13291 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13292 static MonoMethod *method = NULL;
13294 if (!System_Reflection_Emit_TypeBuilder) {
13295 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13296 g_assert (System_Reflection_Emit_TypeBuilder);
13298 if (method == NULL) {
13299 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13304 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13305 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13307 g_assert (mono_class_get_ref_info (klass));
13308 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13310 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13311 mono_error_raise_exception (&error); /* FIXME don't raise here */
13313 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13317 return *(MonoBoolean*)mono_object_unbox (res);
13321 * mono_reflection_type_get_type:
13322 * @reftype: the System.Type object
13324 * Returns the MonoType* associated with the C# System.Type object @reftype.
13327 mono_reflection_type_get_type (MonoReflectionType *reftype)
13329 g_assert (reftype);
13331 return mono_reflection_type_get_handle (reftype);
13335 * mono_reflection_assembly_get_assembly:
13336 * @refassembly: the System.Reflection.Assembly object
13338 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13341 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13343 g_assert (refassembly);
13345 return refassembly->assembly;