2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
226 dynamic_images_lock (void)
228 mono_os_mutex_lock (&dynamic_images_mutex);
232 dynamic_images_unlock (void)
234 mono_os_mutex_unlock (&dynamic_images_mutex);
238 * mono_find_dynamic_image_owner:
240 * Find the dynamic image, if any, which a given pointer is located in the memory of.
243 mono_find_dynamic_image_owner (void *ptr)
245 MonoImage *owner = NULL;
248 dynamic_images_lock ();
252 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254 if (mono_mempool_contains_addr (image->mempool, ptr))
259 dynamic_images_unlock ();
265 mono_reflection_init (void)
267 mono_os_mutex_init (&dynamic_images_mutex);
271 dynamic_image_lock (MonoDynamicImage *image)
273 MONO_PREPARE_BLOCKING;
274 mono_image_lock ((MonoImage*)image);
275 MONO_FINISH_BLOCKING;
279 dynamic_image_unlock (MonoDynamicImage *image)
281 mono_image_unlock ((MonoImage*)image);
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
287 MONO_REQ_GC_UNSAFE_MODE;
289 dynamic_image_lock (assembly);
290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291 dynamic_image_unlock (assembly);
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
297 MONO_REQ_GC_UNSAFE_MODE;
301 dynamic_image_lock (assembly);
302 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303 dynamic_image_unlock (assembly);
309 sigbuffer_init (SigBuffer *buf, int size)
311 MONO_REQ_GC_NEUTRAL_MODE;
313 buf->buf = (char *)g_malloc (size);
315 buf->end = buf->buf + size;
319 sigbuffer_make_room (SigBuffer *buf, int size)
321 MONO_REQ_GC_NEUTRAL_MODE;
323 if (buf->end - buf->p < size) {
324 int new_size = buf->end - buf->buf + size + 32;
325 char *p = (char *)g_realloc (buf->buf, new_size);
326 size = buf->p - buf->buf;
329 buf->end = buf->buf + new_size;
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
336 MONO_REQ_GC_NEUTRAL_MODE;
338 sigbuffer_make_room (buf, 6);
339 mono_metadata_encode_value (val, buf->p, &buf->p);
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 sigbuffer_make_room (buf, 1);
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
355 MONO_REQ_GC_NEUTRAL_MODE;
357 sigbuffer_make_room (buf, size);
358 memcpy (buf->p, p, size);
363 sigbuffer_free (SigBuffer *buf)
365 MONO_REQ_GC_NEUTRAL_MODE;
370 #ifndef DISABLE_REFLECTION_EMIT
374 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
378 image_g_malloc (MonoImage *image, guint size)
380 MONO_REQ_GC_NEUTRAL_MODE;
383 return mono_image_alloc (image, size);
385 return g_malloc (size);
387 #endif /* !DISABLE_REFLECTION_EMIT */
392 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 image_g_malloc0 (MonoImage *image, guint size)
398 MONO_REQ_GC_NEUTRAL_MODE;
401 return mono_image_alloc0 (image, size);
403 return g_malloc0 (size);
406 #ifndef DISABLE_REFLECTION_EMIT
408 image_strdup (MonoImage *image, const char *s)
410 MONO_REQ_GC_NEUTRAL_MODE;
413 return mono_image_strdup (image, s);
419 #define image_g_new(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
422 #define image_g_new0(image,struct_type, n_structs) \
423 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
427 alloc_table (MonoDynamicTable *table, guint nrows)
429 MONO_REQ_GC_NEUTRAL_MODE;
432 g_assert (table->columns);
433 if (nrows + 1 >= table->alloc_rows) {
434 while (nrows + 1 >= table->alloc_rows) {
435 if (table->alloc_rows == 0)
436 table->alloc_rows = 16;
438 table->alloc_rows *= 2;
441 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
446 make_room_in_stream (MonoDynamicStream *stream, int size)
448 MONO_REQ_GC_NEUTRAL_MODE;
450 if (size <= stream->alloc_size)
453 while (stream->alloc_size <= size) {
454 if (stream->alloc_size < 4096)
455 stream->alloc_size = 4096;
457 stream->alloc_size *= 2;
460 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
466 MONO_REQ_GC_NEUTRAL_MODE;
470 gpointer oldkey, oldval;
472 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473 return GPOINTER_TO_UINT (oldval);
475 len = strlen (str) + 1;
478 make_room_in_stream (sh, idx + len);
481 * We strdup the string even if we already copy them in sh->data
482 * so that the string pointers in the hash remain valid even if
483 * we need to realloc sh->data. We may want to avoid that later.
485 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486 memcpy (sh->data + idx, str, len);
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
494 MONO_REQ_GC_UNSAFE_MODE;
496 char *name = mono_string_to_utf8 (str);
498 idx = string_heap_insert (sh, name);
503 #ifndef DISABLE_REFLECTION_EMIT
505 string_heap_init (MonoDynamicStream *sh)
507 MONO_REQ_GC_NEUTRAL_MODE;
510 sh->alloc_size = 4096;
511 sh->data = (char *)g_malloc (4096);
512 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513 string_heap_insert (sh, "");
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 make_room_in_stream (stream, stream->index + len);
525 memcpy (stream->data + stream->index, data, len);
527 stream->index += len;
529 * align index? Not without adding an additional param that controls it since
530 * we may store a blob value in pieces.
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
538 MONO_REQ_GC_NEUTRAL_MODE;
542 make_room_in_stream (stream, stream->index + len);
543 memset (stream->data + stream->index, 0, len);
545 stream->index += len;
550 stream_data_align (MonoDynamicStream *stream)
552 MONO_REQ_GC_NEUTRAL_MODE;
555 guint32 count = stream->index % 4;
557 /* we assume the stream data will be aligned */
559 mono_image_add_stream_data (stream, buf, 4 - count);
562 #ifndef DISABLE_REFLECTION_EMIT
564 mono_blob_entry_hash (const char* str)
566 MONO_REQ_GC_NEUTRAL_MODE;
570 len = mono_metadata_decode_blob_size (str, &str);
574 for (str += 1; str < end; str++)
575 h = (h << 5) - h + *str;
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584 MONO_REQ_GC_NEUTRAL_MODE;
589 len = mono_metadata_decode_blob_size (str1, &end1);
590 len2 = mono_metadata_decode_blob_size (str2, &end2);
593 return memcmp (end1, end2, len) == 0;
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
599 MONO_REQ_GC_NEUTRAL_MODE;
603 gpointer oldkey, oldval;
605 copy = (char *)g_malloc (s1+s2);
606 memcpy (copy, b1, s1);
607 memcpy (copy + s1, b2, s2);
608 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
610 idx = GPOINTER_TO_UINT (oldval);
612 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613 mono_image_add_stream_data (&assembly->blob, b2, s2);
614 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
622 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 size = buf->p - buf->buf;
628 g_assert (size <= (buf->end - buf->buf));
629 mono_metadata_encode_value (size, b, &b);
630 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
634 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635 * dest may be misaligned.
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639 MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
643 for (elem = 0; elem < nelem; ++elem) {
669 g_assert_not_reached ();
675 memcpy (dest, val, len * nelem);
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
682 MONO_REQ_GC_UNSAFE_MODE;
686 guint32 idx = 0, len;
688 len = str->length * 2;
689 mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
692 char *swapped = g_malloc (2 * mono_string_length (str));
693 const char *p = (const char*)mono_string_chars (str);
695 swap_with_size (swapped, p, 2, mono_string_length (str));
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
700 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
705 #ifndef DISABLE_REFLECTION_EMIT
707 default_class_from_mono_type (MonoType *type)
709 MONO_REQ_GC_NEUTRAL_MODE;
711 switch (type->type) {
712 case MONO_TYPE_OBJECT:
713 return mono_defaults.object_class;
715 return mono_defaults.void_class;
716 case MONO_TYPE_BOOLEAN:
717 return mono_defaults.boolean_class;
719 return mono_defaults.char_class;
721 return mono_defaults.sbyte_class;
723 return mono_defaults.byte_class;
725 return mono_defaults.int16_class;
727 return mono_defaults.uint16_class;
729 return mono_defaults.int32_class;
731 return mono_defaults.uint32_class;
733 return mono_defaults.int_class;
735 return mono_defaults.uint_class;
737 return mono_defaults.int64_class;
739 return mono_defaults.uint64_class;
741 return mono_defaults.single_class;
743 return mono_defaults.double_class;
744 case MONO_TYPE_STRING:
745 return mono_defaults.string_class;
747 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748 g_assert_not_reached ();
756 * mono_class_get_ref_info:
758 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
761 mono_class_get_ref_info (MonoClass *klass)
763 MONO_REQ_GC_UNSAFE_MODE;
765 if (klass->ref_info_handle == 0)
768 return mono_gchandle_get_target (klass->ref_info_handle);
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
774 MONO_REQ_GC_UNSAFE_MODE;
776 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777 g_assert (klass->ref_info_handle != 0);
781 mono_class_free_ref_info (MonoClass *klass)
783 MONO_REQ_GC_NEUTRAL_MODE;
785 if (klass->ref_info_handle) {
786 mono_gchandle_free (klass->ref_info_handle);
787 klass->ref_info_handle = 0;
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
794 MONO_REQ_GC_NEUTRAL_MODE;
797 MonoGenericInst *class_inst;
802 class_inst = gclass->context.class_inst;
804 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805 klass = gclass->container_class;
806 sigbuffer_add_value (buf, klass->byval_arg.type);
807 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
809 sigbuffer_add_value (buf, class_inst->type_argc);
810 for (i = 0; i < class_inst->type_argc; ++i)
811 encode_type (assembly, class_inst->type_argv [i], buf);
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
818 MONO_REQ_GC_NEUTRAL_MODE;
821 g_assert_not_reached ();
826 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
830 case MONO_TYPE_BOOLEAN:
844 case MONO_TYPE_STRING:
845 case MONO_TYPE_OBJECT:
846 case MONO_TYPE_TYPEDBYREF:
847 sigbuffer_add_value (buf, type->type);
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, type->data.type, buf);
853 case MONO_TYPE_SZARRAY:
854 sigbuffer_add_value (buf, type->type);
855 encode_type (assembly, &type->data.klass->byval_arg, buf);
857 case MONO_TYPE_VALUETYPE:
858 case MONO_TYPE_CLASS: {
859 MonoClass *k = mono_class_from_mono_type (type);
861 if (k->generic_container) {
862 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863 encode_generic_class (assembly, gclass, buf);
866 * Make sure we use the correct type.
868 sigbuffer_add_value (buf, k->byval_arg.type);
870 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871 * otherwise two typerefs could point to the same type, leading to
872 * verification errors.
874 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
878 case MONO_TYPE_ARRAY:
879 sigbuffer_add_value (buf, type->type);
880 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881 sigbuffer_add_value (buf, type->data.array->rank);
882 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883 sigbuffer_add_value (buf, 0);
885 case MONO_TYPE_GENERICINST:
886 encode_generic_class (assembly, type->data.generic_class, buf);
890 sigbuffer_add_value (buf, type->type);
891 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
894 g_error ("need to encode type %x", type->type);
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
901 MONO_REQ_GC_UNSAFE_MODE;
904 sigbuffer_add_value (buf, MONO_TYPE_VOID);
908 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
914 MONO_REQ_GC_UNSAFE_MODE;
919 for (i = 0; i < mono_array_length (modreq); ++i) {
920 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926 for (i = 0; i < mono_array_length (modopt); ++i) {
927 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
934 #ifndef DISABLE_REFLECTION_EMIT
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
938 MONO_REQ_GC_UNSAFE_MODE;
942 guint32 nparams = sig->param_count;
948 sigbuffer_init (&buf, 32);
950 * FIXME: vararg, explicit_this, differenc call_conv values...
952 idx = sig->call_convention;
954 idx |= 0x20; /* hasthis */
955 if (sig->generic_param_count)
956 idx |= 0x10; /* generic */
957 sigbuffer_add_byte (&buf, idx);
958 if (sig->generic_param_count)
959 sigbuffer_add_value (&buf, sig->generic_param_count);
960 sigbuffer_add_value (&buf, nparams);
961 encode_type (assembly, sig->ret, &buf);
962 for (i = 0; i < nparams; ++i) {
963 if (i == sig->sentinelpos)
964 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965 encode_type (assembly, sig->params [i], &buf);
967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968 sigbuffer_free (&buf);
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
976 MONO_REQ_GC_UNSAFE_MODE;
979 * FIXME: reuse code from method_encode_signature().
983 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
984 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
988 sigbuffer_init (&buf, 32);
989 /* LAMESPEC: all the call conv spec is foobared */
990 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991 if (mb->call_conv & 2)
992 idx |= 0x5; /* vararg */
993 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994 idx |= 0x20; /* hasthis */
996 idx |= 0x10; /* generic */
997 sigbuffer_add_byte (&buf, idx);
999 sigbuffer_add_value (&buf, ngparams);
1000 sigbuffer_add_value (&buf, nparams + notypes);
1001 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002 encode_reflection_type (assembly, mb->rtype, &buf);
1003 for (i = 0; i < nparams; ++i) {
1004 MonoArray *modreq = NULL;
1005 MonoArray *modopt = NULL;
1006 MonoReflectionType *pt;
1008 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014 encode_reflection_type (assembly, pt, &buf);
1017 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018 for (i = 0; i < notypes; ++i) {
1019 MonoReflectionType *pt;
1021 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022 encode_reflection_type (assembly, pt, &buf);
1025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026 sigbuffer_free (&buf);
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1033 MONO_REQ_GC_UNSAFE_MODE;
1035 MonoDynamicTable *table;
1037 guint32 idx, sig_idx;
1038 guint nl = mono_array_length (ilgen->locals);
1042 sigbuffer_init (&buf, 32);
1043 sigbuffer_add_value (&buf, 0x07);
1044 sigbuffer_add_value (&buf, nl);
1045 for (i = 0; i < nl; ++i) {
1046 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1049 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1051 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1053 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1056 if (assembly->standalonesig_cache == NULL)
1057 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1062 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063 idx = table->next_idx ++;
1065 alloc_table (table, table->rows);
1066 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1068 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1070 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1078 MONO_REQ_GC_UNSAFE_MODE;
1080 guint32 num_clauses = 0;
1083 MonoILExceptionInfo *ex_info;
1084 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086 if (ex_info->handlers)
1087 num_clauses += mono_array_length (ex_info->handlers);
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 MonoExceptionClause *clauses;
1102 MonoExceptionClause *clause;
1103 MonoILExceptionInfo *ex_info;
1104 MonoILExceptionBlock *ex_block;
1105 guint32 finally_start;
1106 int i, j, clause_index;;
1108 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1111 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113 finally_start = ex_info->start + ex_info->len;
1114 if (!ex_info->handlers)
1116 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118 clause = &(clauses [clause_index]);
1120 clause->flags = ex_block->type;
1121 clause->try_offset = ex_info->start;
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124 clause->try_len = finally_start - ex_info->start;
1126 clause->try_len = ex_info->len;
1127 clause->handler_offset = ex_block->start;
1128 clause->handler_len = ex_block->len;
1129 if (ex_block->extype) {
1130 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1132 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133 clause->data.filter_offset = ex_block->filter_offset;
1135 clause->data.filter_offset = 0;
1137 finally_start = ex_block->start + ex_block->len;
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1148 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1150 MONO_REQ_GC_UNSAFE_MODE;
1155 gint32 max_stack, i;
1156 gint32 num_locals = 0;
1157 gint32 num_exception = 0;
1160 char fat_header [12];
1162 guint16 short_value;
1163 guint32 local_sig = 0;
1164 guint32 header_size = 12;
1167 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1168 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1172 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1174 code = mb->ilgen->code;
1175 code_size = mb->ilgen->code_len;
1176 max_stack = mb->ilgen->max_stack;
1177 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1178 if (mb->ilgen->ex_handlers)
1179 num_exception = method_count_clauses (mb->ilgen);
1183 char *name = mono_string_to_utf8 (mb->name);
1184 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1185 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1188 mono_raise_exception (exception);
1191 code_size = mono_array_length (code);
1192 max_stack = 8; /* we probably need to run a verifier on the code... */
1195 stream_data_align (&assembly->code);
1197 /* check for exceptions, maxstack, locals */
1198 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1200 if (code_size < 64 && !(code_size & 1)) {
1201 flags = (code_size << 2) | 0x2;
1202 } else if (code_size < 32 && (code_size & 1)) {
1203 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1207 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1208 /* add to the fixup todo list */
1209 if (mb->ilgen && mb->ilgen->num_token_fixups)
1210 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1211 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1212 return assembly->text_rva + idx;
1216 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1218 * FIXME: need to set also the header size in fat_flags.
1219 * (and more sects and init locals flags)
1223 fat_flags |= METHOD_HEADER_MORE_SECTS;
1224 if (mb->init_locals)
1225 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1226 fat_header [0] = fat_flags;
1227 fat_header [1] = (header_size / 4 ) << 4;
1228 short_value = GUINT16_TO_LE (max_stack);
1229 memcpy (fat_header + 2, &short_value, 2);
1230 int_value = GUINT32_TO_LE (code_size);
1231 memcpy (fat_header + 4, &int_value, 4);
1232 int_value = GUINT32_TO_LE (local_sig);
1233 memcpy (fat_header + 8, &int_value, 4);
1234 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1235 /* add to the fixup todo list */
1236 if (mb->ilgen && mb->ilgen->num_token_fixups)
1237 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1239 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1240 if (num_exception) {
1241 unsigned char sheader [4];
1242 MonoILExceptionInfo * ex_info;
1243 MonoILExceptionBlock * ex_block;
1246 stream_data_align (&assembly->code);
1247 /* always use fat format for now */
1248 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1249 num_exception *= 6 * sizeof (guint32);
1250 num_exception += 4; /* include the size of the header */
1251 sheader [1] = num_exception & 0xff;
1252 sheader [2] = (num_exception >> 8) & 0xff;
1253 sheader [3] = (num_exception >> 16) & 0xff;
1254 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1255 /* fat header, so we are already aligned */
1257 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1258 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1259 if (ex_info->handlers) {
1260 int finally_start = ex_info->start + ex_info->len;
1261 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1263 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1265 val = GUINT32_TO_LE (ex_block->type);
1266 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1268 val = GUINT32_TO_LE (ex_info->start);
1269 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1270 /* need fault, too, probably */
1271 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1272 val = GUINT32_TO_LE (finally_start - ex_info->start);
1274 val = GUINT32_TO_LE (ex_info->len);
1275 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276 /* handler offset */
1277 val = GUINT32_TO_LE (ex_block->start);
1278 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1280 val = GUINT32_TO_LE (ex_block->len);
1281 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1282 finally_start = ex_block->start + ex_block->len;
1283 if (ex_block->extype) {
1284 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1286 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1287 val = ex_block->filter_offset;
1291 val = GUINT32_TO_LE (val);
1292 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1294 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1297 g_error ("No clauses for ex info block %d", i);
1301 return assembly->text_rva + idx;
1305 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1307 MONO_REQ_GC_NEUTRAL_MODE;
1310 MonoDynamicTable *table;
1313 table = &assembly->tables [table_idx];
1315 g_assert (col < table->columns);
1317 values = table->values + table->columns;
1318 for (i = 1; i <= table->rows; ++i) {
1319 if (values [col] == token)
1321 values += table->columns;
1327 * LOCKING: Acquires the loader lock.
1329 static MonoCustomAttrInfo*
1330 lookup_custom_attr (MonoImage *image, gpointer member)
1332 MONO_REQ_GC_NEUTRAL_MODE;
1334 MonoCustomAttrInfo* res;
1336 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1341 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1347 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1349 MONO_REQ_GC_UNSAFE_MODE;
1351 /* FIXME: Need to do more checks */
1352 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1353 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1355 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1362 static MonoCustomAttrInfo*
1363 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1365 MONO_REQ_GC_UNSAFE_MODE;
1367 int i, index, count, not_visible;
1368 MonoCustomAttrInfo *ainfo;
1369 MonoReflectionCustomAttr *cattr;
1373 /* FIXME: check in assembly the Run flag is set */
1375 count = mono_array_length (cattrs);
1377 /* Skip nonpublic attributes since MS.NET seems to do the same */
1378 /* FIXME: This needs to be done more globally */
1380 for (i = 0; i < count; ++i) {
1381 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1382 if (!custom_attr_visible (image, cattr))
1385 count -= not_visible;
1387 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1389 ainfo->image = image;
1390 ainfo->num_attrs = count;
1391 ainfo->cached = alloc_img != NULL;
1393 for (i = 0; i < count; ++i) {
1394 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1395 if (custom_attr_visible (image, cattr)) {
1396 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1397 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1398 ainfo->attrs [index].ctor = cattr->ctor->method;
1399 ainfo->attrs [index].data = saved;
1400 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1408 #ifndef DISABLE_REFLECTION_EMIT
1410 * LOCKING: Acquires the loader lock.
1413 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1415 MONO_REQ_GC_UNSAFE_MODE;
1417 MonoCustomAttrInfo *ainfo, *tmp;
1419 if (!cattrs || !mono_array_length (cattrs))
1422 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1424 mono_loader_lock ();
1425 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1427 mono_custom_attrs_free (tmp);
1428 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1429 mono_loader_unlock ();
1435 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1437 MONO_REQ_GC_NEUTRAL_MODE;
1444 * idx is the table index of the object
1445 * type is one of MONO_CUSTOM_ATTR_*
1448 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1450 MONO_REQ_GC_UNSAFE_MODE;
1452 MonoDynamicTable *table;
1453 MonoReflectionCustomAttr *cattr;
1455 guint32 count, i, token;
1457 char *p = blob_size;
1459 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1462 count = mono_array_length (cattrs);
1463 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1464 table->rows += count;
1465 alloc_table (table, table->rows);
1466 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1467 idx <<= MONO_CUSTOM_ATTR_BITS;
1469 for (i = 0; i < count; ++i) {
1470 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1472 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1473 type = mono_metadata_token_index (token);
1474 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1475 switch (mono_metadata_token_table (token)) {
1476 case MONO_TABLE_METHOD:
1477 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1479 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1480 * method, not the one returned by mono_image_create_token ().
1482 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1484 case MONO_TABLE_MEMBERREF:
1485 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1488 g_warning ("got wrong token in custom attr");
1491 values [MONO_CUSTOM_ATTR_TYPE] = type;
1493 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1494 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1495 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1496 values += MONO_CUSTOM_ATTR_SIZE;
1502 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1504 MONO_REQ_GC_UNSAFE_MODE;
1506 MonoDynamicTable *table;
1508 guint32 count, i, idx;
1509 MonoReflectionPermissionSet *perm;
1514 count = mono_array_length (permissions);
1515 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1516 table->rows += count;
1517 alloc_table (table, table->rows);
1519 for (i = 0; i < mono_array_length (permissions); ++i) {
1520 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1522 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1524 idx = mono_metadata_token_index (parent_token);
1525 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1526 switch (mono_metadata_token_table (parent_token)) {
1527 case MONO_TABLE_TYPEDEF:
1528 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1530 case MONO_TABLE_METHOD:
1531 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1533 case MONO_TABLE_ASSEMBLY:
1534 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1537 g_assert_not_reached ();
1540 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1541 values [MONO_DECL_SECURITY_PARENT] = idx;
1542 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1549 * Fill in the MethodDef and ParamDef tables for a method.
1550 * This is used for both normal methods and constructors.
1553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1555 MONO_REQ_GC_UNSAFE_MODE;
1557 MonoDynamicTable *table;
1561 /* room in this table is already allocated */
1562 table = &assembly->tables [MONO_TABLE_METHOD];
1563 *mb->table_idx = table->next_idx ++;
1564 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1565 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1566 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1567 values [MONO_METHOD_FLAGS] = mb->attrs;
1568 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1569 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1570 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1572 table = &assembly->tables [MONO_TABLE_PARAM];
1573 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1575 mono_image_add_decl_security (assembly,
1576 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1579 MonoDynamicTable *mtable;
1582 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1583 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1586 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1587 if (mono_array_get (mb->pinfo, gpointer, i))
1590 table->rows += count;
1591 alloc_table (table, table->rows);
1592 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1593 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1594 MonoReflectionParamBuilder *pb;
1595 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1596 values [MONO_PARAM_FLAGS] = pb->attrs;
1597 values [MONO_PARAM_SEQUENCE] = i;
1598 if (pb->name != NULL) {
1599 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1601 values [MONO_PARAM_NAME] = 0;
1603 values += MONO_PARAM_SIZE;
1604 if (pb->marshal_info) {
1606 alloc_table (mtable, mtable->rows);
1607 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1608 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1609 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1611 pb->table_idx = table->next_idx++;
1612 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1613 guint32 field_type = 0;
1614 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1616 alloc_table (mtable, mtable->rows);
1617 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1618 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1619 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1620 mvalues [MONO_CONSTANT_TYPE] = field_type;
1621 mvalues [MONO_CONSTANT_PADDING] = 0;
1628 #ifndef DISABLE_REFLECTION_EMIT
1630 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1633 MONO_REQ_GC_UNSAFE_MODE;
1635 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1637 rmb->ilgen = mb->ilgen;
1638 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1639 mono_error_raise_exception (&error); /* FIXME don't raise here */
1640 rmb->parameters = mb->parameters;
1641 rmb->generic_params = mb->generic_params;
1642 rmb->generic_container = mb->generic_container;
1643 rmb->opt_types = NULL;
1644 rmb->pinfo = mb->pinfo;
1645 rmb->attrs = mb->attrs;
1646 rmb->iattrs = mb->iattrs;
1647 rmb->call_conv = mb->call_conv;
1648 rmb->code = mb->code;
1649 rmb->type = mb->type;
1650 rmb->name = mb->name;
1651 rmb->table_idx = &mb->table_idx;
1652 rmb->init_locals = mb->init_locals;
1653 rmb->skip_visibility = FALSE;
1654 rmb->return_modreq = mb->return_modreq;
1655 rmb->return_modopt = mb->return_modopt;
1656 rmb->param_modreq = mb->param_modreq;
1657 rmb->param_modopt = mb->param_modopt;
1658 rmb->permissions = mb->permissions;
1659 rmb->mhandle = mb->mhandle;
1664 rmb->charset = mb->charset;
1665 rmb->extra_flags = mb->extra_flags;
1666 rmb->native_cc = mb->native_cc;
1667 rmb->dllentry = mb->dllentry;
1673 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1675 MONO_REQ_GC_UNSAFE_MODE;
1678 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1680 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682 rmb->ilgen = mb->ilgen;
1683 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1684 mono_error_raise_exception (&error); /* FIXME don't raise here */
1685 rmb->parameters = mb->parameters;
1686 rmb->generic_params = NULL;
1687 rmb->generic_container = NULL;
1688 rmb->opt_types = NULL;
1689 rmb->pinfo = mb->pinfo;
1690 rmb->attrs = mb->attrs;
1691 rmb->iattrs = mb->iattrs;
1692 rmb->call_conv = mb->call_conv;
1694 rmb->type = mb->type;
1695 rmb->name = mono_string_new (mono_domain_get (), name);
1696 rmb->table_idx = &mb->table_idx;
1697 rmb->init_locals = mb->init_locals;
1698 rmb->skip_visibility = FALSE;
1699 rmb->return_modreq = NULL;
1700 rmb->return_modopt = NULL;
1701 rmb->param_modreq = mb->param_modreq;
1702 rmb->param_modopt = mb->param_modopt;
1703 rmb->permissions = mb->permissions;
1704 rmb->mhandle = mb->mhandle;
1710 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1712 MONO_REQ_GC_UNSAFE_MODE;
1714 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1716 rmb->ilgen = mb->ilgen;
1717 rmb->rtype = mb->rtype;
1718 rmb->parameters = mb->parameters;
1719 rmb->generic_params = NULL;
1720 rmb->generic_container = NULL;
1721 rmb->opt_types = NULL;
1723 rmb->attrs = mb->attrs;
1725 rmb->call_conv = mb->call_conv;
1727 rmb->type = (MonoObject *) mb->owner;
1728 rmb->name = mb->name;
1729 rmb->table_idx = NULL;
1730 rmb->init_locals = mb->init_locals;
1731 rmb->skip_visibility = mb->skip_visibility;
1732 rmb->return_modreq = NULL;
1733 rmb->return_modopt = NULL;
1734 rmb->param_modreq = NULL;
1735 rmb->param_modopt = NULL;
1736 rmb->permissions = NULL;
1737 rmb->mhandle = mb->mhandle;
1744 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1746 MONO_REQ_GC_UNSAFE_MODE;
1748 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1749 MonoDynamicTable *table;
1752 MonoReflectionMethod *m;
1755 if (!mb->override_methods)
1758 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1759 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1761 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1763 alloc_table (table, table->rows);
1764 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1765 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1766 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1768 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1769 switch (mono_metadata_token_table (tok)) {
1770 case MONO_TABLE_MEMBERREF:
1771 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1773 case MONO_TABLE_METHOD:
1774 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1777 g_assert_not_reached ();
1779 values [MONO_METHODIMPL_DECLARATION] = tok;
1783 #ifndef DISABLE_REFLECTION_EMIT
1785 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1787 MONO_REQ_GC_UNSAFE_MODE;
1789 MonoDynamicTable *table;
1791 ReflectionMethodBuilder rmb;
1794 reflection_methodbuilder_from_method_builder (&rmb, mb);
1796 mono_image_basic_method (&rmb, assembly);
1797 mb->table_idx = *rmb.table_idx;
1799 if (mb->dll) { /* It's a P/Invoke method */
1801 /* map CharSet values to on-disk values */
1802 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1803 int extra_flags = mb->extra_flags;
1804 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1806 alloc_table (table, table->rows);
1807 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1809 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1810 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1812 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1814 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1815 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1816 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1817 table = &assembly->tables [MONO_TABLE_MODULEREF];
1819 alloc_table (table, table->rows);
1820 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1821 values [MONO_IMPLMAP_SCOPE] = table->rows;
1825 if (mb->generic_params) {
1826 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1827 table->rows += mono_array_length (mb->generic_params);
1828 alloc_table (table, table->rows);
1829 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1830 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1832 mono_image_get_generic_param_info (
1833 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1840 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1842 MONO_REQ_GC_UNSAFE_MODE;
1844 ReflectionMethodBuilder rmb;
1846 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1848 mono_image_basic_method (&rmb, assembly);
1849 mb->table_idx = *rmb.table_idx;
1854 type_get_fully_qualified_name (MonoType *type)
1856 MONO_REQ_GC_NEUTRAL_MODE;
1858 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1862 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1864 MONO_REQ_GC_UNSAFE_MODE;
1869 klass = mono_class_from_mono_type (type);
1871 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872 ta = klass->image->assembly;
1873 if (assembly_is_dynamic (ta) || (ta == ass)) {
1874 if (klass->generic_class || klass->generic_container)
1875 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1876 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1878 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1881 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1884 #ifndef DISABLE_REFLECTION_EMIT
1885 /*field_image is the image to which the eventual custom mods have been encoded against*/
1887 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1889 MONO_REQ_GC_NEUTRAL_MODE;
1892 guint32 idx, i, token;
1894 if (!assembly->save)
1897 sigbuffer_init (&buf, 32);
1899 sigbuffer_add_value (&buf, 0x06);
1900 /* encode custom attributes before the type */
1901 if (type->num_mods) {
1902 for (i = 0; i < type->num_mods; ++i) {
1905 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1906 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1908 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1910 token = type->modifiers [i].token;
1913 if (type->modifiers [i].required)
1914 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1916 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1918 sigbuffer_add_value (&buf, token);
1921 encode_type (assembly, type, &buf);
1922 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1923 sigbuffer_free (&buf);
1929 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1931 MONO_REQ_GC_UNSAFE_MODE;
1935 guint32 typespec = 0;
1939 init_type_builder_generics (fb->type);
1941 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1942 klass = mono_class_from_mono_type (type);
1944 sigbuffer_init (&buf, 32);
1946 sigbuffer_add_value (&buf, 0x06);
1947 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1948 /* encode custom attributes before the type */
1950 if (klass->generic_container)
1951 typespec = create_typespec (assembly, type);
1954 MonoGenericClass *gclass;
1955 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1956 encode_generic_class (assembly, gclass, &buf);
1958 encode_type (assembly, type, &buf);
1960 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961 sigbuffer_free (&buf);
1966 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1968 MONO_REQ_GC_UNSAFE_MODE;
1970 char blob_size [64];
1971 char *b = blob_size;
1974 guint32 idx = 0, len = 0, dummy = 0;
1976 buf = (char *)g_malloc (64);
1978 *ret_type = MONO_TYPE_CLASS;
1980 box_val = (char*)&dummy;
1982 box_val = ((char*)val) + sizeof (MonoObject);
1983 *ret_type = val->vtable->klass->byval_arg.type;
1986 switch (*ret_type) {
1987 case MONO_TYPE_BOOLEAN:
1992 case MONO_TYPE_CHAR:
2009 case MONO_TYPE_VALUETYPE: {
2010 MonoClass *klass = val->vtable->klass;
2012 if (klass->enumtype) {
2013 *ret_type = mono_class_enum_basetype (klass)->type;
2015 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2018 g_error ("we can't encode valuetypes, we should have never reached this line");
2021 case MONO_TYPE_CLASS:
2023 case MONO_TYPE_STRING: {
2024 MonoString *str = (MonoString*)val;
2025 /* there is no signature */
2026 len = str->length * 2;
2027 mono_metadata_encode_value (len, b, &b);
2028 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2030 char *swapped = g_malloc (2 * mono_string_length (str));
2031 const char *p = (const char*)mono_string_chars (str);
2033 swap_with_size (swapped, p, 2, mono_string_length (str));
2034 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2038 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2044 case MONO_TYPE_GENERICINST:
2045 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2048 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2051 /* there is no signature */
2052 mono_metadata_encode_value (len, b, &b);
2053 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2054 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2055 swap_with_size (blob_size, box_val, len, 1);
2056 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2058 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2066 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2068 MONO_REQ_GC_UNSAFE_MODE;
2074 sigbuffer_init (&buf, 32);
2076 sigbuffer_add_value (&buf, minfo->type);
2078 switch (minfo->type) {
2079 case MONO_NATIVE_BYVALTSTR:
2080 case MONO_NATIVE_BYVALARRAY:
2081 sigbuffer_add_value (&buf, minfo->count);
2083 case MONO_NATIVE_LPARRAY:
2084 if (minfo->eltype || minfo->has_size) {
2085 sigbuffer_add_value (&buf, minfo->eltype);
2086 if (minfo->has_size) {
2087 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2088 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2090 /* LAMESPEC: ElemMult is undocumented */
2091 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2095 case MONO_NATIVE_SAFEARRAY:
2097 sigbuffer_add_value (&buf, minfo->eltype);
2099 case MONO_NATIVE_CUSTOM:
2101 str = mono_string_to_utf8 (minfo->guid);
2103 sigbuffer_add_value (&buf, len);
2104 sigbuffer_add_mem (&buf, str, len);
2107 sigbuffer_add_value (&buf, 0);
2109 /* native type name */
2110 sigbuffer_add_value (&buf, 0);
2111 /* custom marshaler type name */
2112 if (minfo->marshaltype || minfo->marshaltyperef) {
2113 if (minfo->marshaltyperef)
2114 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2116 str = mono_string_to_utf8 (minfo->marshaltype);
2118 sigbuffer_add_value (&buf, len);
2119 sigbuffer_add_mem (&buf, str, len);
2122 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2123 sigbuffer_add_value (&buf, 0);
2125 if (minfo->mcookie) {
2126 str = mono_string_to_utf8 (minfo->mcookie);
2128 sigbuffer_add_value (&buf, len);
2129 sigbuffer_add_mem (&buf, str, len);
2132 sigbuffer_add_value (&buf, 0);
2138 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2139 sigbuffer_free (&buf);
2144 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2146 MONO_REQ_GC_UNSAFE_MODE;
2148 MonoDynamicTable *table;
2151 /* maybe this fixup should be done in the C# code */
2152 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2153 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2154 table = &assembly->tables [MONO_TABLE_FIELD];
2155 fb->table_idx = table->next_idx ++;
2156 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2157 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2158 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2159 values [MONO_FIELD_FLAGS] = fb->attrs;
2160 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2162 if (fb->offset != -1) {
2163 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2165 alloc_table (table, table->rows);
2166 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2167 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2168 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2170 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2171 MonoTypeEnum field_type = (MonoTypeEnum)0;
2172 table = &assembly->tables [MONO_TABLE_CONSTANT];
2174 alloc_table (table, table->rows);
2175 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2176 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2177 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2178 values [MONO_CONSTANT_TYPE] = field_type;
2179 values [MONO_CONSTANT_PADDING] = 0;
2181 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2183 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2185 alloc_table (table, table->rows);
2186 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2187 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2189 * We store it in the code section because it's simpler for now.
2192 if (mono_array_length (fb->rva_data) >= 10)
2193 stream_data_align (&assembly->code);
2194 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2196 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2197 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2199 if (fb->marshal_info) {
2200 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2202 alloc_table (table, table->rows);
2203 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2204 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2205 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2210 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2212 MONO_REQ_GC_UNSAFE_MODE;
2215 guint32 nparams = 0;
2216 MonoReflectionMethodBuilder *mb = fb->get_method;
2217 MonoReflectionMethodBuilder *smb = fb->set_method;
2220 if (mb && mb->parameters)
2221 nparams = mono_array_length (mb->parameters);
2222 if (!mb && smb && smb->parameters)
2223 nparams = mono_array_length (smb->parameters) - 1;
2224 sigbuffer_init (&buf, 32);
2225 if (fb->call_conv & 0x20)
2226 sigbuffer_add_byte (&buf, 0x28);
2228 sigbuffer_add_byte (&buf, 0x08);
2229 sigbuffer_add_value (&buf, nparams);
2231 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2232 for (i = 0; i < nparams; ++i) {
2233 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2234 encode_reflection_type (assembly, pt, &buf);
2236 } else if (smb && smb->parameters) {
2237 /* the property type is the last param */
2238 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2239 for (i = 0; i < nparams; ++i) {
2240 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2241 encode_reflection_type (assembly, pt, &buf);
2244 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2247 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2248 sigbuffer_free (&buf);
2253 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2255 MONO_REQ_GC_UNSAFE_MODE;
2257 MonoDynamicTable *table;
2259 guint num_methods = 0;
2263 * we need to set things in the following tables:
2264 * PROPERTYMAP (info already filled in _get_type_info ())
2265 * PROPERTY (rows already preallocated in _get_type_info ())
2266 * METHOD (method info already done with the generic method code)
2270 table = &assembly->tables [MONO_TABLE_PROPERTY];
2271 pb->table_idx = table->next_idx ++;
2272 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2273 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2274 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2275 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2277 /* FIXME: we still don't handle 'other' methods */
2278 if (pb->get_method) num_methods ++;
2279 if (pb->set_method) num_methods ++;
2281 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2282 table->rows += num_methods;
2283 alloc_table (table, table->rows);
2285 if (pb->get_method) {
2286 semaidx = table->next_idx ++;
2287 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2289 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2290 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2292 if (pb->set_method) {
2293 semaidx = table->next_idx ++;
2294 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2295 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2296 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2297 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2299 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2300 MonoTypeEnum field_type = (MonoTypeEnum)0;
2301 table = &assembly->tables [MONO_TABLE_CONSTANT];
2303 alloc_table (table, table->rows);
2304 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2305 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2306 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2307 values [MONO_CONSTANT_TYPE] = field_type;
2308 values [MONO_CONSTANT_PADDING] = 0;
2313 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2315 MONO_REQ_GC_UNSAFE_MODE;
2317 MonoDynamicTable *table;
2319 guint num_methods = 0;
2323 * we need to set things in the following tables:
2324 * EVENTMAP (info already filled in _get_type_info ())
2325 * EVENT (rows already preallocated in _get_type_info ())
2326 * METHOD (method info already done with the generic method code)
2329 table = &assembly->tables [MONO_TABLE_EVENT];
2330 eb->table_idx = table->next_idx ++;
2331 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2332 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2333 values [MONO_EVENT_FLAGS] = eb->attrs;
2334 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2337 * FIXME: we still don't handle 'other' methods
2339 if (eb->add_method) num_methods ++;
2340 if (eb->remove_method) num_methods ++;
2341 if (eb->raise_method) num_methods ++;
2343 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2344 table->rows += num_methods;
2345 alloc_table (table, table->rows);
2347 if (eb->add_method) {
2348 semaidx = table->next_idx ++;
2349 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2351 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2352 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2354 if (eb->remove_method) {
2355 semaidx = table->next_idx ++;
2356 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2358 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2359 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2361 if (eb->raise_method) {
2362 semaidx = table->next_idx ++;
2363 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2364 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2365 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2366 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2371 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2373 MONO_REQ_GC_UNSAFE_MODE;
2375 MonoDynamicTable *table;
2376 guint32 num_constraints, i;
2380 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2381 num_constraints = gparam->iface_constraints ?
2382 mono_array_length (gparam->iface_constraints) : 0;
2383 table->rows += num_constraints;
2384 if (gparam->base_type)
2386 alloc_table (table, table->rows);
2388 if (gparam->base_type) {
2389 table_idx = table->next_idx ++;
2390 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2392 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2393 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2394 assembly, mono_reflection_type_get_handle (gparam->base_type));
2397 for (i = 0; i < num_constraints; i++) {
2398 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2399 gparam->iface_constraints, gpointer, i);
2401 table_idx = table->next_idx ++;
2402 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2404 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2405 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2406 assembly, mono_reflection_type_get_handle (constraint));
2411 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2413 MONO_REQ_GC_UNSAFE_MODE;
2415 GenericParamTableEntry *entry;
2418 * The GenericParam table must be sorted according to the `owner' field.
2419 * We need to do this sorting prior to writing the GenericParamConstraint
2420 * table, since we have to use the final GenericParam table indices there
2421 * and they must also be sorted.
2424 entry = g_new0 (GenericParamTableEntry, 1);
2425 entry->owner = owner;
2426 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2427 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2428 entry->gparam = gparam;
2430 g_ptr_array_add (assembly->gen_params, entry);
2434 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2436 MONO_REQ_GC_UNSAFE_MODE;
2438 MonoDynamicTable *table;
2439 MonoGenericParam *param;
2443 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2444 table_idx = table->next_idx ++;
2445 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2447 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2449 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2450 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2451 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2452 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2454 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2456 encode_constraints (entry->gparam, table_idx, assembly);
2460 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2462 MONO_REQ_GC_UNSAFE_MODE;
2464 MonoDynamicTable *table;
2467 guint32 cols [MONO_ASSEMBLY_SIZE];
2471 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2474 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2475 table = &assembly->tables [MONO_TABLE_MODULEREF];
2476 token = table->next_idx ++;
2478 alloc_table (table, table->rows);
2479 values = table->values + token * MONO_MODULEREF_SIZE;
2480 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2482 token <<= MONO_RESOLUTION_SCOPE_BITS;
2483 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2484 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2489 if (assembly_is_dynamic (image->assembly))
2491 memset (cols, 0, sizeof (cols));
2493 /* image->assembly->image is the manifest module */
2494 image = image->assembly->image;
2495 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2498 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2499 token = table->next_idx ++;
2501 alloc_table (table, table->rows);
2502 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2503 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2504 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2505 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2506 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2507 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2508 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2509 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2510 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2512 if (strcmp ("", image->assembly->aname.culture)) {
2513 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2514 image->assembly->aname.culture);
2517 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2518 guchar pubtoken [9];
2520 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2521 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2523 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2525 token <<= MONO_RESOLUTION_SCOPE_BITS;
2526 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2527 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2532 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2534 MONO_REQ_GC_NEUTRAL_MODE;
2536 MonoDynamicTable *table;
2541 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2544 sigbuffer_init (&buf, 32);
2545 switch (type->type) {
2546 case MONO_TYPE_FNPTR:
2548 case MONO_TYPE_SZARRAY:
2549 case MONO_TYPE_ARRAY:
2551 case MONO_TYPE_MVAR:
2552 case MONO_TYPE_GENERICINST:
2553 encode_type (assembly, type, &buf);
2555 case MONO_TYPE_CLASS:
2556 case MONO_TYPE_VALUETYPE: {
2557 MonoClass *k = mono_class_from_mono_type (type);
2558 if (!k || !k->generic_container) {
2559 sigbuffer_free (&buf);
2562 encode_type (assembly, type, &buf);
2566 sigbuffer_free (&buf);
2570 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571 if (assembly->save) {
2572 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573 alloc_table (table, table->rows + 1);
2574 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575 values [MONO_TYPESPEC_SIGNATURE] = token;
2577 sigbuffer_free (&buf);
2579 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2586 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2588 MONO_REQ_GC_UNSAFE_MODE;
2590 MonoDynamicTable *table;
2592 guint32 token, scope, enclosing;
2595 /* if the type requires a typespec, we must try that first*/
2596 if (try_typespec && (token = create_typespec (assembly, type)))
2598 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2601 klass = mono_class_from_mono_type (type);
2603 klass = mono_class_from_mono_type (type);
2606 * If it's in the same module and not a generic type parameter:
2608 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2609 (type->type != MONO_TYPE_MVAR)) {
2610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2611 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2612 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2616 if (klass->nested_in) {
2617 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2618 /* get the typeref idx of the enclosing type */
2619 enclosing >>= MONO_TYPEDEFORREF_BITS;
2620 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2622 scope = resolution_scope_from_image (assembly, klass->image);
2624 table = &assembly->tables [MONO_TABLE_TYPEREF];
2625 if (assembly->save) {
2626 alloc_table (table, table->rows + 1);
2627 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2628 values [MONO_TYPEREF_SCOPE] = scope;
2629 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2630 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2632 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2633 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2635 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2640 * Despite the name, we handle also TypeSpec (with the above helper).
2643 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2645 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2648 #ifndef DISABLE_REFLECTION_EMIT
2650 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2652 MONO_REQ_GC_NEUTRAL_MODE;
2654 MonoDynamicTable *table;
2656 guint32 token, pclass;
2658 switch (parent & MONO_TYPEDEFORREF_MASK) {
2659 case MONO_TYPEDEFORREF_TYPEREF:
2660 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2662 case MONO_TYPEDEFORREF_TYPESPEC:
2663 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2665 case MONO_TYPEDEFORREF_TYPEDEF:
2666 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2669 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2672 /* extract the index */
2673 parent >>= MONO_TYPEDEFORREF_BITS;
2675 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2677 if (assembly->save) {
2678 alloc_table (table, table->rows + 1);
2679 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2680 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2681 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2682 values [MONO_MEMBERREF_SIGNATURE] = sig;
2685 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2692 * Insert a memberef row into the metadata: the token that point to the memberref
2693 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2694 * mono_image_get_fieldref_token()).
2695 * The sig param is an index to an already built signature.
2698 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2700 MONO_REQ_GC_NEUTRAL_MODE;
2702 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2703 return mono_image_add_memberef_row (assembly, parent, name, sig);
2708 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2710 MONO_REQ_GC_NEUTRAL_MODE;
2713 MonoMethodSignature *sig;
2715 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2717 if (create_typespec) {
2718 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2723 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2724 if (token && !create_typespec)
2727 g_assert (!method->is_inflated);
2730 * A methodref signature can't contain an unmanaged calling convention.
2732 sig = mono_metadata_signature_dup (mono_method_signature (method));
2733 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2734 sig->call_convention = MONO_CALL_DEFAULT;
2735 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2736 method->name, method_encode_signature (assembly, sig));
2738 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2741 if (create_typespec) {
2742 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2743 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2744 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2746 if (assembly->save) {
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2751 values [MONO_METHODSPEC_METHOD] = token;
2752 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2755 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2757 /*methodspec and memberef tokens are diferent, */
2758 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2765 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2767 guint32 token, parent, sig;
2768 ReflectionMethodBuilder rmb;
2770 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2772 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2776 name = mono_string_to_utf8 (method->name);
2777 reflection_methodbuilder_from_method_builder (&rmb, method);
2780 * A methodref signature can't contain an unmanaged calling convention.
2781 * Since some flags are encoded as part of call_conv, we need to check against it.
2783 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2784 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2786 sig = method_builder_encode_signature (assembly, &rmb);
2788 if (tb->generic_params)
2789 parent = create_generic_typespec (assembly, tb);
2791 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2793 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2796 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2801 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2802 const gchar *name, guint32 sig)
2804 MonoDynamicTable *table;
2808 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2810 if (assembly->save) {
2811 alloc_table (table, table->rows + 1);
2812 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2813 values [MONO_MEMBERREF_CLASS] = original;
2814 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2815 values [MONO_MEMBERREF_SIGNATURE] = sig;
2818 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2825 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2829 guint32 nparams = mono_array_length (mb->generic_params);
2832 if (!assembly->save)
2835 sigbuffer_init (&buf, 32);
2837 sigbuffer_add_value (&buf, 0xa);
2838 sigbuffer_add_value (&buf, nparams);
2840 for (i = 0; i < nparams; i++) {
2841 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2842 sigbuffer_add_value (&buf, i);
2845 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2846 sigbuffer_free (&buf);
2851 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2853 MonoDynamicTable *table;
2855 guint32 token, mtoken = 0;
2857 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2861 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2863 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2864 switch (mono_metadata_token_table (mtoken)) {
2865 case MONO_TABLE_MEMBERREF:
2866 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2868 case MONO_TABLE_METHOD:
2869 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2872 g_assert_not_reached ();
2875 if (assembly->save) {
2876 alloc_table (table, table->rows + 1);
2877 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2878 values [MONO_METHODSPEC_METHOD] = mtoken;
2879 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2882 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2885 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2890 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2894 if (mb->generic_params && create_methodspec)
2895 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2897 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2901 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2902 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2907 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2909 guint32 token, parent, sig;
2910 ReflectionMethodBuilder rmb;
2912 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2914 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2918 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2920 if (tb->generic_params)
2921 parent = create_generic_typespec (assembly, tb);
2923 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2925 name = mono_string_to_utf8 (rmb.name);
2926 sig = method_builder_encode_signature (assembly, &rmb);
2928 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2931 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2937 is_field_on_inst (MonoClassField *field)
2939 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2943 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2946 get_field_on_inst_generic_type (MonoClassField *field)
2948 MonoClass *klass, *gtd;
2949 MonoDynamicGenericClass *dgclass;
2952 g_assert (is_field_on_inst (field));
2954 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2956 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2957 field_index = field - dgclass->fields;
2958 return dgclass->field_generic_types [field_index];
2961 klass = field->parent;
2962 gtd = klass->generic_class->container_class;
2964 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2965 field_index = field - klass->fields;
2966 return gtd->fields [field_index].type;
2969 g_assert_not_reached ();
2973 #ifndef DISABLE_REFLECTION_EMIT
2975 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2981 g_assert (field->parent);
2983 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2987 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2988 int index = field - field->parent->fields;
2989 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2991 if (is_field_on_inst (field))
2992 type = get_field_on_inst_generic_type (field);
2994 type = mono_field_get_type (field);
2996 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2997 mono_field_get_name (field),
2998 fieldref_encode_signature (assembly, field->parent->image, type));
2999 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3004 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3008 MonoGenericClass *gclass;
3012 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3015 if (is_sre_field_builder (mono_object_class (f->fb))) {
3016 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3017 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3018 klass = mono_class_from_mono_type (type);
3019 gclass = type->data.generic_class;
3020 g_assert (gclass->is_dynamic);
3022 name = mono_string_to_utf8 (fb->name);
3023 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3024 field_encode_signature (assembly, fb));
3026 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3028 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3030 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3031 klass = mono_class_from_mono_type (type);
3033 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3034 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3036 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3037 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3040 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3045 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3049 MonoGenericClass *gclass;
3052 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3054 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3058 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3059 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3060 ReflectionMethodBuilder rmb;
3063 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3064 klass = mono_class_from_mono_type (type);
3066 gclass = type->data.generic_class;
3067 g_assert (gclass->is_dynamic);
3069 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3071 name = mono_string_to_utf8 (rmb.name);
3073 sig = method_builder_encode_signature (assembly, &rmb);
3075 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3077 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3078 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3080 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3081 klass = mono_class_from_mono_type (type);
3083 sig = method_encode_signature (assembly, mono_method_signature (mm));
3084 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3086 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3087 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3091 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3096 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3100 MonoGenericContext tmp_context;
3101 MonoType **type_argv;
3102 MonoGenericInst *ginst;
3103 MonoMethod *method, *inflated;
3106 init_type_builder_generics ((MonoObject*)m->inst);
3108 method = inflate_method (m->inst, (MonoObject*)m->mb);
3110 klass = method->klass;
3112 if (m->method_args == NULL)
3115 if (method->is_inflated)
3116 method = ((MonoMethodInflated *) method)->declaring;
3118 count = mono_array_length (m->method_args);
3120 type_argv = g_new0 (MonoType *, count);
3121 for (i = 0; i < count; i++) {
3122 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3123 type_argv [i] = mono_reflection_type_get_handle (garg);
3125 ginst = mono_metadata_get_generic_inst (count, type_argv);
3128 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3129 tmp_context.method_inst = ginst;
3131 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3132 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3137 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3139 guint32 sig, token = 0;
3143 if (m->method_args) {
3144 MonoMethod *inflated;
3146 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3147 if (create_methodspec)
3148 token = mono_image_get_methodspec_token (assembly, inflated);
3150 token = mono_image_get_inflated_method_token (assembly, inflated);
3154 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3158 if (is_sre_method_builder (mono_object_class (m->mb))) {
3159 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3160 MonoGenericClass *gclass;
3161 ReflectionMethodBuilder rmb;
3164 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3165 klass = mono_class_from_mono_type (type);
3166 gclass = type->data.generic_class;
3167 g_assert (gclass->is_dynamic);
3169 reflection_methodbuilder_from_method_builder (&rmb, mb);
3171 name = mono_string_to_utf8 (rmb.name);
3173 sig = method_builder_encode_signature (assembly, &rmb);
3175 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3177 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3178 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3180 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3181 klass = mono_class_from_mono_type (type);
3183 sig = method_encode_signature (assembly, mono_method_signature (mm));
3184 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3186 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3187 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3190 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3195 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3199 guint32 nparams = context->method_inst->type_argc;
3202 if (!assembly->save)
3205 sigbuffer_init (&buf, 32);
3207 * FIXME: vararg, explicit_this, differenc call_conv values...
3209 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3210 sigbuffer_add_value (&buf, nparams);
3212 for (i = 0; i < nparams; i++)
3213 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3215 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3216 sigbuffer_free (&buf);
3221 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3223 MonoDynamicTable *table;
3225 guint32 token, mtoken = 0, sig;
3226 MonoMethodInflated *imethod;
3227 MonoMethod *declaring;
3229 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3231 g_assert (method->is_inflated);
3232 imethod = (MonoMethodInflated *) method;
3233 declaring = imethod->declaring;
3235 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3236 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3238 if (!mono_method_signature (declaring)->generic_param_count)
3241 switch (mono_metadata_token_table (mtoken)) {
3242 case MONO_TABLE_MEMBERREF:
3243 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3245 case MONO_TABLE_METHOD:
3246 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3249 g_assert_not_reached ();
3252 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3254 if (assembly->save) {
3255 alloc_table (table, table->rows + 1);
3256 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3257 values [MONO_METHODSPEC_METHOD] = mtoken;
3258 values [MONO_METHODSPEC_SIGNATURE] = sig;
3261 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3268 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3270 MonoMethodInflated *imethod;
3273 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3277 g_assert (method->is_inflated);
3278 imethod = (MonoMethodInflated *) method;
3280 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3281 token = method_encode_methodspec (assembly, method);
3283 guint32 sig = method_encode_signature (
3284 assembly, mono_method_signature (imethod->declaring));
3285 token = mono_image_get_memberref_token (
3286 assembly, &method->klass->byval_arg, method->name, sig);
3289 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3294 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3296 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3299 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3300 token = mono_image_get_memberref_token (
3301 assembly, &m->klass->byval_arg, m->name, sig);
3307 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3309 MonoDynamicTable *table;
3318 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3319 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3320 * Because of this, we must not insert it into the `typeref' hash table.
3322 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3323 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3327 sigbuffer_init (&buf, 32);
3329 g_assert (tb->generic_params);
3330 klass = mono_class_from_mono_type (type);
3332 if (tb->generic_container)
3333 mono_reflection_create_generic_class (tb);
3335 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3336 g_assert (klass->generic_container);
3337 sigbuffer_add_value (&buf, klass->byval_arg.type);
3338 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3340 count = mono_array_length (tb->generic_params);
3341 sigbuffer_add_value (&buf, count);
3342 for (i = 0; i < count; i++) {
3343 MonoReflectionGenericParam *gparam;
3345 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3347 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3350 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3352 if (assembly->save) {
3353 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3354 alloc_table (table, table->rows + 1);
3355 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3356 values [MONO_TYPESPEC_SIGNATURE] = token;
3358 sigbuffer_free (&buf);
3360 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3361 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3367 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3370 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3372 int i, count, len, pos;
3377 count += mono_array_length (modreq);
3379 count += mono_array_length (modopt);
3382 return mono_metadata_type_dup (NULL, type);
3384 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3385 t = (MonoType *)g_malloc (len);
3386 memcpy (t, type, MONO_SIZEOF_TYPE);
3388 t->num_mods = count;
3391 for (i = 0; i < mono_array_length (modreq); ++i) {
3392 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3393 t->modifiers [pos].required = 1;
3394 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3399 for (i = 0; i < mono_array_length (modopt); ++i) {
3400 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3401 t->modifiers [pos].required = 0;
3402 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3411 init_type_builder_generics (MonoObject *type)
3413 MonoReflectionTypeBuilder *tb;
3415 if (!is_sre_type_builder(mono_object_class (type)))
3417 tb = (MonoReflectionTypeBuilder *)type;
3419 if (tb && tb->generic_container)
3420 mono_reflection_create_generic_class (tb);
3424 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3426 MonoDynamicTable *table;
3427 MonoType *custom = NULL, *type;
3429 guint32 token, pclass, parent, sig;
3432 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3436 /* FIXME: is this call necessary? */
3437 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3438 name = mono_string_to_utf8 (fb->name);
3440 /*FIXME this is one more layer of ugliness due how types are created.*/
3441 init_type_builder_generics (fb->type);
3443 /* fb->type does not include the custom modifiers */
3444 /* FIXME: We should do this in one place when a fieldbuilder is created */
3445 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3446 if (fb->modreq || fb->modopt)
3447 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3449 sig = fieldref_encode_signature (assembly, NULL, type);
3452 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3453 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3455 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3456 parent >>= MONO_TYPEDEFORREF_BITS;
3458 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3460 if (assembly->save) {
3461 alloc_table (table, table->rows + 1);
3462 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3463 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3464 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3465 values [MONO_MEMBERREF_SIGNATURE] = sig;
3468 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3470 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3476 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3482 if (!assembly->save)
3485 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3486 g_assert (helper->type == 2);
3488 if (helper->arguments)
3489 nargs = mono_array_length (helper->arguments);
3493 sigbuffer_init (&buf, 32);
3495 /* Encode calling convention */
3496 /* Change Any to Standard */
3497 if ((helper->call_conv & 0x03) == 0x03)
3498 helper->call_conv = 0x01;
3499 /* explicit_this implies has_this */
3500 if (helper->call_conv & 0x40)
3501 helper->call_conv &= 0x20;
3503 if (helper->call_conv == 0) { /* Unmanaged */
3504 idx = helper->unmanaged_call_conv - 1;
3507 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3508 if (helper->call_conv & 0x02) /* varargs */
3512 sigbuffer_add_byte (&buf, idx);
3513 sigbuffer_add_value (&buf, nargs);
3514 encode_reflection_type (assembly, helper->return_type, &buf);
3515 for (i = 0; i < nargs; ++i) {
3516 MonoArray *modreqs = NULL;
3517 MonoArray *modopts = NULL;
3518 MonoReflectionType *pt;
3520 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3521 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3522 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3523 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3525 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3526 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3527 encode_reflection_type (assembly, pt, &buf);
3529 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3530 sigbuffer_free (&buf);
3536 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3539 MonoDynamicTable *table;
3542 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3543 idx = table->next_idx ++;
3545 alloc_table (table, table->rows);
3546 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3548 values [MONO_STAND_ALONE_SIGNATURE] =
3549 mono_reflection_encode_sighelper (assembly, helper);
3555 reflection_cc_to_file (int call_conv) {
3556 switch (call_conv & 0x3) {
3558 case 1: return MONO_CALL_DEFAULT;
3559 case 2: return MONO_CALL_VARARG;
3561 g_assert_not_reached ();
3565 #endif /* !DISABLE_REFLECTION_EMIT */
3569 MonoMethodSignature *sig;
3574 #ifndef DISABLE_REFLECTION_EMIT
3576 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3581 MonoMethodSignature *sig;
3585 name = mono_string_to_utf8 (m->name);
3586 nparams = mono_array_length (m->parameters);
3587 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3589 sig->sentinelpos = -1;
3590 sig->call_convention = reflection_cc_to_file (m->call_conv);
3591 sig->param_count = nparams;
3592 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3593 mtype = mono_reflection_type_get_handle (m->parent);
3594 for (i = 0; i < nparams; ++i)
3595 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3597 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3598 am = (ArrayMethod *)tmp->data;
3599 if (strcmp (name, am->name) == 0 &&
3600 mono_metadata_type_equal (am->parent, mtype) &&
3601 mono_metadata_signature_equal (am->sig, sig)) {
3604 m->table_idx = am->token & 0xffffff;
3608 am = g_new0 (ArrayMethod, 1);
3612 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3613 method_encode_signature (assembly, sig));
3614 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3615 m->table_idx = am->token & 0xffffff;
3620 * Insert into the metadata tables all the info about the TypeBuilder tb.
3621 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3624 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3626 MonoDynamicTable *table;
3628 int i, is_object = 0, is_system = 0;
3631 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3632 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3633 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3634 n = mono_string_to_utf8 (tb->name);
3635 if (strcmp (n, "Object") == 0)
3637 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3639 n = mono_string_to_utf8 (tb->nspace);
3640 if (strcmp (n, "System") == 0)
3642 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3644 if (tb->parent && !(is_system && is_object) &&
3645 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3646 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3648 values [MONO_TYPEDEF_EXTENDS] = 0;
3650 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3651 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3654 * if we have explicitlayout or sequentiallayouts, output data in the
3655 * ClassLayout table.
3657 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3658 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3659 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3661 alloc_table (table, table->rows);
3662 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3663 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3664 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3665 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3668 /* handle interfaces */
3669 if (tb->interfaces) {
3670 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3672 table->rows += mono_array_length (tb->interfaces);
3673 alloc_table (table, table->rows);
3674 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3675 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3676 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3677 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3678 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3679 values += MONO_INTERFACEIMPL_SIZE;
3685 table = &assembly->tables [MONO_TABLE_FIELD];
3686 table->rows += tb->num_fields;
3687 alloc_table (table, table->rows);
3688 for (i = 0; i < tb->num_fields; ++i)
3689 mono_image_get_field_info (
3690 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3693 /* handle constructors */
3695 table = &assembly->tables [MONO_TABLE_METHOD];
3696 table->rows += mono_array_length (tb->ctors);
3697 alloc_table (table, table->rows);
3698 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3699 mono_image_get_ctor_info (domain,
3700 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3703 /* handle methods */
3705 table = &assembly->tables [MONO_TABLE_METHOD];
3706 table->rows += tb->num_methods;
3707 alloc_table (table, table->rows);
3708 for (i = 0; i < tb->num_methods; ++i)
3709 mono_image_get_method_info (
3710 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3713 /* Do the same with properties etc.. */
3714 if (tb->events && mono_array_length (tb->events)) {
3715 table = &assembly->tables [MONO_TABLE_EVENT];
3716 table->rows += mono_array_length (tb->events);
3717 alloc_table (table, table->rows);
3718 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3720 alloc_table (table, table->rows);
3721 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3722 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3723 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3724 for (i = 0; i < mono_array_length (tb->events); ++i)
3725 mono_image_get_event_info (
3726 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3728 if (tb->properties && mono_array_length (tb->properties)) {
3729 table = &assembly->tables [MONO_TABLE_PROPERTY];
3730 table->rows += mono_array_length (tb->properties);
3731 alloc_table (table, table->rows);
3732 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3734 alloc_table (table, table->rows);
3735 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3736 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3737 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3738 for (i = 0; i < mono_array_length (tb->properties); ++i)
3739 mono_image_get_property_info (
3740 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3743 /* handle generic parameters */
3744 if (tb->generic_params) {
3745 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3746 table->rows += mono_array_length (tb->generic_params);
3747 alloc_table (table, table->rows);
3748 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3749 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3751 mono_image_get_generic_param_info (
3752 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3756 mono_image_add_decl_security (assembly,
3757 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3760 MonoDynamicTable *ntable;
3762 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3763 ntable->rows += mono_array_length (tb->subtypes);
3764 alloc_table (ntable, ntable->rows);
3765 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3767 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3768 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3770 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3771 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3772 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3773 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3774 mono_string_to_utf8 (tb->name), tb->table_idx,
3775 ntable->next_idx, ntable->rows);*/
3776 values += MONO_NESTED_CLASS_SIZE;
3784 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3788 mono_ptr_array_append (*types, type);
3790 if (!type->subtypes)
3793 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3794 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3795 collect_types (types, subtype);
3800 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3802 if ((*type1)->table_idx < (*type2)->table_idx)
3805 if ((*type1)->table_idx > (*type2)->table_idx)
3812 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3817 for (i = 0; i < mono_array_length (pinfo); ++i) {
3818 MonoReflectionParamBuilder *pb;
3819 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3822 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3827 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3830 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3832 for (i = 0; i < tb->num_fields; ++i) {
3833 MonoReflectionFieldBuilder* fb;
3834 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3835 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3839 for (i = 0; i < mono_array_length (tb->events); ++i) {
3840 MonoReflectionEventBuilder* eb;
3841 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3842 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3845 if (tb->properties) {
3846 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3847 MonoReflectionPropertyBuilder* pb;
3848 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3849 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3853 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3854 MonoReflectionCtorBuilder* cb;
3855 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3856 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3857 params_add_cattrs (assembly, cb->pinfo);
3862 for (i = 0; i < tb->num_methods; ++i) {
3863 MonoReflectionMethodBuilder* mb;
3864 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3865 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3866 params_add_cattrs (assembly, mb->pinfo);
3871 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3872 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3877 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3881 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3883 if (moduleb->global_methods) {
3884 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3885 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3886 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3887 params_add_cattrs (assembly, mb->pinfo);
3891 if (moduleb->global_fields) {
3892 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3893 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3894 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3898 if (moduleb->types) {
3899 for (i = 0; i < moduleb->num_types; ++i)
3900 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3905 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3907 MonoDynamicTable *table;
3911 char *b = blob_size;
3914 table = &assembly->tables [MONO_TABLE_FILE];
3916 alloc_table (table, table->rows);
3917 values = table->values + table->next_idx * MONO_FILE_SIZE;
3918 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3919 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3920 if (image_is_dynamic (module->image)) {
3921 /* This depends on the fact that the main module is emitted last */
3922 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3923 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3926 path = g_strdup (module->image->name);
3928 mono_sha1_get_digest_from_file (path, hash);
3931 mono_metadata_encode_value (20, b, &b);
3932 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3933 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3940 MonoDynamicTable *table;
3943 table = &assembly->tables [MONO_TABLE_MODULE];
3944 mb->table_idx = table->next_idx ++;
3945 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3946 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3949 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3950 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3951 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3952 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3956 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3957 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3959 MonoDynamicTable *table;
3963 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3964 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3967 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3969 alloc_table (table, table->rows);
3970 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3972 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3973 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3974 if (klass->nested_in)
3975 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3977 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3978 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3979 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3981 res = table->next_idx;
3985 /* Emit nested types */
3986 if (klass->ext && klass->ext->nested_classes) {
3989 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3990 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3997 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3998 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4003 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4005 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4007 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4008 parent_index, assembly);
4012 * We need to do this ourselves since klass->nested_classes is not set up.
4015 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4016 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4021 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4022 guint32 module_index, MonoDynamicImage *assembly)
4024 MonoImage *image = module->image;
4028 t = &image->tables [MONO_TABLE_TYPEDEF];
4030 for (i = 0; i < t->rows; ++i) {
4032 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4033 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4035 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4036 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4041 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4043 MonoDynamicTable *table;
4045 guint32 scope, scope_idx, impl, current_idx;
4046 gboolean forwarder = TRUE;
4047 gpointer iter = NULL;
4050 if (klass->nested_in) {
4051 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4054 scope = resolution_scope_from_image (assembly, klass->image);
4055 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4056 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4057 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4060 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4063 alloc_table (table, table->rows);
4064 current_idx = table->next_idx;
4065 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4067 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4068 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4069 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4070 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4071 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4075 while ((nested = mono_class_get_nested_types (klass, &iter)))
4076 add_exported_type (assemblyb, assembly, nested, current_idx);
4080 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4085 if (!assemblyb->type_forwarders)
4088 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4089 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4094 type = mono_reflection_type_get_handle (t);
4097 klass = mono_class_from_mono_type (type);
4099 add_exported_type (assemblyb, assembly, klass, 0);
4103 #define align_pointer(base,p)\
4105 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4107 (p) += 4 - (__diff & 3);\
4111 compare_constants (const void *a, const void *b)
4113 const guint32 *a_values = (const guint32 *)a;
4114 const guint32 *b_values = (const guint32 *)b;
4115 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4119 compare_semantics (const void *a, const void *b)
4121 const guint32 *a_values = (const guint32 *)a;
4122 const guint32 *b_values = (const guint32 *)b;
4123 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4126 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4130 compare_custom_attrs (const void *a, const void *b)
4132 const guint32 *a_values = (const guint32 *)a;
4133 const guint32 *b_values = (const guint32 *)b;
4135 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4139 compare_field_marshal (const void *a, const void *b)
4141 const guint32 *a_values = (const guint32 *)a;
4142 const guint32 *b_values = (const guint32 *)b;
4144 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4148 compare_nested (const void *a, const void *b)
4150 const guint32 *a_values = (const guint32 *)a;
4151 const guint32 *b_values = (const guint32 *)b;
4153 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4157 compare_genericparam (const void *a, const void *b)
4159 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4160 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4162 if ((*b_entry)->owner == (*a_entry)->owner)
4164 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4165 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4167 return (*a_entry)->owner - (*b_entry)->owner;
4171 compare_declsecurity_attrs (const void *a, const void *b)
4173 const guint32 *a_values = (const guint32 *)a;
4174 const guint32 *b_values = (const guint32 *)b;
4176 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4180 compare_interface_impl (const void *a, const void *b)
4182 const guint32 *a_values = (const guint32 *)a;
4183 const guint32 *b_values = (const guint32 *)b;
4185 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4189 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4193 pad_heap (MonoDynamicStream *sh)
4195 if (sh->index & 3) {
4196 int sz = 4 - (sh->index & 3);
4197 memset (sh->data + sh->index, 0, sz);
4204 MonoDynamicStream *stream;
4208 * build_compressed_metadata() fills in the blob of data that represents the
4209 * raw metadata as it will be saved in the PE file. The five streams are output
4210 * and the metadata tables are comnpressed from the guint32 array representation,
4211 * to the compressed on-disk format.
4214 build_compressed_metadata (MonoDynamicImage *assembly)
4216 MonoDynamicTable *table;
4218 guint64 valid_mask = 0;
4219 guint64 sorted_mask;
4220 guint32 heapt_size = 0;
4221 guint32 meta_size = 256; /* allow for header and other stuff */
4222 guint32 table_offset;
4223 guint32 ntables = 0;
4229 struct StreamDesc stream_desc [5];
4231 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4232 for (i = 0; i < assembly->gen_params->len; i++){
4233 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4234 write_generic_param_entry (assembly, entry);
4237 stream_desc [0].name = "#~";
4238 stream_desc [0].stream = &assembly->tstream;
4239 stream_desc [1].name = "#Strings";
4240 stream_desc [1].stream = &assembly->sheap;
4241 stream_desc [2].name = "#US";
4242 stream_desc [2].stream = &assembly->us;
4243 stream_desc [3].name = "#Blob";
4244 stream_desc [3].stream = &assembly->blob;
4245 stream_desc [4].name = "#GUID";
4246 stream_desc [4].stream = &assembly->guid;
4248 /* tables that are sorted */
4249 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4250 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4251 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4252 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4253 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4254 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4255 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4257 /* Compute table sizes */
4258 /* the MonoImage has already been created in mono_image_basic_init() */
4259 meta = &assembly->image;
4261 /* sizes should be multiple of 4 */
4262 pad_heap (&assembly->blob);
4263 pad_heap (&assembly->guid);
4264 pad_heap (&assembly->sheap);
4265 pad_heap (&assembly->us);
4267 /* Setup the info used by compute_sizes () */
4268 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4269 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4270 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4272 meta_size += assembly->blob.index;
4273 meta_size += assembly->guid.index;
4274 meta_size += assembly->sheap.index;
4275 meta_size += assembly->us.index;
4277 for (i=0; i < MONO_TABLE_NUM; ++i)
4278 meta->tables [i].rows = assembly->tables [i].rows;
4280 for (i = 0; i < MONO_TABLE_NUM; i++){
4281 if (meta->tables [i].rows == 0)
4283 valid_mask |= (guint64)1 << i;
4285 meta->tables [i].row_size = mono_metadata_compute_size (
4286 meta, i, &meta->tables [i].size_bitfield);
4287 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4289 heapt_size += 24; /* #~ header size */
4290 heapt_size += ntables * 4;
4291 /* make multiple of 4 */
4294 meta_size += heapt_size;
4295 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4296 p = (unsigned char*)meta->raw_metadata;
4297 /* the metadata signature */
4298 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4299 /* version numbers and 4 bytes reserved */
4300 int16val = (guint16*)p;
4301 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4302 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4304 /* version string */
4305 int32val = (guint32*)p;
4306 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4308 memcpy (p, meta->version, strlen (meta->version));
4309 p += GUINT32_FROM_LE (*int32val);
4310 align_pointer (meta->raw_metadata, p);
4311 int16val = (guint16*)p;
4312 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4313 *int16val = GUINT16_TO_LE (5); /* number of streams */
4317 * write the stream info.
4319 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4320 table_offset += 3; table_offset &= ~3;
4322 assembly->tstream.index = heapt_size;
4323 for (i = 0; i < 5; ++i) {
4324 int32val = (guint32*)p;
4325 stream_desc [i].stream->offset = table_offset;
4326 *int32val++ = GUINT32_TO_LE (table_offset);
4327 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4328 table_offset += GUINT32_FROM_LE (*int32val);
4329 table_offset += 3; table_offset &= ~3;
4331 strcpy ((char*)p, stream_desc [i].name);
4332 p += strlen (stream_desc [i].name) + 1;
4333 align_pointer (meta->raw_metadata, p);
4336 * now copy the data, the table stream header and contents goes first.
4338 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4339 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4340 int32val = (guint32*)p;
4341 *int32val = GUINT32_TO_LE (0); /* reserved */
4344 *p++ = 2; /* version */
4347 if (meta->idx_string_wide)
4349 if (meta->idx_guid_wide)
4351 if (meta->idx_blob_wide)
4354 *p++ = 1; /* reserved */
4355 int64val = (guint64*)p;
4356 *int64val++ = GUINT64_TO_LE (valid_mask);
4357 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4359 int32val = (guint32*)p;
4360 for (i = 0; i < MONO_TABLE_NUM; i++){
4361 if (meta->tables [i].rows == 0)
4363 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4365 p = (unsigned char*)int32val;
4367 /* sort the tables that still need sorting */
4368 table = &assembly->tables [MONO_TABLE_CONSTANT];
4370 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4371 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4373 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4374 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4376 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4377 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4379 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4380 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4382 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4383 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4384 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4386 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4387 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4389 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4391 /* compress the tables */
4392 for (i = 0; i < MONO_TABLE_NUM; i++){
4395 guint32 bitfield = meta->tables [i].size_bitfield;
4396 if (!meta->tables [i].rows)
4398 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4399 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4400 meta->tables [i].base = (char*)p;
4401 for (row = 1; row <= meta->tables [i].rows; ++row) {
4402 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4403 for (col = 0; col < assembly->tables [i].columns; ++col) {
4404 switch (mono_metadata_table_size (bitfield, col)) {
4406 *p++ = values [col];
4409 *p++ = values [col] & 0xff;
4410 *p++ = (values [col] >> 8) & 0xff;
4413 *p++ = values [col] & 0xff;
4414 *p++ = (values [col] >> 8) & 0xff;
4415 *p++ = (values [col] >> 16) & 0xff;
4416 *p++ = (values [col] >> 24) & 0xff;
4419 g_assert_not_reached ();
4423 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4426 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4427 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4428 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4429 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4430 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4432 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4436 * Some tables in metadata need to be sorted according to some criteria, but
4437 * when methods and fields are first created with reflection, they may be assigned a token
4438 * that doesn't correspond to the final token they will get assigned after the sorting.
4439 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4440 * with the reflection objects that represent them. Once all the tables are set up, the
4441 * reflection objects will contains the correct table index. fixup_method() will fixup the
4442 * tokens for the method with ILGenerator @ilgen.
4445 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4447 guint32 code_idx = GPOINTER_TO_UINT (value);
4448 MonoReflectionILTokenInfo *iltoken;
4449 MonoReflectionFieldBuilder *field;
4450 MonoReflectionCtorBuilder *ctor;
4451 MonoReflectionMethodBuilder *method;
4452 MonoReflectionTypeBuilder *tb;
4453 MonoReflectionArrayMethod *am;
4455 unsigned char *target;
4457 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4458 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4459 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4460 switch (target [3]) {
4461 case MONO_TABLE_FIELD:
4462 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4463 field = (MonoReflectionFieldBuilder *)iltoken->member;
4464 idx = field->table_idx;
4465 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4466 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4467 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4469 g_assert_not_reached ();
4472 case MONO_TABLE_METHOD:
4473 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4474 method = (MonoReflectionMethodBuilder *)iltoken->member;
4475 idx = method->table_idx;
4476 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4477 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4478 idx = ctor->table_idx;
4479 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4480 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4481 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4482 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4484 g_assert_not_reached ();
4487 case MONO_TABLE_TYPEDEF:
4488 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4489 g_assert_not_reached ();
4490 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4491 idx = tb->table_idx;
4493 case MONO_TABLE_MEMBERREF:
4494 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4495 am = (MonoReflectionArrayMethod*)iltoken->member;
4496 idx = am->table_idx;
4497 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4498 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4499 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4500 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4501 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4502 g_assert (m->klass->generic_class || m->klass->generic_container);
4504 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4506 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4507 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4508 g_assert (is_field_on_inst (f));
4510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4511 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4513 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4517 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4520 g_assert_not_reached ();
4523 case MONO_TABLE_METHODSPEC:
4524 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4525 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4526 g_assert (mono_method_signature (m)->generic_param_count);
4528 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4530 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4533 g_assert_not_reached ();
4537 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4539 target [0] = idx & 0xff;
4540 target [1] = (idx >> 8) & 0xff;
4541 target [2] = (idx >> 16) & 0xff;
4548 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4549 * value is not known when the table is emitted.
4552 fixup_cattrs (MonoDynamicImage *assembly)
4554 MonoDynamicTable *table;
4556 guint32 type, i, idx, token;
4559 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4561 for (i = 0; i < table->rows; ++i) {
4562 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4564 type = values [MONO_CUSTOM_ATTR_TYPE];
4565 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4566 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4567 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4568 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4571 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4572 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4573 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4575 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4576 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4577 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4578 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4585 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4587 MonoDynamicTable *table;
4590 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4592 alloc_table (table, table->rows);
4593 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4594 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4595 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4596 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4597 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4602 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4604 MonoDynamicTable *table;
4608 char *b = blob_size;
4610 guint32 idx, offset;
4612 if (rsrc->filename) {
4613 name = mono_string_to_utf8 (rsrc->filename);
4614 sname = g_path_get_basename (name);
4616 table = &assembly->tables [MONO_TABLE_FILE];
4618 alloc_table (table, table->rows);
4619 values = table->values + table->next_idx * MONO_FILE_SIZE;
4620 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4621 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4624 mono_sha1_get_digest_from_file (name, hash);
4625 mono_metadata_encode_value (20, b, &b);
4626 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4627 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4629 idx = table->next_idx++;
4631 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4637 data = mono_array_addr (rsrc->data, char, 0);
4638 len = mono_array_length (rsrc->data);
4644 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4645 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4646 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4647 mono_image_add_stream_data (&assembly->resources, data, len);
4651 * The entry should be emitted into the MANIFESTRESOURCE table of
4652 * the main module, but that needs to reference the FILE table
4653 * which isn't emitted yet.
4660 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4664 set_version_from_string (MonoString *version, guint32 *values)
4666 gchar *ver, *p, *str;
4669 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4670 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4671 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4672 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4675 ver = str = mono_string_to_utf8 (version);
4676 for (i = 0; i < 4; ++i) {
4677 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4683 /* handle Revision and Build */
4693 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4697 char *b = blob_size;
4702 len = mono_array_length (pkey);
4703 mono_metadata_encode_value (len, b, &b);
4704 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4705 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4707 assembly->public_key = (guint8 *)g_malloc (len);
4708 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4709 assembly->public_key_len = len;
4711 /* Special case: check for ECMA key (16 bytes) */
4712 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4713 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4714 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4715 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4716 /* minimum key size (in 2.0) is 384 bits */
4717 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4719 /* FIXME - verifier */
4720 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4721 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4723 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4729 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4731 MonoDynamicTable *table;
4732 MonoDynamicImage *assembly;
4733 MonoReflectionAssemblyBuilder *assemblyb;
4737 guint32 module_index;
4739 assemblyb = moduleb->assemblyb;
4740 assembly = moduleb->dynamic_image;
4741 domain = mono_object_domain (assemblyb);
4743 /* Emit ASSEMBLY table */
4744 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4745 alloc_table (table, 1);
4746 values = table->values + MONO_ASSEMBLY_SIZE;
4747 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4748 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4749 if (assemblyb->culture) {
4750 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4752 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4754 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4755 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4756 set_version_from_string (assemblyb->version, values);
4758 /* Emit FILE + EXPORTED_TYPE table */
4760 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4762 MonoReflectionModuleBuilder *file_module =
4763 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4764 if (file_module != moduleb) {
4765 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4767 if (file_module->types) {
4768 for (j = 0; j < file_module->num_types; ++j) {
4769 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4775 if (assemblyb->loaded_modules) {
4776 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4777 MonoReflectionModule *file_module =
4778 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4779 mono_image_fill_file_table (domain, file_module, assembly);
4781 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4784 if (assemblyb->type_forwarders)
4785 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4787 /* Emit MANIFESTRESOURCE table */
4789 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4791 MonoReflectionModuleBuilder *file_module =
4792 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4793 /* The table for the main module is emitted later */
4794 if (file_module != moduleb) {
4796 if (file_module->resources) {
4797 int len = mono_array_length (file_module->resources);
4798 for (j = 0; j < len; ++j) {
4799 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4800 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4807 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4810 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4811 * for the modulebuilder @moduleb.
4812 * At the end of the process, method and field tokens are fixed up and the
4813 * on-disk compressed metadata representation is created.
4816 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4818 MonoDynamicTable *table;
4819 MonoDynamicImage *assembly;
4820 MonoReflectionAssemblyBuilder *assemblyb;
4826 assemblyb = moduleb->assemblyb;
4827 assembly = moduleb->dynamic_image;
4828 domain = mono_object_domain (assemblyb);
4830 if (assembly->text_rva)
4833 assembly->text_rva = START_TEXT_RVA;
4835 if (moduleb->is_main) {
4836 mono_image_emit_manifest (moduleb);
4839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840 table->rows = 1; /* .<Module> */
4842 alloc_table (table, table->rows);
4844 * Set the first entry.
4846 values = table->values + table->columns;
4847 values [MONO_TYPEDEF_FLAGS] = 0;
4848 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4849 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4850 values [MONO_TYPEDEF_EXTENDS] = 0;
4851 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4852 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4855 * handle global methods
4856 * FIXME: test what to do when global methods are defined in multiple modules.
4858 if (moduleb->global_methods) {
4859 table = &assembly->tables [MONO_TABLE_METHOD];
4860 table->rows += mono_array_length (moduleb->global_methods);
4861 alloc_table (table, table->rows);
4862 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4863 mono_image_get_method_info (
4864 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4866 if (moduleb->global_fields) {
4867 table = &assembly->tables [MONO_TABLE_FIELD];
4868 table->rows += mono_array_length (moduleb->global_fields);
4869 alloc_table (table, table->rows);
4870 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4871 mono_image_get_field_info (
4872 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4875 table = &assembly->tables [MONO_TABLE_MODULE];
4876 alloc_table (table, 1);
4877 mono_image_fill_module_table (domain, moduleb, assembly);
4879 /* Collect all types into a list sorted by their table_idx */
4880 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4883 for (i = 0; i < moduleb->num_types; ++i) {
4884 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4885 collect_types (&types, type);
4888 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4889 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4890 table->rows += mono_ptr_array_size (types);
4891 alloc_table (table, table->rows);
4894 * Emit type names + namespaces at one place inside the string heap,
4895 * so load_class_names () needs to touch fewer pages.
4897 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4898 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4899 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4901 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4902 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4903 string_heap_insert_mstring (&assembly->sheap, tb->name);
4906 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4907 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4908 mono_image_get_type_info (domain, type, assembly);
4912 * table->rows is already set above and in mono_image_fill_module_table.
4914 /* add all the custom attributes at the end, once all the indexes are stable */
4915 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4917 /* CAS assembly permissions */
4918 if (assemblyb->permissions_minimum)
4919 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4920 if (assemblyb->permissions_optional)
4921 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4922 if (assemblyb->permissions_refused)
4923 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4925 module_add_cattrs (assembly, moduleb);
4928 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4930 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4931 * the final tokens and don't need another fixup pass. */
4933 if (moduleb->global_methods) {
4934 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4935 MonoReflectionMethodBuilder *mb = mono_array_get (
4936 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4937 mono_image_add_methodimpl (assembly, mb);
4941 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4942 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4943 if (type->methods) {
4944 for (j = 0; j < type->num_methods; ++j) {
4945 MonoReflectionMethodBuilder *mb = mono_array_get (
4946 type->methods, MonoReflectionMethodBuilder*, j);
4948 mono_image_add_methodimpl (assembly, mb);
4953 mono_ptr_array_destroy (types);
4955 fixup_cattrs (assembly);
4958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4961 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4963 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4970 guint32 import_lookup_table;
4974 guint32 import_address_table_rva;
4982 #ifndef DISABLE_REFLECTION_EMIT
4985 * mono_image_insert_string:
4986 * @module: module builder object
4989 * Insert @str into the user string stream of @module.
4992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4994 MonoDynamicImage *assembly;
4999 if (!module->dynamic_image)
5000 mono_image_module_basic_init (module);
5002 assembly = module->dynamic_image;
5004 if (assembly->save) {
5005 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5006 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5009 char *swapped = g_malloc (2 * mono_string_length (str));
5010 const char *p = (const char*)mono_string_chars (str);
5012 swap_with_size (swapped, p, 2, mono_string_length (str));
5013 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5017 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5019 mono_image_add_stream_data (&assembly->us, "", 1);
5021 idx = assembly->us.index ++;
5024 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5026 return MONO_TOKEN_STRING | idx;
5030 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5034 MonoMethodSignature *sig;
5036 klass = obj->vtable->klass;
5037 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5038 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5039 MonoMethodSignature *old;
5040 guint32 sig_token, parent;
5043 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5045 nargs = mono_array_length (opt_param_types);
5046 old = mono_method_signature (method);
5047 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5049 sig->hasthis = old->hasthis;
5050 sig->explicit_this = old->explicit_this;
5051 sig->call_convention = old->call_convention;
5052 sig->generic_param_count = old->generic_param_count;
5053 sig->param_count = old->param_count + nargs;
5054 sig->sentinelpos = old->param_count;
5055 sig->ret = old->ret;
5057 for (i = 0; i < old->param_count; i++)
5058 sig->params [i] = old->params [i];
5060 for (i = 0; i < nargs; i++) {
5061 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5062 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5065 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5066 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5067 parent >>= MONO_TYPEDEFORREF_BITS;
5069 parent <<= MONO_MEMBERREF_PARENT_BITS;
5070 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5072 sig_token = method_encode_signature (assembly, sig);
5073 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5074 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5075 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5076 ReflectionMethodBuilder rmb;
5077 guint32 parent, sig_token;
5078 int nopt_args, nparams, ngparams, i;
5081 reflection_methodbuilder_from_method_builder (&rmb, mb);
5082 rmb.opt_types = opt_param_types;
5083 nopt_args = mono_array_length (opt_param_types);
5085 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5086 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5087 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5089 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5090 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5091 sig->call_convention = rmb.call_conv;
5092 sig->generic_param_count = ngparams;
5093 sig->param_count = nparams + nopt_args;
5094 sig->sentinelpos = nparams;
5095 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5097 for (i = 0; i < nparams; i++) {
5098 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5099 sig->params [i] = mono_reflection_type_get_handle (rt);
5102 for (i = 0; i < nopt_args; i++) {
5103 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5104 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5107 sig_token = method_builder_encode_signature (assembly, &rmb);
5109 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5110 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5112 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5113 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5115 name = mono_string_to_utf8 (rmb.name);
5116 token = mono_image_get_varargs_method_token (
5117 assembly, parent, name, sig_token);
5120 g_error ("requested method token for %s\n", klass->name);
5123 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5124 register_dyn_token (assembly, token, obj);
5129 * mono_image_create_token:
5130 * @assembly: a dynamic assembly
5132 * @register_token: Whenever to register the token in the assembly->tokens hash.
5134 * Get a token to insert in the IL code stream for the given MemberInfo.
5135 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5136 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5140 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5141 gboolean create_open_instance, gboolean register_token)
5146 klass = obj->vtable->klass;
5148 /* Check for user defined reflection objects */
5149 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5150 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5151 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5153 if (strcmp (klass->name, "MethodBuilder") == 0) {
5154 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5155 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5157 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5158 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5160 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5161 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5162 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5163 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5164 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5166 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5167 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5169 token = mono_image_get_ctorbuilder_token (assembly, mb);
5170 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5171 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5172 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5173 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5174 if (tb->generic_params) {
5175 token = mono_image_get_generic_field_token (assembly, fb);
5177 if (tb->module->dynamic_image == assembly) {
5178 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5180 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5183 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5185 if (create_open_instance && tb->generic_params) {
5187 init_type_builder_generics (obj);
5188 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5190 token = mono_metadata_token_from_dor (token);
5191 } else if (tb->module->dynamic_image == assembly) {
5192 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5195 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5196 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5198 } else if (strcmp (klass->name, "MonoType") == 0) {
5199 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5200 MonoClass *mc = mono_class_from_mono_type (type);
5201 token = mono_metadata_token_from_dor (
5202 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5203 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5204 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5205 token = mono_metadata_token_from_dor (
5206 mono_image_typedef_or_ref (assembly, type));
5207 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5208 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5209 token = mono_metadata_token_from_dor (
5210 mono_image_typedef_or_ref (assembly, type));
5211 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5212 strcmp (klass->name, "MonoMethod") == 0 ||
5213 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5214 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5215 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5216 if (m->method->is_inflated) {
5217 if (create_open_instance)
5218 token = mono_image_get_methodspec_token (assembly, m->method);
5220 token = mono_image_get_inflated_method_token (assembly, m->method);
5221 } else if ((m->method->klass->image == &assembly->image) &&
5222 !m->method->klass->generic_class) {
5223 static guint32 method_table_idx = 0xffffff;
5224 if (m->method->klass->wastypebuilder) {
5225 /* we use the same token as the one that was assigned
5226 * to the Methodbuilder.
5227 * FIXME: do the equivalent for Fields.
5229 token = m->method->token;
5232 * Each token should have a unique index, but the indexes are
5233 * assigned by managed code, so we don't know about them. An
5234 * easy solution is to count backwards...
5236 method_table_idx --;
5237 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5240 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5242 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5243 } else if (strcmp (klass->name, "MonoField") == 0) {
5244 MonoReflectionField *f = (MonoReflectionField *)obj;
5245 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5246 static guint32 field_table_idx = 0xffffff;
5248 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5250 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5252 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5253 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5254 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5255 token = mono_image_get_array_token (assembly, m);
5256 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5257 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5258 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5259 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5260 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5261 token = mono_metadata_token_from_dor (
5262 mono_image_typedef_or_ref (assembly, type));
5263 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5264 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5265 token = mono_image_get_field_on_inst_token (assembly, f);
5266 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5267 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5268 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5269 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5270 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5271 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5272 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5273 MonoReflectionType *type = (MonoReflectionType *)obj;
5274 token = mono_metadata_token_from_dor (
5275 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5277 g_error ("requested token for %s\n", klass->name);
5281 mono_image_register_token (assembly, token, obj);
5287 * mono_image_register_token:
5289 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5290 * the Module.ResolveXXXToken () methods to work.
5293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5297 dynamic_image_lock (assembly);
5298 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5300 /* There could be multiple MethodInfo objects with the same token */
5301 //g_assert (prev == obj);
5303 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5305 dynamic_image_unlock (assembly);
5308 static MonoDynamicImage*
5309 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5311 static const guchar entrycode [16] = {0xff, 0x25, 0};
5312 MonoDynamicImage *image;
5315 const char *version;
5317 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5318 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5320 version = mono_get_runtime_info ()->runtime_version;
5323 /* The MonoGHashTable's need GC tracking */
5324 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5326 image = g_new0 (MonoDynamicImage, 1);
5329 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5331 /*g_print ("created image %p\n", image);*/
5332 /* keep in sync with image.c */
5333 image->image.name = assembly_name;
5334 image->image.assembly_name = image->image.name; /* they may be different */
5335 image->image.module_name = module_name;
5336 image->image.version = g_strdup (version);
5337 image->image.md_version_major = 1;
5338 image->image.md_version_minor = 1;
5339 image->image.dynamic = TRUE;
5341 image->image.references = g_new0 (MonoAssembly*, 1);
5342 image->image.references [0] = NULL;
5344 mono_image_init (&image->image);
5346 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5347 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5348 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5349 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5350 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5351 image->handleref = g_hash_table_new (NULL, NULL);
5352 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5353 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5354 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5355 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5356 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5357 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5358 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5359 image->gen_params = g_ptr_array_new ();
5360 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5362 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5363 string_heap_init (&image->sheap);
5364 mono_image_add_stream_data (&image->us, "", 1);
5365 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5366 /* import tables... */
5367 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5368 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5369 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5370 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5371 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5372 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5373 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5374 stream_data_align (&image->code);
5376 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5378 for (i=0; i < MONO_TABLE_NUM; ++i) {
5379 image->tables [i].next_idx = 1;
5380 image->tables [i].columns = table_sizes [i];
5383 image->image.assembly = (MonoAssembly*)assembly;
5384 image->run = assembly->run;
5385 image->save = assembly->save;
5386 image->pe_kind = 0x1; /* ILOnly */
5387 image->machine = 0x14c; /* I386 */
5389 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5391 dynamic_images_lock ();
5393 if (!dynamic_images)
5394 dynamic_images = g_ptr_array_new ();
5396 g_ptr_array_add (dynamic_images, image);
5398 dynamic_images_unlock ();
5405 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5411 release_hashtable (MonoGHashTable **hash)
5414 mono_g_hash_table_destroy (*hash);
5420 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5422 release_hashtable (&image->token_fixups);
5423 release_hashtable (&image->handleref_managed);
5424 release_hashtable (&image->tokens);
5425 release_hashtable (&image->remapped_tokens);
5426 release_hashtable (&image->generic_def_objects);
5427 release_hashtable (&image->methodspec);
5430 // Free dynamic image pass one: Free resources but not image itself
5432 mono_dynamic_image_free (MonoDynamicImage *image)
5434 MonoDynamicImage *di = image;
5439 mono_g_hash_table_destroy (di->methodspec);
5441 g_hash_table_destroy (di->typespec);
5443 g_hash_table_destroy (di->typeref);
5445 g_hash_table_destroy (di->handleref);
5446 if (di->handleref_managed)
5447 mono_g_hash_table_destroy (di->handleref_managed);
5449 mono_g_hash_table_destroy (di->tokens);
5450 if (di->remapped_tokens)
5451 mono_g_hash_table_destroy (di->remapped_tokens);
5452 if (di->generic_def_objects)
5453 mono_g_hash_table_destroy (di->generic_def_objects);
5454 if (di->blob_cache) {
5455 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5456 g_hash_table_destroy (di->blob_cache);
5458 if (di->standalonesig_cache)
5459 g_hash_table_destroy (di->standalonesig_cache);
5460 for (list = di->array_methods; list; list = list->next) {
5461 ArrayMethod *am = (ArrayMethod *)list->data;
5466 g_list_free (di->array_methods);
5467 if (di->gen_params) {
5468 for (i = 0; i < di->gen_params->len; i++) {
5469 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5470 mono_gc_deregister_root ((char*) &entry->gparam);
5473 g_ptr_array_free (di->gen_params, TRUE);
5475 if (di->token_fixups)
5476 mono_g_hash_table_destroy (di->token_fixups);
5477 if (di->method_to_table_idx)
5478 g_hash_table_destroy (di->method_to_table_idx);
5479 if (di->field_to_table_idx)
5480 g_hash_table_destroy (di->field_to_table_idx);
5481 if (di->method_aux_hash)
5482 g_hash_table_destroy (di->method_aux_hash);
5483 if (di->vararg_aux_hash)
5484 g_hash_table_destroy (di->vararg_aux_hash);
5485 g_free (di->strong_name);
5486 g_free (di->win32_res);
5488 g_free (di->public_key);
5490 /*g_print ("string heap destroy for image %p\n", di);*/
5491 mono_dynamic_stream_reset (&di->sheap);
5492 mono_dynamic_stream_reset (&di->code);
5493 mono_dynamic_stream_reset (&di->resources);
5494 mono_dynamic_stream_reset (&di->us);
5495 mono_dynamic_stream_reset (&di->blob);
5496 mono_dynamic_stream_reset (&di->tstream);
5497 mono_dynamic_stream_reset (&di->guid);
5498 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5499 g_free (di->tables [i].values);
5502 dynamic_images_lock ();
5505 g_ptr_array_remove (dynamic_images, di);
5507 dynamic_images_unlock ();
5510 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5512 mono_dynamic_image_free_image (MonoDynamicImage *image)
5514 /* See create_dynamic_mono_image () */
5516 /* Allocated using GC_MALLOC */
5522 #ifndef DISABLE_REFLECTION_EMIT
5525 * mono_image_basic_init:
5526 * @assembly: an assembly builder object
5528 * Create the MonoImage that represents the assembly builder and setup some
5529 * of the helper hash table and the basic metadata streams.
5532 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5534 MonoDynamicAssembly *assembly;
5535 MonoDynamicImage *image;
5536 MonoDomain *domain = mono_object_domain (assemblyb);
5538 if (assemblyb->dynamic_assembly)
5542 /* assembly->assembly.image might be GC allocated */
5543 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5545 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5548 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5550 assembly->assembly.ref_count = 1;
5551 assembly->assembly.dynamic = TRUE;
5552 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5553 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5554 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5555 if (assemblyb->culture)
5556 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5558 assembly->assembly.aname.culture = g_strdup ("");
5560 if (assemblyb->version) {
5561 char *vstr = mono_string_to_utf8 (assemblyb->version);
5562 char **version = g_strsplit (vstr, ".", 4);
5563 char **parts = version;
5564 assembly->assembly.aname.major = atoi (*parts++);
5565 assembly->assembly.aname.minor = atoi (*parts++);
5566 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5567 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5569 g_strfreev (version);
5572 assembly->assembly.aname.major = 0;
5573 assembly->assembly.aname.minor = 0;
5574 assembly->assembly.aname.build = 0;
5575 assembly->assembly.aname.revision = 0;
5578 assembly->run = assemblyb->access != 2;
5579 assembly->save = assemblyb->access != 1;
5580 assembly->domain = domain;
5582 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5583 image->initial_image = TRUE;
5584 assembly->assembly.aname.name = image->image.name;
5585 assembly->assembly.image = &image->image;
5586 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5587 /* -1 to correct for the trailing NULL byte */
5588 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5589 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5591 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5594 mono_domain_assemblies_lock (domain);
5595 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5596 mono_domain_assemblies_unlock (domain);
5598 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5600 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5602 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5605 #endif /* !DISABLE_REFLECTION_EMIT */
5607 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5610 calc_section_size (MonoDynamicImage *assembly)
5614 /* alignment constraints */
5615 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5616 g_assert ((assembly->code.index % 4) == 0);
5617 assembly->meta_size += 3;
5618 assembly->meta_size &= ~3;
5619 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5620 g_assert ((assembly->resources.index % 4) == 0);
5622 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5623 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5626 if (assembly->win32_res) {
5627 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5629 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5630 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5634 assembly->sections [MONO_SECTION_RELOC].size = 12;
5635 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5645 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5649 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5651 ResTreeNode *t1 = (ResTreeNode*)a;
5652 ResTreeNode *t2 = (ResTreeNode*)b;
5654 return t1->id - t2->id;
5658 * resource_tree_create:
5660 * Organize the resources into a resource tree.
5662 static ResTreeNode *
5663 resource_tree_create (MonoArray *win32_resources)
5665 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5669 tree = g_new0 (ResTreeNode, 1);
5671 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5672 MonoReflectionWin32Resource *win32_res =
5673 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5677 /* FIXME: BUG: this stores managed references in unmanaged memory */
5678 lang_node = g_new0 (ResTreeNode, 1);
5679 lang_node->id = win32_res->lang_id;
5680 lang_node->win32_res = win32_res;
5682 /* Create type node if neccesary */
5684 for (l = tree->children; l; l = l->next)
5685 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5686 type_node = (ResTreeNode*)l->data;
5691 type_node = g_new0 (ResTreeNode, 1);
5692 type_node->id = win32_res->res_type;
5695 * The resource types have to be sorted otherwise
5696 * Windows Explorer can't display the version information.
5698 tree->children = g_slist_insert_sorted (tree->children,
5699 type_node, resource_tree_compare_by_id);
5702 /* Create res node if neccesary */
5704 for (l = type_node->children; l; l = l->next)
5705 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5706 res_node = (ResTreeNode*)l->data;
5711 res_node = g_new0 (ResTreeNode, 1);
5712 res_node->id = win32_res->res_id;
5713 type_node->children = g_slist_append (type_node->children, res_node);
5716 res_node->children = g_slist_append (res_node->children, lang_node);
5723 * resource_tree_encode:
5725 * Encode the resource tree into the format used in the PE file.
5728 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5731 MonoPEResourceDir dir;
5732 MonoPEResourceDirEntry dir_entry;
5733 MonoPEResourceDataEntry data_entry;
5735 guint32 res_id_entries;
5738 * For the format of the resource directory, see the article
5739 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5743 memset (&dir, 0, sizeof (dir));
5744 memset (&dir_entry, 0, sizeof (dir_entry));
5745 memset (&data_entry, 0, sizeof (data_entry));
5747 g_assert (sizeof (dir) == 16);
5748 g_assert (sizeof (dir_entry) == 8);
5749 g_assert (sizeof (data_entry) == 16);
5751 node->offset = p - begin;
5753 /* IMAGE_RESOURCE_DIRECTORY */
5754 res_id_entries = g_slist_length (node->children);
5755 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5757 memcpy (p, &dir, sizeof (dir));
5760 /* Reserve space for entries */
5762 p += sizeof (dir_entry) * res_id_entries;
5764 /* Write children */
5765 for (l = node->children; l; l = l->next) {
5766 ResTreeNode *child = (ResTreeNode*)l->data;
5768 if (child->win32_res) {
5771 child->offset = p - begin;
5773 /* IMAGE_RESOURCE_DATA_ENTRY */
5774 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5775 size = mono_array_length (child->win32_res->res_data);
5776 data_entry.rde_size = GUINT32_TO_LE (size);
5778 memcpy (p, &data_entry, sizeof (data_entry));
5779 p += sizeof (data_entry);
5781 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5784 resource_tree_encode (child, begin, p, &p);
5788 /* IMAGE_RESOURCE_ENTRY */
5789 for (l = node->children; l; l = l->next) {
5790 ResTreeNode *child = (ResTreeNode*)l->data;
5792 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5793 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5795 memcpy (entries, &dir_entry, sizeof (dir_entry));
5796 entries += sizeof (dir_entry);
5803 resource_tree_free (ResTreeNode * node)
5806 for (list = node->children; list; list = list->next)
5807 resource_tree_free ((ResTreeNode*)list->data);
5808 g_slist_free(node->children);
5813 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5818 MonoReflectionWin32Resource *win32_res;
5821 if (!assemblyb->win32_resources)
5825 * Resources are stored in a three level tree inside the PE file.
5826 * - level one contains a node for each type of resource
5827 * - level two contains a node for each resource
5828 * - level three contains a node for each instance of a resource for a
5829 * specific language.
5832 tree = resource_tree_create (assemblyb->win32_resources);
5834 /* Estimate the size of the encoded tree */
5836 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5837 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5838 size += mono_array_length (win32_res->res_data);
5840 /* Directory structure */
5841 size += mono_array_length (assemblyb->win32_resources) * 256;
5842 p = buf = (char *)g_malloc (size);
5844 resource_tree_encode (tree, p, p, &p);
5846 g_assert (p - buf <= size);
5848 assembly->win32_res = (char *)g_malloc (p - buf);
5849 assembly->win32_res_size = p - buf;
5850 memcpy (assembly->win32_res, buf, p - buf);
5853 resource_tree_free (tree);
5857 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5859 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5862 p += sizeof (MonoPEResourceDir);
5863 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5864 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5865 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5866 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5867 fixup_resource_directory (res_section, child, rva);
5869 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5870 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5873 p += sizeof (MonoPEResourceDirEntry);
5878 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5881 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5882 g_error ("WriteFile returned %d\n", GetLastError ());
5886 * mono_image_create_pefile:
5887 * @mb: a module builder object
5889 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5890 * assembly->pefile where it can be easily retrieved later in chunks.
5893 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5895 MonoMSDOSHeader *msdos;
5896 MonoDotNetHeader *header;
5897 MonoSectionTable *section;
5898 MonoCLIHeader *cli_header;
5899 guint32 size, image_size, virtual_base, text_offset;
5900 guint32 header_start, section_start, file_offset, virtual_offset;
5901 MonoDynamicImage *assembly;
5902 MonoReflectionAssemblyBuilder *assemblyb;
5903 MonoDynamicStream pefile_stream = {0};
5904 MonoDynamicStream *pefile = &pefile_stream;
5906 guint32 *rva, value;
5908 static const unsigned char msheader[] = {
5909 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5910 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5913 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5914 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5915 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5916 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5919 assemblyb = mb->assemblyb;
5921 mono_image_basic_init (assemblyb);
5922 assembly = mb->dynamic_image;
5924 assembly->pe_kind = assemblyb->pe_kind;
5925 assembly->machine = assemblyb->machine;
5926 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5927 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5929 mono_image_build_metadata (mb);
5931 if (mb->is_main && assemblyb->resources) {
5932 int len = mono_array_length (assemblyb->resources);
5933 for (i = 0; i < len; ++i)
5934 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5937 if (mb->resources) {
5938 int len = mono_array_length (mb->resources);
5939 for (i = 0; i < len; ++i)
5940 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5943 build_compressed_metadata (assembly);
5946 assembly_add_win32_resources (assembly, assemblyb);
5948 nsections = calc_section_size (assembly);
5950 /* The DOS header and stub */
5951 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5952 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5954 /* the dotnet header */
5955 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5957 /* the section tables */
5958 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5960 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5961 virtual_offset = VIRT_ALIGN;
5964 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5965 if (!assembly->sections [i].size)
5968 file_offset += FILE_ALIGN - 1;
5969 file_offset &= ~(FILE_ALIGN - 1);
5970 virtual_offset += VIRT_ALIGN - 1;
5971 virtual_offset &= ~(VIRT_ALIGN - 1);
5973 assembly->sections [i].offset = file_offset;
5974 assembly->sections [i].rva = virtual_offset;
5976 file_offset += assembly->sections [i].size;
5977 virtual_offset += assembly->sections [i].size;
5978 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5981 file_offset += FILE_ALIGN - 1;
5982 file_offset &= ~(FILE_ALIGN - 1);
5984 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5986 /* back-patch info */
5987 msdos = (MonoMSDOSHeader*)pefile->data;
5988 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5990 header = (MonoDotNetHeader*)(pefile->data + header_start);
5991 header->pesig [0] = 'P';
5992 header->pesig [1] = 'E';
5994 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5995 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5996 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5997 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5998 if (assemblyb->pekind == 1) {
6000 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6003 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6006 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6008 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6009 header->pe.pe_major = 6;
6010 header->pe.pe_minor = 0;
6011 size = assembly->sections [MONO_SECTION_TEXT].size;
6012 size += FILE_ALIGN - 1;
6013 size &= ~(FILE_ALIGN - 1);
6014 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6015 size = assembly->sections [MONO_SECTION_RSRC].size;
6016 size += FILE_ALIGN - 1;
6017 size &= ~(FILE_ALIGN - 1);
6018 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6019 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6020 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6021 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6022 /* pe_rva_entry_point always at the beginning of the text section */
6023 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6025 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6026 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6027 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6028 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6029 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6030 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6031 size = section_start;
6032 size += FILE_ALIGN - 1;
6033 size &= ~(FILE_ALIGN - 1);
6034 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6036 size += VIRT_ALIGN - 1;
6037 size &= ~(VIRT_ALIGN - 1);
6038 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6041 // Translate the PEFileKind value to the value expected by the Windows loader
6047 // PEFileKinds.Dll == 1
6048 // PEFileKinds.ConsoleApplication == 2
6049 // PEFileKinds.WindowApplication == 3
6052 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6053 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6055 if (assemblyb->pekind == 3)
6060 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6062 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6063 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6064 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6065 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6066 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6067 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6069 /* fill data directory entries */
6071 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6072 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6074 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6075 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6077 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6078 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6079 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6080 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6081 /* patch entrypoint name */
6082 if (assemblyb->pekind == 1)
6083 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6085 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6086 /* patch imported function RVA name */
6087 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6088 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6090 /* the import table */
6091 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6092 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6093 /* patch imported dll RVA name and other entries in the dir */
6094 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6095 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6096 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6097 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6098 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6099 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6101 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6102 value = (assembly->text_rva + assembly->imp_names_offset);
6103 *p++ = (value) & 0xff;
6104 *p++ = (value >> 8) & (0xff);
6105 *p++ = (value >> 16) & (0xff);
6106 *p++ = (value >> 24) & (0xff);
6108 /* the CLI header info */
6109 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6110 cli_header->ch_size = GUINT32_FROM_LE (72);
6111 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6112 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6113 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6114 if (assemblyb->entry_point) {
6115 guint32 table_idx = 0;
6116 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6117 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6118 table_idx = methodb->table_idx;
6120 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6122 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6124 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6126 /* The embedded managed resources */
6127 text_offset = assembly->text_rva + assembly->code.index;
6128 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6129 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6130 text_offset += assembly->resources.index;
6131 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6132 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6133 text_offset += assembly->meta_size;
6134 if (assembly->strong_name_size) {
6135 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6136 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6137 text_offset += assembly->strong_name_size;
6140 /* write the section tables and section content */
6141 section = (MonoSectionTable*)(pefile->data + section_start);
6142 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6143 static const char section_names [][7] = {
6144 ".text", ".rsrc", ".reloc"
6146 if (!assembly->sections [i].size)
6148 strcpy (section->st_name, section_names [i]);
6149 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6150 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6151 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6152 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6153 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6154 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6155 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6159 checked_write_file (file, pefile->data, pefile->index);
6161 mono_dynamic_stream_reset (pefile);
6163 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6164 if (!assembly->sections [i].size)
6167 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6168 g_error ("SetFilePointer returned %d\n", GetLastError ());
6171 case MONO_SECTION_TEXT:
6172 /* patch entry point */
6173 p = (guchar*)(assembly->code.data + 2);
6174 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6175 *p++ = (value) & 0xff;
6176 *p++ = (value >> 8) & 0xff;
6177 *p++ = (value >> 16) & 0xff;
6178 *p++ = (value >> 24) & 0xff;
6180 checked_write_file (file, assembly->code.data, assembly->code.index);
6181 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6182 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6183 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6186 g_free (assembly->image.raw_metadata);
6188 case MONO_SECTION_RELOC: {
6192 guint16 type_and_offset;
6196 g_assert (sizeof (reloc) == 12);
6198 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6199 reloc.block_size = GUINT32_FROM_LE (12);
6202 * the entrypoint is always at the start of the text section
6203 * 3 is IMAGE_REL_BASED_HIGHLOW
6204 * 2 is patch_size_rva - text_rva
6206 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6209 checked_write_file (file, &reloc, sizeof (reloc));
6213 case MONO_SECTION_RSRC:
6214 if (assembly->win32_res) {
6216 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6217 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6218 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6222 g_assert_not_reached ();
6226 /* check that the file is properly padded */
6227 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6228 g_error ("SetFilePointer returned %d\n", GetLastError ());
6229 if (! SetEndOfFile (file))
6230 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6232 mono_dynamic_stream_reset (&assembly->code);
6233 mono_dynamic_stream_reset (&assembly->us);
6234 mono_dynamic_stream_reset (&assembly->blob);
6235 mono_dynamic_stream_reset (&assembly->guid);
6236 mono_dynamic_stream_reset (&assembly->sheap);
6238 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6239 g_hash_table_destroy (assembly->blob_cache);
6240 assembly->blob_cache = NULL;
6243 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6246 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6248 g_assert_not_reached ();
6251 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6253 #ifndef DISABLE_REFLECTION_EMIT
6255 MonoReflectionModule *
6256 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6260 MonoImageOpenStatus status;
6261 MonoDynamicAssembly *assembly;
6262 guint32 module_count;
6263 MonoImage **new_modules;
6264 gboolean *new_modules_loaded;
6266 name = mono_string_to_utf8 (fileName);
6268 image = mono_image_open (name, &status);
6271 if (status == MONO_IMAGE_ERROR_ERRNO)
6272 exc = mono_get_exception_file_not_found (fileName);
6274 exc = mono_get_exception_bad_image_format (name);
6276 mono_raise_exception (exc);
6281 assembly = ab->dynamic_assembly;
6282 image->assembly = (MonoAssembly*)assembly;
6284 module_count = image->assembly->image->module_count;
6285 new_modules = g_new0 (MonoImage *, module_count + 1);
6286 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6288 if (image->assembly->image->modules)
6289 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6290 if (image->assembly->image->modules_loaded)
6291 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6292 new_modules [module_count] = image;
6293 new_modules_loaded [module_count] = TRUE;
6294 mono_image_addref (image);
6296 g_free (image->assembly->image->modules);
6297 image->assembly->image->modules = new_modules;
6298 image->assembly->image->modules_loaded = new_modules_loaded;
6299 image->assembly->image->module_count ++;
6301 mono_assembly_load_references (image, &status);
6303 mono_image_close (image);
6304 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6307 return mono_module_get_object (mono_domain_get (), image);
6310 #endif /* DISABLE_REFLECTION_EMIT */
6313 * We need to return always the same object for MethodInfo, FieldInfo etc..
6314 * but we need to consider the reflected type.
6315 * type uses a different hash, since it uses custom hash/equal functions.
6320 MonoClass *refclass;
6324 reflected_equal (gconstpointer a, gconstpointer b) {
6325 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6326 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6328 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6332 reflected_hash (gconstpointer a) {
6333 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6334 return mono_aligned_addr_hash (ea->item);
6337 #define CHECK_OBJECT(t,p,k) \
6343 mono_domain_lock (domain); \
6344 if (!domain->refobject_hash) \
6345 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6346 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6347 mono_domain_unlock (domain); \
6350 mono_domain_unlock (domain); \
6353 #ifdef HAVE_BOEHM_GC
6354 /* ReflectedEntry doesn't need to be GC tracked */
6355 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6356 #define FREE_REFENTRY(entry) g_free ((entry))
6357 #define REFENTRY_REQUIRES_CLEANUP
6359 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6361 #define FREE_REFENTRY(entry)
6364 #define CACHE_OBJECT(t,p,o,k) \
6367 ReflectedEntry pe; \
6369 pe.refclass = (k); \
6370 mono_domain_lock (domain); \
6371 if (!domain->refobject_hash) \
6372 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6373 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6375 ReflectedEntry *e = ALLOC_REFENTRY; \
6377 e->refclass = (k); \
6378 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6381 mono_domain_unlock (domain); \
6386 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6388 mono_domain_lock (domain);
6389 if (domain->refobject_hash) {
6391 gpointer orig_pe, orig_value;
6394 pe.refclass = klass;
6395 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6396 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6397 FREE_REFENTRY (orig_pe);
6400 mono_domain_unlock (domain);
6403 #ifdef REFENTRY_REQUIRES_CLEANUP
6405 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6407 FREE_REFENTRY (key);
6412 mono_reflection_cleanup_domain (MonoDomain *domain)
6414 if (domain->refobject_hash) {
6415 /*let's avoid scanning the whole hashtable if not needed*/
6416 #ifdef REFENTRY_REQUIRES_CLEANUP
6417 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6419 mono_g_hash_table_destroy (domain->refobject_hash);
6420 domain->refobject_hash = NULL;
6424 #ifndef DISABLE_REFLECTION_EMIT
6426 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6428 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6432 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6434 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6438 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6440 MonoDynamicImage *image = moduleb->dynamic_image;
6441 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6445 MonoImage **new_modules;
6447 char *name, *fqname;
6449 * FIXME: we already created an image in mono_image_basic_init (), but
6450 * we don't know which module it belongs to, since that is only
6451 * determined at assembly save time.
6453 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6454 name = mono_string_to_utf8 (ab->name);
6455 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6456 if (!mono_error_ok (&error)) {
6458 mono_error_raise_exception (&error);
6460 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6462 moduleb->module.image = &image->image;
6463 moduleb->dynamic_image = image;
6464 register_module (mono_object_domain (moduleb), moduleb, image);
6466 /* register the module with the assembly */
6467 ass = ab->dynamic_assembly->assembly.image;
6468 module_count = ass->module_count;
6469 new_modules = g_new0 (MonoImage *, module_count + 1);
6472 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6473 new_modules [module_count] = &image->image;
6474 mono_image_addref (&image->image);
6476 g_free (ass->modules);
6477 ass->modules = new_modules;
6478 ass->module_count ++;
6483 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6485 MonoDynamicImage *image = moduleb->dynamic_image;
6487 g_assert (type->type);
6488 image->wrappers_type = mono_class_from_mono_type (type->type);
6494 * mono_assembly_get_object:
6495 * @domain: an app domain
6496 * @assembly: an assembly
6498 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6500 MonoReflectionAssembly*
6501 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6504 static MonoClass *assembly_type;
6505 MonoReflectionAssembly *res;
6507 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6508 if (!assembly_type) {
6509 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6511 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6513 assembly_type = klass;
6515 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6516 mono_error_raise_exception (&error); /* FIXME don't raise here */
6517 res->assembly = assembly;
6519 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6524 MonoReflectionModule*
6525 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6528 static MonoClass *module_type;
6529 MonoReflectionModule *res;
6532 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6534 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6536 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6538 module_type = klass;
6540 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6541 mono_error_raise_exception (&error); /* FIXME don't raise here */
6544 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6546 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6547 basename = g_path_get_basename (image->name);
6548 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6549 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6553 if (image->assembly->image == image) {
6554 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6558 if (image->assembly->image->modules) {
6559 for (i = 0; i < image->assembly->image->module_count; i++) {
6560 if (image->assembly->image->modules [i] == image)
6561 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6563 g_assert (res->token);
6567 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6570 MonoReflectionModule*
6571 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6574 static MonoClass *module_type;
6575 MonoReflectionModule *res;
6576 MonoTableInfo *table;
6577 guint32 cols [MONO_FILE_SIZE];
6579 guint32 i, name_idx;
6583 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6585 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6587 module_type = klass;
6589 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6590 mono_error_raise_exception (&error); /* FIXME don't raise here */
6592 table = &image->tables [MONO_TABLE_FILE];
6593 g_assert (table_index < table->rows);
6594 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6597 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6598 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6600 /* Check whenever the row has a corresponding row in the moduleref table */
6601 table = &image->tables [MONO_TABLE_MODULEREF];
6602 for (i = 0; i < table->rows; ++i) {
6603 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6604 val = mono_metadata_string_heap (image, name_idx);
6605 if (strcmp (val, name) == 0)
6606 res->image = image->modules [i];
6609 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6610 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6611 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6612 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6613 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6619 verify_safe_for_managed_space (MonoType *type)
6621 switch (type->type) {
6623 case MONO_TYPE_ARRAY:
6624 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6626 return verify_safe_for_managed_space (type->data.type);
6627 case MONO_TYPE_SZARRAY:
6628 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6629 case MONO_TYPE_GENERICINST: {
6630 MonoGenericInst *inst = type->data.generic_class->inst;
6634 for (i = 0; i < inst->type_argc; ++i)
6635 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6641 case MONO_TYPE_MVAR:
6649 mono_type_normalize (MonoType *type)
6652 MonoGenericClass *gclass;
6653 MonoGenericInst *ginst;
6655 MonoGenericContainer *gcontainer;
6656 MonoType **argv = NULL;
6657 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6659 if (type->type != MONO_TYPE_GENERICINST)
6662 gclass = type->data.generic_class;
6663 ginst = gclass->context.class_inst;
6664 if (!ginst->is_open)
6667 gtd = gclass->container_class;
6668 gcontainer = gtd->generic_container;
6669 argv = g_newa (MonoType*, ginst->type_argc);
6671 for (i = 0; i < ginst->type_argc; ++i) {
6672 MonoType *t = ginst->type_argv [i], *norm;
6673 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6674 is_denorm_gtd = FALSE;
6675 norm = mono_type_normalize (t);
6678 requires_rebind = TRUE;
6682 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6684 if (requires_rebind) {
6685 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6686 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6692 * mono_type_get_object:
6693 * @domain: an app domain
6696 * Return an System.MonoType object representing the type @type.
6699 mono_type_get_object (MonoDomain *domain, MonoType *type)
6702 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6703 mono_error_raise_exception (&error);
6709 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6711 MonoType *norm_type;
6712 MonoReflectionType *res;
6715 mono_error_init (error);
6717 klass = mono_class_from_mono_type (type);
6719 /*we must avoid using @type as it might have come
6720 * from a mono_metadata_type_dup and the caller
6721 * expects that is can be freed.
6722 * Using the right type from
6724 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6726 /* void is very common */
6727 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6728 return (MonoReflectionType*)domain->typeof_void;
6731 * If the vtable of the given class was already created, we can use
6732 * the MonoType from there and avoid all locking and hash table lookups.
6734 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6735 * that the resulting object is different.
6737 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6738 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6739 if (vtable && vtable->type)
6740 return (MonoReflectionType *)vtable->type;
6743 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6744 mono_domain_lock (domain);
6745 if (!domain->type_hash)
6746 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6747 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6748 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6749 mono_domain_unlock (domain);
6750 mono_loader_unlock ();
6754 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6755 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6756 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6757 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6758 * artifact of how generics are encoded and should be transparent to managed code so we
6759 * need to weed out this diference when retrieving managed System.Type objects.
6761 norm_type = mono_type_normalize (type);
6762 if (norm_type != type) {
6763 res = mono_type_get_object_checked (domain, norm_type, error);
6764 if (!mono_error_ok (error))
6766 mono_g_hash_table_insert (domain->type_hash, type, res);
6767 mono_domain_unlock (domain);
6768 mono_loader_unlock ();
6772 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6773 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6776 if (!verify_safe_for_managed_space (type)) {
6777 mono_domain_unlock (domain);
6778 mono_loader_unlock ();
6779 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6782 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6783 gboolean is_type_done = TRUE;
6784 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6785 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6786 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6788 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6789 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6791 if (gparam->owner && gparam->owner->is_method) {
6792 MonoMethod *method = gparam->owner->owner.method;
6793 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6794 is_type_done = FALSE;
6795 } else if (gparam->owner && !gparam->owner->is_method) {
6796 MonoClass *klass = gparam->owner->owner.klass;
6797 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6798 is_type_done = FALSE;
6802 /* g_assert_not_reached (); */
6803 /* should this be considered an error condition? */
6804 if (is_type_done && !type->byref) {
6805 mono_domain_unlock (domain);
6806 mono_loader_unlock ();
6807 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6810 /* This is stored in vtables/JITted code so it has to be pinned */
6811 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6812 if (!mono_error_ok (error))
6816 mono_g_hash_table_insert (domain->type_hash, type, res);
6818 if (type->type == MONO_TYPE_VOID)
6819 domain->typeof_void = (MonoObject*)res;
6821 mono_domain_unlock (domain);
6822 mono_loader_unlock ();
6827 * mono_method_get_object:
6828 * @domain: an app domain
6830 * @refclass: the reflected type (can be NULL)
6832 * Return an System.Reflection.MonoMethod object representing the method @method.
6834 MonoReflectionMethod*
6835 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6838 * We use the same C representation for methods and constructors, but the type
6839 * name in C# is different.
6841 static MonoClass *System_Reflection_MonoMethod = NULL;
6842 static MonoClass *System_Reflection_MonoCMethod = NULL;
6843 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6844 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6846 MonoReflectionType *rt;
6848 MonoReflectionMethod *ret;
6850 if (method->is_inflated) {
6851 MonoReflectionGenericMethod *gret;
6854 refclass = method->klass;
6855 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6856 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6857 if (!System_Reflection_MonoGenericCMethod)
6858 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6859 klass = System_Reflection_MonoGenericCMethod;
6861 if (!System_Reflection_MonoGenericMethod)
6862 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6863 klass = System_Reflection_MonoGenericMethod;
6865 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, &error);
6866 mono_error_raise_exception (&error); /* FIXME don't raise here */
6867 gret->method.method = method;
6869 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6871 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6872 mono_error_raise_exception (&error); /* FIXME don't raise here */
6874 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6876 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6880 refclass = method->klass;
6882 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6883 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6884 if (!System_Reflection_MonoCMethod)
6885 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6886 klass = System_Reflection_MonoCMethod;
6889 if (!System_Reflection_MonoMethod)
6890 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6891 klass = System_Reflection_MonoMethod;
6893 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, &error);
6894 mono_error_raise_exception (&error); /* FIXME don't raise here */
6895 ret->method = method;
6897 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6898 mono_error_raise_exception (&error); /* FIXME don't raise here */;
6900 MONO_OBJECT_SETREF (ret, reftype, rt);
6902 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6906 * mono_method_clear_object:
6908 * Clear the cached reflection objects for the dynamic method METHOD.
6911 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6914 g_assert (method_is_dynamic (method));
6916 klass = method->klass;
6918 clear_cached_object (domain, method, klass);
6919 klass = klass->parent;
6921 /* Added by mono_param_get_objects () */
6922 clear_cached_object (domain, &(method->signature), NULL);
6923 klass = method->klass;
6925 clear_cached_object (domain, &(method->signature), klass);
6926 klass = klass->parent;
6931 * mono_field_get_object:
6932 * @domain: an app domain
6936 * Return an System.Reflection.MonoField object representing the field @field
6939 MonoReflectionField*
6940 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6943 MonoReflectionType *rt;
6944 MonoReflectionField *res;
6945 static MonoClass *monofield_klass;
6947 CHECK_OBJECT (MonoReflectionField *, field, klass);
6948 if (!monofield_klass)
6949 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6950 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, &error);
6951 mono_error_raise_exception (&error); /* FIXME don't raise here */
6954 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6956 if (is_field_on_inst (field)) {
6957 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6959 rt = mono_type_get_object_checked (domain, field->type, &error);
6960 mono_error_raise_exception (&error); /* FIXME don't raise here */
6962 MONO_OBJECT_SETREF (res, type, rt);
6965 rt = mono_type_get_object_checked (domain, field->type, &error);
6966 mono_error_raise_exception (&error); /* FIXME don't raise here */
6968 MONO_OBJECT_SETREF (res, type, rt);
6970 res->attrs = mono_field_get_flags (field);
6972 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6976 * mono_property_get_object:
6977 * @domain: an app domain
6979 * @property: a property
6981 * Return an System.Reflection.MonoProperty object representing the property @property
6984 MonoReflectionProperty*
6985 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6988 MonoReflectionProperty *res;
6989 static MonoClass *monoproperty_klass;
6991 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6992 if (!monoproperty_klass)
6993 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6994 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
6995 mono_error_raise_exception (&error); /* FIXME don't raise here */
6997 res->property = property;
6998 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7002 * mono_event_get_object:
7003 * @domain: an app domain
7007 * Return an System.Reflection.MonoEvent object representing the event @event
7010 MonoReflectionEvent*
7011 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7014 MonoReflectionEvent *res;
7015 MonoReflectionMonoEvent *mono_event;
7016 static MonoClass *monoevent_klass;
7018 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7019 if (!monoevent_klass)
7020 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7021 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7022 mono_error_raise_exception (&error); /* FIXME don't raise here */
7023 mono_event->klass = klass;
7024 mono_event->event = event;
7025 res = (MonoReflectionEvent*)mono_event;
7026 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7030 * mono_get_reflection_missing_object:
7031 * @domain: Domain where the object lives
7033 * Returns the System.Reflection.Missing.Value singleton object
7034 * (of type System.Reflection.Missing).
7036 * Used as the value for ParameterInfo.DefaultValue when Optional
7040 mono_get_reflection_missing_object (MonoDomain *domain)
7043 static MonoClassField *missing_value_field = NULL;
7045 if (!missing_value_field) {
7046 MonoClass *missing_klass;
7047 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7048 mono_class_init (missing_klass);
7049 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7050 g_assert (missing_value_field);
7052 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7058 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7061 *dbnull = mono_get_dbnull_object (domain);
7066 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7068 if (!*reflection_missing)
7069 *reflection_missing = mono_get_reflection_missing_object (domain);
7070 return *reflection_missing;
7074 * mono_param_get_objects:
7075 * @domain: an app domain
7078 * Return an System.Reflection.ParameterInfo array object representing the parameters
7079 * in the method @method.
7082 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7084 static MonoClass *System_Reflection_ParameterInfo;
7085 static MonoClass *System_Reflection_ParameterInfo_array;
7087 MonoArray *res = NULL;
7088 MonoReflectionMethod *member = NULL;
7089 MonoReflectionParameter *param = NULL;
7090 char **names, **blobs = NULL;
7091 guint32 *types = NULL;
7092 MonoType *type = NULL;
7093 MonoObject *dbnull = NULL;
7094 MonoObject *missing = NULL;
7095 MonoMarshalSpec **mspecs;
7096 MonoMethodSignature *sig;
7097 MonoVTable *pinfo_vtable;
7098 MonoReflectionType *rt;
7101 if (!System_Reflection_ParameterInfo_array) {
7104 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7106 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7108 mono_memory_barrier ();
7109 System_Reflection_ParameterInfo = klass;
7112 klass = mono_array_class_get (klass, 1);
7113 mono_memory_barrier ();
7114 System_Reflection_ParameterInfo_array = klass;
7117 sig = mono_method_signature_checked (method, &error);
7118 if (!mono_error_ok (&error))
7119 mono_error_raise_exception (&error);
7121 if (!sig->param_count) {
7122 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7123 mono_error_raise_exception (&error); /* FIXME don't raise here */
7128 /* Note: the cache is based on the address of the signature into the method
7129 * since we already cache MethodInfos with the method as keys.
7131 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7133 member = mono_method_get_object (domain, method, refclass);
7134 names = g_new (char *, sig->param_count);
7135 mono_method_get_param_names (method, (const char **) names);
7137 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7138 mono_method_get_marshal_info (method, mspecs);
7140 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7141 mono_error_raise_exception (&error); /* FIXME don't raise here */
7143 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7144 for (i = 0; i < sig->param_count; ++i) {
7145 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7146 mono_error_raise_exception (&error); /* FIXME don't raise here */
7148 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7149 mono_error_raise_exception (&error); /* FIXME don't raise here */
7151 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7153 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7155 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7157 param->PositionImpl = i;
7158 param->AttrsImpl = sig->params [i]->attrs;
7160 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7161 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7162 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7164 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7168 blobs = g_new0 (char *, sig->param_count);
7169 types = g_new0 (guint32, sig->param_count);
7170 get_default_param_value_blobs (method, blobs, types);
7173 /* Build MonoType for the type from the Constant Table */
7175 type = g_new0 (MonoType, 1);
7176 type->type = (MonoTypeEnum)types [i];
7177 type->data.klass = NULL;
7178 if (types [i] == MONO_TYPE_CLASS)
7179 type->data.klass = mono_defaults.object_class;
7180 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7181 /* For enums, types [i] contains the base type */
7183 type->type = MONO_TYPE_VALUETYPE;
7184 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7186 type->data.klass = mono_class_from_mono_type (type);
7188 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7190 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7191 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7192 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7193 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7195 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7201 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7203 mono_array_setref (res, i, param);
7210 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7212 mono_metadata_free_marshal_spec (mspecs [i]);
7215 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7219 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7221 return mono_param_get_objects_internal (domain, method, NULL);
7225 * mono_method_body_get_object:
7226 * @domain: an app domain
7229 * Return an System.Reflection.MethodBody object representing the method @method.
7231 MonoReflectionMethodBody*
7232 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7234 static MonoClass *System_Reflection_MethodBody = NULL;
7235 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7236 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7238 MonoReflectionMethodBody *ret;
7239 MonoMethodHeader *header;
7241 MonoReflectionType *rt;
7242 guint32 method_rva, local_var_sig_token;
7244 unsigned char format, flags;
7247 /* for compatibility with .net */
7248 if (method_is_dynamic (method))
7249 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7251 if (!System_Reflection_MethodBody)
7252 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7253 if (!System_Reflection_LocalVariableInfo)
7254 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7255 if (!System_Reflection_ExceptionHandlingClause)
7256 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7258 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7260 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7261 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7262 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7263 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7264 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7267 image = method->klass->image;
7268 header = mono_method_get_header (method);
7270 if (!image_is_dynamic (image)) {
7271 /* Obtain local vars signature token */
7272 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7273 ptr = mono_image_rva_map (image, method_rva);
7274 flags = *(const unsigned char *) ptr;
7275 format = flags & METHOD_HEADER_FORMAT_MASK;
7277 case METHOD_HEADER_TINY_FORMAT:
7278 local_var_sig_token = 0;
7280 case METHOD_HEADER_FAT_FORMAT:
7284 local_var_sig_token = read32 (ptr);
7287 g_assert_not_reached ();
7290 local_var_sig_token = 0; //FIXME
7292 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7293 mono_error_raise_exception (&error); /* FIXME don't raise here */
7295 ret->init_locals = header->init_locals;
7296 ret->max_stack = header->max_stack;
7297 ret->local_var_sig_token = local_var_sig_token;
7298 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7299 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7302 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7303 for (i = 0; i < header->num_locals; ++i) {
7304 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7305 mono_error_raise_exception (&error); /* FIXME don't raise here */
7307 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7308 mono_error_raise_exception (&error); /* FIXME don't raise here */
7310 MONO_OBJECT_SETREF (info, local_type, rt);
7312 info->is_pinned = header->locals [i]->pinned;
7313 info->local_index = i;
7314 mono_array_setref (ret->locals, i, info);
7318 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7319 for (i = 0; i < header->num_clauses; ++i) {
7320 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7321 mono_error_raise_exception (&error); /* FIXME don't raise here */
7322 MonoExceptionClause *clause = &header->clauses [i];
7324 info->flags = clause->flags;
7325 info->try_offset = clause->try_offset;
7326 info->try_length = clause->try_len;
7327 info->handler_offset = clause->handler_offset;
7328 info->handler_length = clause->handler_len;
7329 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7330 info->filter_offset = clause->data.filter_offset;
7331 else if (clause->data.catch_class) {
7332 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7333 mono_error_raise_exception (&error); /* FIXME don't raise here */
7335 MONO_OBJECT_SETREF (info, catch_type, rt);
7338 mono_array_setref (ret->clauses, i, info);
7341 mono_metadata_free_mh (header);
7342 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7347 * mono_get_dbnull_object:
7348 * @domain: Domain where the object lives
7350 * Returns the System.DBNull.Value singleton object
7352 * Used as the value for ParameterInfo.DefaultValue
7355 mono_get_dbnull_object (MonoDomain *domain)
7358 static MonoClassField *dbnull_value_field = NULL;
7360 if (!dbnull_value_field) {
7361 MonoClass *dbnull_klass;
7362 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7363 mono_class_init (dbnull_klass);
7364 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7365 g_assert (dbnull_value_field);
7367 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7373 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7375 guint32 param_index, i, lastp, crow = 0;
7376 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7379 MonoClass *klass = method->klass;
7380 MonoImage *image = klass->image;
7381 MonoMethodSignature *methodsig = mono_method_signature (method);
7383 MonoTableInfo *constt;
7384 MonoTableInfo *methodt;
7385 MonoTableInfo *paramt;
7387 if (!methodsig->param_count)
7390 mono_class_init (klass);
7392 if (image_is_dynamic (klass->image)) {
7393 MonoReflectionMethodAux *aux;
7394 if (method->is_inflated)
7395 method = ((MonoMethodInflated*)method)->declaring;
7396 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7397 if (aux && aux->param_defaults) {
7398 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7399 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7404 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7405 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7406 constt = &image->tables [MONO_TABLE_CONSTANT];
7408 idx = mono_method_get_index (method) - 1;
7409 g_assert (idx != -1);
7411 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7412 if (idx + 1 < methodt->rows)
7413 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7415 lastp = paramt->rows + 1;
7417 for (i = param_index; i < lastp; ++i) {
7420 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7421 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7423 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7426 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7431 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7432 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7433 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7440 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7446 MonoType *basetype = type;
7451 klass = mono_class_from_mono_type (type);
7452 if (klass->valuetype) {
7453 object = mono_object_new_checked (domain, klass, &error);
7454 mono_error_raise_exception (&error); /* FIXME don't raise here */
7455 retval = ((gchar *) object + sizeof (MonoObject));
7456 if (klass->enumtype)
7457 basetype = mono_class_enum_basetype (klass);
7462 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7469 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7472 gboolean quoted = FALSE;
7474 memset (assembly, 0, sizeof (MonoAssemblyName));
7475 assembly->culture = "";
7476 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7483 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7494 /* Remove trailing whitespace */
7496 while (*s && g_ascii_isspace (*s))
7499 while (g_ascii_isspace (*p))
7502 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7504 assembly->major = strtoul (p, &s, 10);
7505 if (s == p || *s != '.')
7508 assembly->minor = strtoul (p, &s, 10);
7509 if (s == p || *s != '.')
7512 assembly->build = strtoul (p, &s, 10);
7513 if (s == p || *s != '.')
7516 assembly->revision = strtoul (p, &s, 10);
7520 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7522 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7523 assembly->culture = "";
7526 assembly->culture = p;
7527 while (*p && *p != ',') {
7531 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7533 if (strncmp (p, "null", 4) == 0) {
7538 while (*p && *p != ',') {
7541 len = (p - start + 1);
7542 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7543 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7544 g_strlcpy ((char*)assembly->public_key_token, start, len);
7547 while (*p && *p != ',')
7551 while (g_ascii_isspace (*p) || *p == ',') {
7565 * mono_reflection_parse_type:
7568 * Parse a type name as accepted by the GetType () method and output the info
7569 * extracted in the info structure.
7570 * the name param will be mangled, so, make a copy before passing it to this function.
7571 * The fields in info will be valid until the memory pointed to by name is valid.
7573 * See also mono_type_get_name () below.
7575 * Returns: 0 on parse error.
7578 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7579 MonoTypeNameParse *info)
7581 char *start, *p, *w, *last_point, *startn;
7582 int in_modifiers = 0;
7583 int isbyref = 0, rank = 0, isptr = 0;
7585 start = p = w = name;
7587 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7588 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7589 info->name = info->name_space = NULL;
7590 info->nested = NULL;
7591 info->modifiers = NULL;
7592 info->type_arguments = NULL;
7594 /* last_point separates the namespace from the name */
7597 while (*p == ' ') p++, start++, w++, name++;
7602 *p = 0; /* NULL terminate the name */
7604 info->nested = g_list_append (info->nested, startn);
7605 /* we have parsed the nesting namespace + name */
7609 info->name_space = start;
7611 info->name = last_point + 1;
7613 info->name_space = (char *)"";
7641 info->name_space = start;
7643 info->name = last_point + 1;
7645 info->name_space = (char *)"";
7652 if (isbyref) /* only one level allowed by the spec */
7656 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7660 if (isbyref) /* pointer to ref not okay */
7662 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7667 if (isbyref) /* array of ref and generic ref are not okay */
7669 //Decide if it's an array of a generic argument list
7674 if (*p == ',' || *p == '*' || *p == ']') { //array
7682 else if (*p == '*') /* '*' means unknown lower bound */
7683 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7690 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7692 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7695 info->type_arguments = g_ptr_array_new ();
7697 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7698 gboolean fqname = FALSE;
7700 g_ptr_array_add (info->type_arguments, subinfo);
7702 while (*p == ' ') p++;
7708 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7711 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7712 if (fqname && (*p != ']')) {
7720 while (*p && (*p != ']'))
7728 if (g_ascii_isspace (*aname)) {
7735 !assembly_name_to_aname (&subinfo->assembly, aname))
7737 } else if (fqname && (*p == ']')) {
7759 if (g_ascii_isspace (*p)) {
7766 return 0; /* missing assembly name */
7767 if (!assembly_name_to_aname (&info->assembly, p))
7773 if (info->assembly.name)
7776 // *w = 0; /* terminate class name */
7778 if (!info->name || !*info->name)
7782 /* add other consistency checks */
7788 * mono_identifier_unescape_type_name_chars:
7789 * @identifier: the display name of a mono type
7792 * The name in internal form, that is without escaping backslashes.
7794 * The string is modified in place!
7797 mono_identifier_unescape_type_name_chars(char* identifier)
7802 for (w = r = identifier; *r != 0; r++)
7820 mono_identifier_unescape_info (MonoTypeNameParse* info);
7823 unescape_each_type_argument(void* data, void* user_data)
7825 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7826 mono_identifier_unescape_info (info);
7830 unescape_each_nested_name (void* data, void* user_data)
7832 char* nested_name = (char*) data;
7833 mono_identifier_unescape_type_name_chars(nested_name);
7837 * mono_identifier_unescape_info:
7839 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7843 * Destructively updates the info by unescaping the identifiers that
7844 * comprise the type namespace, name, nested types (if any) and
7845 * generic type arguments (if any).
7847 * The resulting info has the names in internal form.
7851 mono_identifier_unescape_info (MonoTypeNameParse *info)
7855 mono_identifier_unescape_type_name_chars(info->name_space);
7856 mono_identifier_unescape_type_name_chars(info->name);
7857 // but don't escape info->assembly
7858 if (info->type_arguments)
7859 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7861 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7865 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7867 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7869 mono_identifier_unescape_info (info);
7875 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7877 gboolean type_resolve = FALSE;
7879 MonoImage *rootimage = image;
7881 if (info->assembly.name) {
7882 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7883 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7885 * This could happen in the AOT compiler case when the search hook is not
7888 assembly = image->assembly;
7890 /* then we must load the assembly ourselve - see #60439 */
7891 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7895 image = assembly->image;
7896 } else if (!image) {
7897 image = mono_defaults.corlib;
7900 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7901 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7902 image = mono_defaults.corlib;
7903 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7910 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7916 gboolean bounded = FALSE;
7919 image = mono_defaults.corlib;
7922 rootimage = mono_defaults.corlib;
7926 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7927 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7929 klass = mono_class_from_name (image, info->name_space, info->name);
7933 for (mod = info->nested; mod; mod = mod->next) {
7934 gpointer iter = NULL;
7938 mono_class_init (parent);
7940 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7942 char *nested_name, *nested_nspace;
7943 gboolean match = TRUE;
7945 lastp = strrchr ((const char *)mod->data, '.');
7947 /* Nested classes can have namespaces */
7950 nested_name = g_strdup (lastp + 1);
7951 nspace_len = lastp - (char*)mod->data;
7952 nested_nspace = (char *)g_malloc (nspace_len + 1);
7953 memcpy (nested_nspace, mod->data, nspace_len);
7954 nested_nspace [nspace_len] = '\0';
7957 nested_name = (char *)mod->data;
7958 nested_nspace = NULL;
7961 if (nested_nspace) {
7963 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7966 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7972 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7975 if (strcmp (klass->name, nested_name) != 0)
7980 g_free (nested_name);
7981 g_free (nested_nspace);
7993 if (info->type_arguments) {
7994 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7995 MonoReflectionType *the_type;
7999 for (i = 0; i < info->type_arguments->len; i++) {
8000 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8002 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8003 if (!type_args [i]) {
8009 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8010 mono_error_raise_exception (&error); /* FIXME don't raise here */
8012 instance = mono_reflection_bind_generic_parameters (
8013 the_type, info->type_arguments->len, type_args);
8019 klass = mono_class_from_mono_type (instance);
8022 for (mod = info->modifiers; mod; mod = mod->next) {
8023 modval = GPOINTER_TO_UINT (mod->data);
8024 if (!modval) { /* byref: must be last modifier */
8025 return &klass->this_arg;
8026 } else if (modval == -1) {
8027 klass = mono_ptr_class_get (&klass->byval_arg);
8028 } else if (modval == -2) {
8030 } else { /* array rank */
8031 klass = mono_bounded_array_class_get (klass, modval, bounded);
8035 return &klass->byval_arg;
8039 * mono_reflection_get_type:
8040 * @image: a metadata context
8041 * @info: type description structure
8042 * @ignorecase: flag for case-insensitive string compares
8043 * @type_resolve: whenever type resolve was already tried
8045 * Build a MonoType from the type description in @info.
8050 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8051 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8055 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8057 MonoReflectionAssemblyBuilder *abuilder;
8061 g_assert (assembly_is_dynamic (assembly));
8062 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8064 /* Enumerate all modules */
8067 if (abuilder->modules) {
8068 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8069 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8070 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8076 if (!type && abuilder->loaded_modules) {
8077 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8078 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8079 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8089 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8092 MonoReflectionAssembly *assembly;
8096 if (image && image_is_dynamic (image))
8097 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8099 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8102 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8109 *type_resolve = TRUE;
8112 /* Reconstruct the type name */
8113 fullName = g_string_new ("");
8114 if (info->name_space && (info->name_space [0] != '\0'))
8115 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8117 g_string_printf (fullName, "%s", info->name);
8118 for (mod = info->nested; mod; mod = mod->next)
8119 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8121 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8123 if (assembly_is_dynamic (assembly->assembly))
8124 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8126 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8129 g_string_free (fullName, TRUE);
8134 mono_reflection_free_type_info (MonoTypeNameParse *info)
8136 g_list_free (info->modifiers);
8137 g_list_free (info->nested);
8139 if (info->type_arguments) {
8142 for (i = 0; i < info->type_arguments->len; i++) {
8143 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8145 mono_reflection_free_type_info (subinfo);
8146 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8150 g_ptr_array_free (info->type_arguments, TRUE);
8155 * mono_reflection_type_from_name:
8157 * @image: a metadata context (can be NULL).
8159 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8160 * it defaults to get the type from @image or, if @image is NULL or loading
8161 * from it fails, uses corlib.
8165 mono_reflection_type_from_name (char *name, MonoImage *image)
8167 MonoType *type = NULL;
8168 MonoTypeNameParse info;
8171 /* Make a copy since parse_type modifies its argument */
8172 tmp = g_strdup (name);
8174 /*g_print ("requested type %s\n", str);*/
8175 if (mono_reflection_parse_type (tmp, &info)) {
8176 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8180 mono_reflection_free_type_info (&info);
8185 * mono_reflection_get_token:
8187 * Return the metadata token of OBJ which should be an object
8188 * representing a metadata element.
8191 mono_reflection_get_token (MonoObject *obj)
8196 klass = obj->vtable->klass;
8198 if (strcmp (klass->name, "MethodBuilder") == 0) {
8199 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8201 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8202 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8203 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8205 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8206 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8207 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8209 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8210 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8211 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8212 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8213 } else if (strcmp (klass->name, "MonoType") == 0) {
8214 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8215 MonoClass *mc = mono_class_from_mono_type (type);
8216 if (!mono_class_init (mc))
8217 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8219 token = mc->type_token;
8220 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8221 strcmp (klass->name, "MonoMethod") == 0 ||
8222 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8223 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8224 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8225 if (m->method->is_inflated) {
8226 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8227 return inflated->declaring->token;
8229 token = m->method->token;
8231 } else if (strcmp (klass->name, "MonoField") == 0) {
8232 MonoReflectionField *f = (MonoReflectionField*)obj;
8234 if (is_field_on_inst (f->field)) {
8235 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8237 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8238 int field_index = f->field - dgclass->fields;
8241 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8242 obj = dgclass->field_objects [field_index];
8243 return mono_reflection_get_token (obj);
8246 token = mono_class_get_field_token (f->field);
8247 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8248 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8250 token = mono_class_get_property_token (p->property);
8251 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8252 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8254 token = mono_class_get_event_token (p->event);
8255 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8256 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8257 MonoClass *member_class = mono_object_class (p->MemberImpl);
8258 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8260 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8261 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8262 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8265 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8266 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8268 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8269 MonoException *ex = mono_get_exception_not_implemented (msg);
8271 mono_raise_exception (ex);
8278 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8282 int slen = mono_metadata_decode_value (p, &p);
8284 mono_error_init (error);
8286 n = (char *)g_memdup (p, slen + 1);
8288 t = mono_reflection_type_from_name (n, image);
8290 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8291 /* We don't free n, it's consumed by mono_error */
8292 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8298 return mono_class_from_mono_type (t);
8302 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8304 int slen, type = t->type;
8305 MonoClass *tklass = t->data.klass;
8307 mono_error_init (error);
8313 case MONO_TYPE_BOOLEAN: {
8314 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8319 case MONO_TYPE_CHAR:
8321 case MONO_TYPE_I2: {
8322 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8327 #if SIZEOF_VOID_P == 4
8333 case MONO_TYPE_I4: {
8334 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8339 #if SIZEOF_VOID_P == 8
8340 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8344 case MONO_TYPE_I8: {
8345 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8350 case MONO_TYPE_R8: {
8351 double *val = (double *)g_malloc (sizeof (double));
8356 case MONO_TYPE_VALUETYPE:
8357 if (t->data.klass->enumtype) {
8358 type = mono_class_enum_basetype (t->data.klass)->type;
8361 MonoClass *k = t->data.klass;
8363 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8364 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8370 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8373 case MONO_TYPE_STRING:
8374 if (*p == (char)0xFF) {
8378 slen = mono_metadata_decode_value (p, &p);
8380 return mono_string_new_len (mono_domain_get (), p, slen);
8381 case MONO_TYPE_CLASS: {
8382 MonoReflectionType *rt;
8385 if (*p == (char)0xFF) {
8390 slen = mono_metadata_decode_value (p, &p);
8391 n = (char *)g_memdup (p, slen + 1);
8393 t = mono_reflection_type_from_name (n, image);
8395 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8396 /* We don't free n, it's consumed by mono_error */
8397 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8403 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8404 if (!mono_error_ok (error))
8409 case MONO_TYPE_OBJECT: {
8412 MonoClass *subc = NULL;
8417 } else if (subt == 0x0E) {
8418 type = MONO_TYPE_STRING;
8420 } else if (subt == 0x1D) {
8421 MonoType simple_type = {{0}};
8425 type = MONO_TYPE_SZARRAY;
8426 if (etype == 0x50) {
8427 tklass = mono_defaults.systemtype_class;
8428 } else if (etype == 0x55) {
8429 tklass = load_cattr_enum_type (image, p, &p, error);
8430 if (!mono_error_ok (error))
8434 /* See Partition II, Appendix B3 */
8435 etype = MONO_TYPE_OBJECT;
8436 simple_type.type = (MonoTypeEnum)etype;
8437 tklass = mono_class_from_mono_type (&simple_type);
8440 } else if (subt == 0x55) {
8443 slen = mono_metadata_decode_value (p, &p);
8444 n = (char *)g_memdup (p, slen + 1);
8446 t = mono_reflection_type_from_name (n, image);
8448 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8449 /* We don't free n, it's consumed by mono_error */
8450 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8455 subc = mono_class_from_mono_type (t);
8456 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8457 MonoType simple_type = {{0}};
8458 simple_type.type = (MonoTypeEnum)subt;
8459 subc = mono_class_from_mono_type (&simple_type);
8461 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8463 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8465 if (mono_error_ok (error)) {
8466 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8467 g_assert (!subc->has_references);
8468 if (mono_error_ok (error))
8469 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8475 case MONO_TYPE_SZARRAY: {
8477 guint32 i, alen, basetype;
8480 if (alen == 0xffffffff) {
8484 arr = mono_array_new (mono_domain_get(), tklass, alen);
8485 basetype = tklass->byval_arg.type;
8486 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8487 basetype = mono_class_enum_basetype (tklass)->type;
8492 case MONO_TYPE_BOOLEAN:
8493 for (i = 0; i < alen; i++) {
8494 MonoBoolean val = *p++;
8495 mono_array_set (arr, MonoBoolean, i, val);
8498 case MONO_TYPE_CHAR:
8501 for (i = 0; i < alen; i++) {
8502 guint16 val = read16 (p);
8503 mono_array_set (arr, guint16, i, val);
8510 for (i = 0; i < alen; i++) {
8511 guint32 val = read32 (p);
8512 mono_array_set (arr, guint32, i, val);
8517 for (i = 0; i < alen; i++) {
8520 mono_array_set (arr, double, i, val);
8526 for (i = 0; i < alen; i++) {
8527 guint64 val = read64 (p);
8528 mono_array_set (arr, guint64, i, val);
8532 case MONO_TYPE_CLASS:
8533 case MONO_TYPE_OBJECT:
8534 case MONO_TYPE_STRING:
8535 case MONO_TYPE_SZARRAY:
8536 for (i = 0; i < alen; i++) {
8537 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8538 if (!mono_error_ok (error))
8540 mono_array_setref (arr, i, item);
8544 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8550 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8556 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8558 static MonoClass *klass;
8559 static MonoMethod *ctor;
8562 void *params [2], *unboxed;
8565 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8567 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8569 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8570 mono_error_raise_exception (&error); /* FIXME don't raise here */
8573 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8574 mono_error_raise_exception (&error); /* FIXME don't raise here */
8575 unboxed = mono_object_unbox (retval);
8576 mono_runtime_invoke (ctor, unboxed, params, NULL);
8582 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8584 static MonoClass *klass;
8585 static MonoMethod *ctor;
8588 void *unboxed, *params [2];
8591 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8593 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8596 params [1] = typedarg;
8597 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8598 mono_error_raise_exception (&error); /* FIXME don't raise here */
8599 unboxed = mono_object_unbox (retval);
8600 mono_runtime_invoke (ctor, unboxed, params, NULL);
8606 type_is_reference (MonoType *type)
8608 switch (type->type) {
8609 case MONO_TYPE_BOOLEAN:
8610 case MONO_TYPE_CHAR:
8623 case MONO_TYPE_VALUETYPE:
8631 free_param_data (MonoMethodSignature *sig, void **params) {
8633 for (i = 0; i < sig->param_count; ++i) {
8634 if (!type_is_reference (sig->params [i]))
8635 g_free (params [i]);
8640 * Find the field index in the metadata FieldDef table.
8643 find_field_index (MonoClass *klass, MonoClassField *field) {
8646 for (i = 0; i < klass->field.count; ++i) {
8647 if (field == &klass->fields [i])
8648 return klass->field.first + 1 + i;
8654 * Find the property index in the metadata Property table.
8657 find_property_index (MonoClass *klass, MonoProperty *property) {
8660 for (i = 0; i < klass->ext->property.count; ++i) {
8661 if (property == &klass->ext->properties [i])
8662 return klass->ext->property.first + 1 + i;
8668 * Find the event index in the metadata Event table.
8671 find_event_index (MonoClass *klass, MonoEvent *event) {
8674 for (i = 0; i < klass->ext->event.count; ++i) {
8675 if (event == &klass->ext->events [i])
8676 return klass->ext->event.first + 1 + i;
8682 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8684 const char *p = (const char*)data;
8686 guint32 i, j, num_named;
8688 void *params_buf [32];
8689 void **params = NULL;
8690 MonoMethodSignature *sig;
8691 MonoObject *exc = NULL;
8693 mono_error_init (error);
8695 mono_class_init (method->klass);
8697 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8698 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8703 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8704 if (!mono_error_ok (error)) return NULL;
8705 mono_runtime_invoke (method, attr, NULL, NULL);
8709 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8712 /*g_print ("got attr %s\n", method->klass->name);*/
8714 sig = mono_method_signature (method);
8715 if (sig->param_count < 32) {
8716 params = params_buf;
8717 memset (params, 0, sizeof (void*) * sig->param_count);
8719 /* Allocate using GC so it gets GC tracking */
8720 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8725 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8726 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8727 if (!mono_error_ok (error))
8732 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8733 if (!mono_error_ok (error)) goto fail;
8735 mono_runtime_invoke (method, attr, params, &exc);
8738 num_named = read16 (named);
8740 for (j = 0; j < num_named; j++) {
8742 char *name, named_type, data_type;
8743 named_type = *named++;
8744 data_type = *named++; /* type of data */
8745 if (data_type == MONO_TYPE_SZARRAY)
8746 data_type = *named++;
8747 if (data_type == MONO_TYPE_ENUM) {
8750 type_len = mono_metadata_decode_blob_size (named, &named);
8751 type_name = (char *)g_malloc (type_len + 1);
8752 memcpy (type_name, named, type_len);
8753 type_name [type_len] = 0;
8755 /* FIXME: lookup the type and check type consistency */
8758 name_len = mono_metadata_decode_blob_size (named, &named);
8759 name = (char *)g_malloc (name_len + 1);
8760 memcpy (name, named, name_len);
8761 name [name_len] = 0;
8763 if (named_type == 0x53) {
8764 MonoClassField *field;
8767 /* how this fail is a blackbox */
8768 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8770 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8775 val = load_cattr_value (image, field->type, named, &named, error);
8776 if (!mono_error_ok (error)) {
8778 if (!type_is_reference (field->type))
8783 mono_field_set_value (attr, field, val);
8784 if (!type_is_reference (field->type))
8786 } else if (named_type == 0x54) {
8789 MonoType *prop_type;
8791 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8794 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8800 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8805 /* can we have more that 1 arg in a custom attr named property? */
8806 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8807 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8809 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8810 if (!mono_error_ok (error)) {
8812 if (!type_is_reference (prop_type))
8813 g_free (pparams [0]);
8818 mono_property_set_value (prop, attr, pparams, NULL);
8819 if (!type_is_reference (prop_type))
8820 g_free (pparams [0]);
8825 free_param_data (method->signature, params);
8826 if (params != params_buf)
8827 mono_gc_free_fixed (params);
8832 free_param_data (method->signature, params);
8833 if (params != params_buf)
8834 mono_gc_free_fixed (params);
8836 mono_raise_exception ((MonoException*)exc);
8841 * mono_reflection_create_custom_attr_data_args:
8843 * Create an array of typed and named arguments from the cattr blob given by DATA.
8844 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8845 * NAMED_ARG_INFO will contain information about the named arguments.
8848 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)
8850 MonoArray *typedargs, *namedargs;
8851 MonoClass *attrklass;
8853 const char *p = (const char*)data;
8855 guint32 i, j, num_named;
8856 CattrNamedArg *arginfo = NULL;
8860 *named_arg_info = NULL;
8862 mono_error_init (error);
8864 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8865 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8869 mono_class_init (method->klass);
8871 domain = mono_domain_get ();
8873 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8876 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8880 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8884 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8885 if (!mono_error_ok (error)) {
8886 if (!type_is_reference (mono_method_signature (method)->params [i]))
8891 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8892 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8893 mono_array_setref (typedargs, i, obj);
8895 if (!type_is_reference (mono_method_signature (method)->params [i]))
8900 num_named = read16 (named);
8901 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8903 attrklass = method->klass;
8905 arginfo = g_new0 (CattrNamedArg, num_named);
8906 *named_arg_info = arginfo;
8908 for (j = 0; j < num_named; j++) {
8910 char *name, named_type, data_type;
8911 named_type = *named++;
8912 data_type = *named++; /* type of data */
8913 if (data_type == MONO_TYPE_SZARRAY)
8914 data_type = *named++;
8915 if (data_type == MONO_TYPE_ENUM) {
8918 type_len = mono_metadata_decode_blob_size (named, &named);
8919 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8922 type_name = (char *)g_malloc (type_len + 1);
8923 memcpy (type_name, named, type_len);
8924 type_name [type_len] = 0;
8926 /* FIXME: lookup the type and check type consistency */
8929 name_len = mono_metadata_decode_blob_size (named, &named);
8930 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8932 name = (char *)g_malloc (name_len + 1);
8933 memcpy (name, named, name_len);
8934 name [name_len] = 0;
8936 if (named_type == 0x53) {
8938 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8946 arginfo [j].type = field->type;
8947 arginfo [j].field = field;
8949 val = load_cattr_value (image, field->type, named, &named, error);
8950 if (!mono_error_ok (error)) {
8951 if (!type_is_reference (field->type))
8957 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8958 mono_array_setref (namedargs, j, obj);
8959 if (!type_is_reference (field->type))
8961 } else if (named_type == 0x54) {
8963 MonoType *prop_type;
8964 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8967 if (!prop || !prop->set) {
8972 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8973 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8975 arginfo [j].type = prop_type;
8976 arginfo [j].prop = prop;
8978 val = load_cattr_value (image, prop_type, named, &named, error);
8979 if (!mono_error_ok (error)) {
8980 if (!type_is_reference (prop_type))
8986 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8987 mono_array_setref (namedargs, j, obj);
8988 if (!type_is_reference (prop_type))
8994 *typed_args = typedargs;
8995 *named_args = namedargs;
8998 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9000 *named_arg_info = NULL;
9004 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9007 MonoArray *typedargs, *namedargs;
9010 CattrNamedArg *arginfo = NULL;
9020 image = assembly->assembly->image;
9021 method = ref_method->method;
9022 domain = mono_object_domain (ref_method);
9024 if (!mono_class_init (method->klass))
9025 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9027 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9028 if (!mono_error_ok (&error))
9029 mono_error_raise_exception (&error);
9030 if (mono_loader_get_last_error ())
9031 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
9033 if (!typedargs || !namedargs) {
9038 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9039 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9040 MonoObject *typedarg;
9042 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9043 mono_array_setref (typedargs, i, typedarg);
9046 for (i = 0; i < mono_array_length (namedargs); ++i) {
9047 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9048 MonoObject *typedarg, *namedarg, *minfo;
9050 if (arginfo [i].prop)
9051 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9053 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
9055 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9056 namedarg = create_cattr_named_arg (minfo, typedarg);
9058 mono_array_setref (namedargs, i, namedarg);
9061 *ctor_args = typedargs;
9062 *named_args = namedargs;
9067 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9069 static MonoMethod *ctor;
9075 g_assert (image->assembly);
9078 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9080 domain = mono_domain_get ();
9081 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9082 mono_error_raise_exception (&error); /* FIXME don't raise here */
9083 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
9084 params [1] = mono_assembly_get_object (domain, image->assembly);
9085 params [2] = (gpointer)&cattr->data;
9086 params [3] = &cattr->data_size;
9087 mono_runtime_invoke (ctor, attr, params, NULL);
9092 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9098 mono_error_init (error);
9101 for (i = 0; i < cinfo->num_attrs; ++i) {
9102 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9106 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9108 for (i = 0; i < cinfo->num_attrs; ++i) {
9109 if (!cinfo->attrs [i].ctor)
9110 /* The cattr type is not finished yet */
9111 /* We should include the type name but cinfo doesn't contain it */
9112 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9113 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9114 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9115 if (!mono_error_ok (error))
9117 mono_array_setref (result, n, attr);
9125 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9128 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9129 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9135 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9141 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9142 for (i = 0; i < cinfo->num_attrs; ++i) {
9143 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9144 mono_array_setref (result, i, attr);
9150 * mono_custom_attrs_from_index:
9152 * Returns: NULL if no attributes are found or if a loading error occurs.
9155 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9157 guint32 mtoken, i, len;
9158 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9160 MonoCustomAttrInfo *ainfo;
9161 GList *tmp, *list = NULL;
9163 MonoCustomAttrEntry* attr;
9165 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9167 i = mono_metadata_custom_attrs_from_index (image, idx);
9171 while (i < ca->rows) {
9172 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9174 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9177 len = g_list_length (list);
9180 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9181 ainfo->num_attrs = len;
9182 ainfo->image = image;
9183 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9185 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9186 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9187 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9188 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9189 mtoken |= MONO_TOKEN_METHOD_DEF;
9191 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9192 mtoken |= MONO_TOKEN_MEMBER_REF;
9195 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9198 attr = &ainfo->attrs [i - 1];
9199 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9201 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9202 mono_loader_set_error_from_mono_error (&error);
9208 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9209 /*FIXME raising an exception here doesn't make any sense*/
9210 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9215 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9216 attr->data_size = mono_metadata_decode_value (data, &data);
9217 attr->data = (guchar*)data;
9225 mono_custom_attrs_from_method (MonoMethod *method)
9230 * An instantiated method has the same cattrs as the generic method definition.
9232 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9233 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9235 if (method->is_inflated)
9236 method = ((MonoMethodInflated *) method)->declaring;
9238 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9239 return lookup_custom_attr (method->klass->image, method);
9242 /* Synthetic methods */
9245 idx = mono_method_get_index (method);
9246 idx <<= MONO_CUSTOM_ATTR_BITS;
9247 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9248 return mono_custom_attrs_from_index (method->klass->image, idx);
9252 mono_custom_attrs_from_class (MonoClass *klass)
9256 if (klass->generic_class)
9257 klass = klass->generic_class->container_class;
9259 if (image_is_dynamic (klass->image))
9260 return lookup_custom_attr (klass->image, klass);
9262 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9263 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9264 idx <<= MONO_CUSTOM_ATTR_BITS;
9265 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9267 idx = mono_metadata_token_index (klass->type_token);
9268 idx <<= MONO_CUSTOM_ATTR_BITS;
9269 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9271 return mono_custom_attrs_from_index (klass->image, idx);
9275 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9279 if (image_is_dynamic (assembly->image))
9280 return lookup_custom_attr (assembly->image, assembly);
9281 idx = 1; /* there is only one assembly */
9282 idx <<= MONO_CUSTOM_ATTR_BITS;
9283 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9284 return mono_custom_attrs_from_index (assembly->image, idx);
9287 static MonoCustomAttrInfo*
9288 mono_custom_attrs_from_module (MonoImage *image)
9292 if (image_is_dynamic (image))
9293 return lookup_custom_attr (image, image);
9294 idx = 1; /* there is only one module */
9295 idx <<= MONO_CUSTOM_ATTR_BITS;
9296 idx |= MONO_CUSTOM_ATTR_MODULE;
9297 return mono_custom_attrs_from_index (image, idx);
9301 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9305 if (image_is_dynamic (klass->image)) {
9306 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9307 return lookup_custom_attr (klass->image, property);
9309 idx = find_property_index (klass, property);
9310 idx <<= MONO_CUSTOM_ATTR_BITS;
9311 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9312 return mono_custom_attrs_from_index (klass->image, idx);
9316 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9320 if (image_is_dynamic (klass->image)) {
9321 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9322 return lookup_custom_attr (klass->image, event);
9324 idx = find_event_index (klass, event);
9325 idx <<= MONO_CUSTOM_ATTR_BITS;
9326 idx |= MONO_CUSTOM_ATTR_EVENT;
9327 return mono_custom_attrs_from_index (klass->image, idx);
9331 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9334 if (image_is_dynamic (klass->image)) {
9335 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9336 return lookup_custom_attr (klass->image, field);
9338 idx = find_field_index (klass, field);
9339 idx <<= MONO_CUSTOM_ATTR_BITS;
9340 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9341 return mono_custom_attrs_from_index (klass->image, idx);
9345 * mono_custom_attrs_from_param:
9346 * @method: handle to the method that we want to retrieve custom parameter information from
9347 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9349 * The result must be released with mono_custom_attrs_free().
9351 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9354 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9357 guint32 i, idx, method_index;
9358 guint32 param_list, param_last, param_pos, found;
9360 MonoReflectionMethodAux *aux;
9363 * An instantiated method has the same cattrs as the generic method definition.
9365 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9366 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9368 if (method->is_inflated)
9369 method = ((MonoMethodInflated *) method)->declaring;
9371 if (image_is_dynamic (method->klass->image)) {
9372 MonoCustomAttrInfo *res, *ainfo;
9375 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9376 if (!aux || !aux->param_cattr)
9379 /* Need to copy since it will be freed later */
9380 ainfo = aux->param_cattr [param];
9383 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9384 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9385 memcpy (res, ainfo, size);
9389 image = method->klass->image;
9390 method_index = mono_method_get_index (method);
9393 ca = &image->tables [MONO_TABLE_METHOD];
9395 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9396 if (method_index == ca->rows) {
9397 ca = &image->tables [MONO_TABLE_PARAM];
9398 param_last = ca->rows + 1;
9400 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9401 ca = &image->tables [MONO_TABLE_PARAM];
9404 for (i = param_list; i < param_last; ++i) {
9405 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9406 if (param_pos == param) {
9414 idx <<= MONO_CUSTOM_ATTR_BITS;
9415 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9416 return mono_custom_attrs_from_index (image, idx);
9420 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9424 for (i = 0; i < ainfo->num_attrs; ++i) {
9425 klass = ainfo->attrs [i].ctor->klass;
9426 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9433 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9436 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9437 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9442 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9448 mono_error_init (error);
9451 for (i = 0; i < ainfo->num_attrs; ++i) {
9452 klass = ainfo->attrs [i].ctor->klass;
9453 if (mono_class_has_parent (klass, attr_klass)) {
9458 if (attr_index == -1)
9461 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9462 if (!mono_error_ok (error))
9464 return mono_array_get (attrs, MonoObject*, attr_index);
9468 * mono_reflection_get_custom_attrs_info:
9469 * @obj: a reflection object handle
9471 * Return the custom attribute info for attributes defined for the
9472 * reflection handle @obj. The objects.
9474 * FIXME this function leaks like a sieve for SRE objects.
9477 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9480 MonoCustomAttrInfo *cinfo = NULL;
9482 klass = obj->vtable->klass;
9483 if (klass == mono_defaults.monotype_class) {
9484 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9485 klass = mono_class_from_mono_type (type);
9486 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9487 cinfo = mono_custom_attrs_from_class (klass);
9488 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9489 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9490 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9491 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9492 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9493 cinfo = mono_custom_attrs_from_module (module->image);
9494 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9495 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9496 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9497 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9498 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9499 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9500 } else if (strcmp ("MonoField", klass->name) == 0) {
9501 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9502 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9503 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9504 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9505 cinfo = mono_custom_attrs_from_method (rmethod->method);
9506 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9507 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9508 cinfo = mono_custom_attrs_from_method (rmethod->method);
9509 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9510 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9511 MonoClass *member_class = mono_object_class (param->MemberImpl);
9512 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9513 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9514 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9515 } else if (is_sr_mono_property (member_class)) {
9516 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9518 if (!(method = prop->property->get))
9519 method = prop->property->set;
9522 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9524 #ifndef DISABLE_REFLECTION_EMIT
9525 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9526 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9527 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9528 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9529 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9530 MonoMethod *method = NULL;
9531 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9532 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9533 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9534 method = ((MonoReflectionMethod *)c->cb)->method;
9536 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));
9538 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9542 char *type_name = mono_type_get_full_name (member_class);
9543 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9544 MonoException *ex = mono_get_exception_not_supported (msg);
9547 mono_raise_exception (ex);
9549 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9550 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9551 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9552 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9553 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9554 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9555 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9556 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9557 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9558 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9559 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9560 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9561 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9562 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9563 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9564 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9565 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9566 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9567 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9568 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9569 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9570 } else { /* handle other types here... */
9571 g_error ("get custom attrs not yet supported for %s", klass->name);
9578 * mono_reflection_get_custom_attrs_by_type:
9579 * @obj: a reflection object handle
9581 * Return an array with all the custom attributes defined of the
9582 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9583 * of that type are returned. The objects are fully build. Return NULL if a loading error
9587 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9590 MonoCustomAttrInfo *cinfo;
9592 mono_error_init (error);
9594 cinfo = mono_reflection_get_custom_attrs_info (obj);
9596 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9598 mono_custom_attrs_free (cinfo);
9600 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9601 if (mono_loader_get_last_error ())
9603 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9610 * mono_reflection_get_custom_attrs:
9611 * @obj: a reflection object handle
9613 * Return an array with all the custom attributes defined of the
9614 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9618 mono_reflection_get_custom_attrs (MonoObject *obj)
9622 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9626 * mono_reflection_get_custom_attrs_data:
9627 * @obj: a reflection obj handle
9629 * Returns an array of System.Reflection.CustomAttributeData,
9630 * which include information about attributes reflected on
9631 * types loaded using the Reflection Only methods
9634 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9637 MonoCustomAttrInfo *cinfo;
9639 cinfo = mono_reflection_get_custom_attrs_info (obj);
9641 result = mono_custom_attrs_data_construct (cinfo);
9643 mono_custom_attrs_free (cinfo);
9645 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9650 static MonoReflectionType*
9651 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9653 static MonoMethod *method_get_underlying_system_type = NULL;
9654 MonoMethod *usertype_method;
9656 if (!method_get_underlying_system_type)
9657 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9658 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9659 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9664 is_corlib_type (MonoClass *klass)
9666 return klass->image == mono_defaults.corlib;
9669 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9670 static MonoClass *cached_class; \
9672 return cached_class == _class; \
9673 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9674 cached_class = _class; \
9681 #ifndef DISABLE_REFLECTION_EMIT
9683 is_sre_array (MonoClass *klass)
9685 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9689 is_sre_byref (MonoClass *klass)
9691 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9695 is_sre_pointer (MonoClass *klass)
9697 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9701 is_sre_generic_instance (MonoClass *klass)
9703 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9707 is_sre_type_builder (MonoClass *klass)
9709 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9713 is_sre_method_builder (MonoClass *klass)
9715 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9719 is_sre_ctor_builder (MonoClass *klass)
9721 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9725 is_sre_field_builder (MonoClass *klass)
9727 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9731 is_sre_method_on_tb_inst (MonoClass *klass)
9733 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9737 is_sre_ctor_on_tb_inst (MonoClass *klass)
9739 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9743 mono_reflection_type_get_handle (MonoReflectionType* ref)
9751 if (is_usertype (ref)) {
9752 ref = mono_reflection_type_get_underlying_system_type (ref);
9753 if (ref == NULL || is_usertype (ref))
9759 klass = mono_object_class (ref);
9761 if (is_sre_array (klass)) {
9763 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9764 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9766 if (sre_array->rank == 0) //single dimentional array
9767 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9769 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9770 sre_array->type.type = res;
9772 } else if (is_sre_byref (klass)) {
9774 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9775 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9777 res = &mono_class_from_mono_type (base)->this_arg;
9778 sre_byref->type.type = res;
9780 } else if (is_sre_pointer (klass)) {
9782 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9783 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9785 res = &mono_ptr_class_get (base)->byval_arg;
9786 sre_pointer->type.type = res;
9788 } else if (is_sre_generic_instance (klass)) {
9789 MonoType *res, **types;
9790 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9793 count = mono_array_length (gclass->type_arguments);
9794 types = g_new0 (MonoType*, count);
9795 for (i = 0; i < count; ++i) {
9796 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9797 types [i] = mono_reflection_type_get_handle (t);
9804 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9807 gclass->type.type = res;
9811 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9818 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9820 mono_reflection_type_get_handle (type);
9824 mono_reflection_register_with_runtime (MonoReflectionType *type)
9826 MonoType *res = mono_reflection_type_get_handle (type);
9827 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9831 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9833 klass = mono_class_from_mono_type (res);
9835 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9836 mono_domain_lock (domain);
9838 if (!image_is_dynamic (klass->image)) {
9839 mono_class_setup_supertypes (klass);
9841 if (!domain->type_hash)
9842 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9843 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9844 mono_g_hash_table_insert (domain->type_hash, res, type);
9846 mono_domain_unlock (domain);
9847 mono_loader_unlock ();
9851 * LOCKING: Assumes the loader lock is held.
9853 static MonoMethodSignature*
9854 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9855 MonoMethodSignature *sig;
9858 count = parameters? mono_array_length (parameters): 0;
9860 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9861 sig->param_count = count;
9862 sig->sentinelpos = -1; /* FIXME */
9863 for (i = 0; i < count; ++i)
9864 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9869 * LOCKING: Assumes the loader lock is held.
9871 static MonoMethodSignature*
9872 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9873 MonoMethodSignature *sig;
9875 sig = parameters_to_signature (image, ctor->parameters);
9876 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9877 sig->ret = &mono_defaults.void_class->byval_arg;
9882 * LOCKING: Assumes the loader lock is held.
9884 static MonoMethodSignature*
9885 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9886 MonoMethodSignature *sig;
9888 sig = parameters_to_signature (image, method->parameters);
9889 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9890 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9891 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9895 static MonoMethodSignature*
9896 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9897 MonoMethodSignature *sig;
9899 sig = parameters_to_signature (NULL, method->parameters);
9900 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9901 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9902 sig->generic_param_count = 0;
9907 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9909 MonoClass *klass = mono_object_class (prop);
9910 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9911 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9912 *name = mono_string_to_utf8 (pb->name);
9913 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9915 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9916 *name = g_strdup (p->property->name);
9917 if (p->property->get)
9918 *type = mono_method_signature (p->property->get)->ret;
9920 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9925 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9927 MonoClass *klass = mono_object_class (field);
9928 if (strcmp (klass->name, "FieldBuilder") == 0) {
9929 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9930 *name = mono_string_to_utf8 (fb->name);
9931 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9933 MonoReflectionField *f = (MonoReflectionField *)field;
9934 *name = g_strdup (mono_field_get_name (f->field));
9935 *type = f->field->type;
9939 #else /* DISABLE_REFLECTION_EMIT */
9942 mono_reflection_register_with_runtime (MonoReflectionType *type)
9948 is_sre_type_builder (MonoClass *klass)
9954 is_sre_generic_instance (MonoClass *klass)
9960 init_type_builder_generics (MonoObject *type)
9964 #endif /* !DISABLE_REFLECTION_EMIT */
9968 is_sr_mono_field (MonoClass *klass)
9970 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9974 is_sr_mono_property (MonoClass *klass)
9976 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9980 is_sr_mono_method (MonoClass *klass)
9982 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9986 is_sr_mono_cmethod (MonoClass *klass)
9988 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9992 is_sr_mono_generic_method (MonoClass *klass)
9994 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9998 is_sr_mono_generic_cmethod (MonoClass *klass)
10000 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10004 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10006 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10010 is_usertype (MonoReflectionType *ref)
10012 MonoClass *klass = mono_object_class (ref);
10013 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10016 static MonoReflectionType*
10017 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10019 mono_error_init (error);
10020 if (!type || type->type)
10023 if (is_usertype (type)) {
10024 type = mono_reflection_type_get_underlying_system_type (type);
10025 if (is_usertype (type)) {
10026 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10034 * Encode a value in a custom attribute stream of bytes.
10035 * The value to encode is either supplied as an object in argument val
10036 * (valuetypes are boxed), or as a pointer to the data in the
10038 * @type represents the type of the value
10039 * @buffer is the start of the buffer
10040 * @p the current position in the buffer
10041 * @buflen contains the size of the buffer and is used to return the new buffer size
10042 * if this needs to be realloced.
10043 * @retbuffer and @retp return the start and the position of the buffer
10046 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10048 MonoTypeEnum simple_type;
10050 if ((p-buffer) + 10 >= *buflen) {
10053 newbuf = (char *)g_realloc (buffer, *buflen);
10054 p = newbuf + (p-buffer);
10058 argval = ((char*)arg + sizeof (MonoObject));
10059 simple_type = type->type;
10061 switch (simple_type) {
10062 case MONO_TYPE_BOOLEAN:
10067 case MONO_TYPE_CHAR:
10070 swap_with_size (p, argval, 2, 1);
10076 swap_with_size (p, argval, 4, 1);
10080 swap_with_size (p, argval, 8, 1);
10085 swap_with_size (p, argval, 8, 1);
10088 case MONO_TYPE_VALUETYPE:
10089 if (type->data.klass->enumtype) {
10090 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10093 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10096 case MONO_TYPE_STRING: {
10103 str = mono_string_to_utf8 ((MonoString*)arg);
10104 slen = strlen (str);
10105 if ((p-buffer) + 10 + slen >= *buflen) {
10109 newbuf = (char *)g_realloc (buffer, *buflen);
10110 p = newbuf + (p-buffer);
10113 mono_metadata_encode_value (slen, p, &p);
10114 memcpy (p, str, slen);
10119 case MONO_TYPE_CLASS: {
10127 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10128 slen = strlen (str);
10129 if ((p-buffer) + 10 + slen >= *buflen) {
10133 newbuf = (char *)g_realloc (buffer, *buflen);
10134 p = newbuf + (p-buffer);
10137 mono_metadata_encode_value (slen, p, &p);
10138 memcpy (p, str, slen);
10143 case MONO_TYPE_SZARRAY: {
10145 MonoClass *eclass, *arg_eclass;
10148 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10151 len = mono_array_length ((MonoArray*)arg);
10153 *p++ = (len >> 8) & 0xff;
10154 *p++ = (len >> 16) & 0xff;
10155 *p++ = (len >> 24) & 0xff;
10157 *retbuffer = buffer;
10158 eclass = type->data.klass;
10159 arg_eclass = mono_object_class (arg)->element_class;
10162 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10163 eclass = mono_defaults.object_class;
10165 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10166 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10167 int elsize = mono_class_array_element_size (arg_eclass);
10168 for (i = 0; i < len; ++i) {
10169 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10172 } else if (eclass->valuetype && arg_eclass->valuetype) {
10173 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10174 int elsize = mono_class_array_element_size (eclass);
10175 for (i = 0; i < len; ++i) {
10176 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10180 for (i = 0; i < len; ++i) {
10181 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10186 case MONO_TYPE_OBJECT: {
10192 * The parameter type is 'object' but the type of the actual
10193 * argument is not. So we have to add type information to the blob
10194 * too. This is completely undocumented in the spec.
10198 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10203 klass = mono_object_class (arg);
10205 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10208 } else if (klass->enumtype) {
10210 } else if (klass == mono_defaults.string_class) {
10211 simple_type = MONO_TYPE_STRING;
10214 } else if (klass->rank == 1) {
10216 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10217 /* See Partition II, Appendix B3 */
10220 *p++ = klass->element_class->byval_arg.type;
10221 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10223 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10224 *p++ = simple_type = klass->byval_arg.type;
10227 g_error ("unhandled type in custom attr");
10229 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10230 slen = strlen (str);
10231 if ((p-buffer) + 10 + slen >= *buflen) {
10235 newbuf = (char *)g_realloc (buffer, *buflen);
10236 p = newbuf + (p-buffer);
10239 mono_metadata_encode_value (slen, p, &p);
10240 memcpy (p, str, slen);
10243 simple_type = mono_class_enum_basetype (klass)->type;
10247 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10250 *retbuffer = buffer;
10254 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10256 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10257 char *str = type_get_qualified_name (type, NULL);
10258 int slen = strlen (str);
10262 * This seems to be optional...
10265 mono_metadata_encode_value (slen, p, &p);
10266 memcpy (p, str, slen);
10269 } else if (type->type == MONO_TYPE_OBJECT) {
10271 } else if (type->type == MONO_TYPE_CLASS) {
10272 /* it should be a type: encode_cattr_value () has the check */
10275 mono_metadata_encode_value (type->type, p, &p);
10276 if (type->type == MONO_TYPE_SZARRAY)
10277 /* See the examples in Partition VI, Annex B */
10278 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10284 #ifndef DISABLE_REFLECTION_EMIT
10286 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10289 /* Preallocate a large enough buffer */
10290 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10291 char *str = type_get_qualified_name (type, NULL);
10292 len = strlen (str);
10294 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10295 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10296 len = strlen (str);
10301 len += strlen (name);
10303 if ((p-buffer) + 20 + len >= *buflen) {
10307 newbuf = (char *)g_realloc (buffer, *buflen);
10308 p = newbuf + (p-buffer);
10312 encode_field_or_prop_type (type, p, &p);
10314 len = strlen (name);
10315 mono_metadata_encode_value (len, p, &p);
10316 memcpy (p, name, len);
10318 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10320 *retbuffer = buffer;
10324 * mono_reflection_get_custom_attrs_blob:
10325 * @ctor: custom attribute constructor
10326 * @ctorArgs: arguments o the constructor
10332 * Creates the blob of data that needs to be saved in the metadata and that represents
10333 * the custom attributed described by @ctor, @ctorArgs etc.
10334 * Returns: a Byte array representing the blob of data.
10337 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10340 MonoMethodSignature *sig;
10345 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10346 /* sig is freed later so allocate it in the heap */
10347 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10349 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10352 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10354 p = buffer = (char *)g_malloc (buflen);
10355 /* write the prolog */
10358 for (i = 0; i < sig->param_count; ++i) {
10359 arg = mono_array_get (ctorArgs, MonoObject*, i);
10360 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10364 i += mono_array_length (properties);
10366 i += mono_array_length (fields);
10368 *p++ = (i >> 8) & 0xff;
10371 for (i = 0; i < mono_array_length (properties); ++i) {
10375 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10376 get_prop_name_and_type (prop, &pname, &ptype);
10377 *p++ = 0x54; /* PROPERTY signature */
10378 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10385 for (i = 0; i < mono_array_length (fields); ++i) {
10389 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10390 get_field_name_and_type (field, &fname, &ftype);
10391 *p++ = 0x53; /* FIELD signature */
10392 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10397 g_assert (p - buffer <= buflen);
10398 buflen = p - buffer;
10399 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10400 p = mono_array_addr (result, char, 0);
10401 memcpy (p, buffer, buflen);
10403 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10409 * mono_reflection_setup_internal_class:
10410 * @tb: a TypeBuilder object
10412 * Creates a MonoClass that represents the TypeBuilder.
10413 * This is a trick that lets us simplify a lot of reflection code
10414 * (and will allow us to support Build and Run assemblies easier).
10417 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10420 MonoClass *klass, *parent;
10422 RESOLVE_TYPE (tb->parent, &error);
10423 mono_error_raise_exception (&error); /* FIXME don't raise here */
10425 mono_loader_lock ();
10428 /* check so we can compile corlib correctly */
10429 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10430 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10431 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10433 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10439 /* the type has already being created: it means we just have to change the parent */
10440 if (tb->type.type) {
10441 klass = mono_class_from_mono_type (tb->type.type);
10442 klass->parent = NULL;
10443 /* fool mono_class_setup_parent */
10444 klass->supertypes = NULL;
10445 mono_class_setup_parent (klass, parent);
10446 mono_class_setup_mono_type (klass);
10447 mono_loader_unlock ();
10451 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10453 klass->image = &tb->module->dynamic_image->image;
10455 klass->inited = 1; /* we lie to the runtime */
10456 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10457 if (!mono_error_ok (&error))
10459 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10460 if (!mono_error_ok (&error))
10462 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10463 klass->flags = tb->attrs;
10465 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10467 klass->element_class = klass;
10469 if (mono_class_get_ref_info (klass) == NULL) {
10471 mono_class_set_ref_info (klass, tb);
10473 /* Put into cache so mono_class_get_checked () will find it.
10474 Skip nested types as those should not be available on the global scope. */
10475 if (!tb->nesting_type)
10476 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10479 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10480 by performing a mono_class_get which does the full resolution.
10482 Working around this semantics would require us to write a lot of code for no clear advantage.
10484 mono_image_append_class_to_reflection_info_set (klass);
10486 g_assert (mono_class_get_ref_info (klass) == tb);
10489 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10491 if (parent != NULL) {
10492 mono_class_setup_parent (klass, parent);
10493 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10494 const char *old_n = klass->name;
10495 /* trick to get relative numbering right when compiling corlib */
10496 klass->name = "BuildingObject";
10497 mono_class_setup_parent (klass, mono_defaults.object_class);
10498 klass->name = old_n;
10501 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10502 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10503 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10504 klass->instance_size = sizeof (MonoObject);
10505 klass->size_inited = 1;
10506 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10509 mono_class_setup_mono_type (klass);
10511 mono_class_setup_supertypes (klass);
10514 * FIXME: handle interfaces.
10517 tb->type.type = &klass->byval_arg;
10519 if (tb->nesting_type) {
10520 g_assert (tb->nesting_type->type);
10521 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10524 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10526 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10528 mono_loader_unlock ();
10532 mono_loader_unlock ();
10533 mono_error_raise_exception (&error);
10537 * mono_reflection_setup_generic_class:
10538 * @tb: a TypeBuilder object
10540 * Setup the generic class before adding the first generic parameter.
10543 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10548 * mono_reflection_create_generic_class:
10549 * @tb: a TypeBuilder object
10551 * Creates the generic class after all generic parameters have been added.
10554 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10559 klass = mono_class_from_mono_type (tb->type.type);
10561 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10563 if (klass->generic_container || (count == 0))
10566 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10568 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10570 klass->generic_container->owner.klass = klass;
10571 klass->generic_container->type_argc = count;
10572 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10574 klass->is_generic = 1;
10576 for (i = 0; i < count; i++) {
10577 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10578 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10579 klass->generic_container->type_params [i] = *param;
10580 /*Make sure we are a diferent type instance */
10581 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10582 klass->generic_container->type_params [i].info.pklass = NULL;
10583 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10585 g_assert (klass->generic_container->type_params [i].param.owner);
10588 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10592 * mono_reflection_create_internal_class:
10593 * @tb: a TypeBuilder object
10595 * Actually create the MonoClass that is associated with the TypeBuilder.
10598 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10602 klass = mono_class_from_mono_type (tb->type.type);
10604 mono_loader_lock ();
10605 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10606 MonoReflectionFieldBuilder *fb;
10608 MonoType *enum_basetype;
10610 g_assert (tb->fields != NULL);
10611 g_assert (mono_array_length (tb->fields) >= 1);
10613 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10615 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10616 mono_loader_unlock ();
10620 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10621 klass->element_class = mono_class_from_mono_type (enum_basetype);
10622 if (!klass->element_class)
10623 klass->element_class = mono_class_from_mono_type (enum_basetype);
10626 * get the element_class from the current corlib.
10628 ec = default_class_from_mono_type (enum_basetype);
10629 klass->instance_size = ec->instance_size;
10630 klass->size_inited = 1;
10632 * this is almost safe to do with enums and it's needed to be able
10633 * to create objects of the enum type (for use in SetConstant).
10635 /* FIXME: Does this mean enums can't have method overrides ? */
10636 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10638 mono_loader_unlock ();
10641 static MonoMarshalSpec*
10642 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10643 MonoReflectionMarshal *minfo)
10645 MonoMarshalSpec *res;
10647 res = image_g_new0 (image, MonoMarshalSpec, 1);
10648 res->native = (MonoMarshalNative)minfo->type;
10650 switch (minfo->type) {
10651 case MONO_NATIVE_LPARRAY:
10652 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10653 if (minfo->has_size) {
10654 res->data.array_data.param_num = minfo->param_num;
10655 res->data.array_data.num_elem = minfo->count;
10656 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10659 res->data.array_data.param_num = -1;
10660 res->data.array_data.num_elem = -1;
10661 res->data.array_data.elem_mult = -1;
10665 case MONO_NATIVE_BYVALTSTR:
10666 case MONO_NATIVE_BYVALARRAY:
10667 res->data.array_data.num_elem = minfo->count;
10670 case MONO_NATIVE_CUSTOM:
10671 if (minfo->marshaltyperef)
10672 res->data.custom_data.custom_name =
10673 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10674 if (minfo->mcookie)
10675 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10684 #endif /* !DISABLE_REFLECTION_EMIT */
10686 MonoReflectionMarshalAsAttribute*
10687 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10688 MonoMarshalSpec *spec)
10690 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10692 MonoReflectionType *rt;
10693 MonoReflectionMarshalAsAttribute *minfo;
10696 if (!System_Reflection_Emit_MarshalAsAttribute) {
10697 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10698 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10699 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10702 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10703 mono_error_raise_exception (&error); /* FIXME don't raise here */
10704 minfo->utype = spec->native;
10706 switch (minfo->utype) {
10707 case MONO_NATIVE_LPARRAY:
10708 minfo->array_subtype = spec->data.array_data.elem_type;
10709 minfo->size_const = spec->data.array_data.num_elem;
10710 if (spec->data.array_data.param_num != -1)
10711 minfo->size_param_index = spec->data.array_data.param_num;
10714 case MONO_NATIVE_BYVALTSTR:
10715 case MONO_NATIVE_BYVALARRAY:
10716 minfo->size_const = spec->data.array_data.num_elem;
10719 case MONO_NATIVE_CUSTOM:
10720 if (spec->data.custom_data.custom_name) {
10721 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10723 rt = mono_type_get_object_checked (domain, mtype, &error);
10724 mono_error_raise_exception (&error); /* FIXME don't raise here */
10726 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10729 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10731 if (spec->data.custom_data.cookie)
10732 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10742 #ifndef DISABLE_REFLECTION_EMIT
10744 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10745 ReflectionMethodBuilder *rmb,
10746 MonoMethodSignature *sig)
10750 MonoMethodWrapper *wrapperm;
10751 MonoMarshalSpec **specs;
10752 MonoReflectionMethodAux *method_aux;
10757 mono_error_init (&error);
10759 * Methods created using a MethodBuilder should have their memory allocated
10760 * inside the image mempool, while dynamic methods should have their memory
10763 dynamic = rmb->refs != NULL;
10764 image = dynamic ? NULL : klass->image;
10767 g_assert (!klass->generic_class);
10769 mono_loader_lock ();
10771 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10772 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10773 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10775 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10777 wrapperm = (MonoMethodWrapper*)m;
10779 m->dynamic = dynamic;
10781 m->flags = rmb->attrs;
10782 m->iflags = rmb->iattrs;
10783 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10785 m->signature = sig;
10786 m->sre_method = TRUE;
10787 m->skip_visibility = rmb->skip_visibility;
10788 if (rmb->table_idx)
10789 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10791 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10792 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10793 m->string_ctor = 1;
10795 m->signature->pinvoke = 1;
10796 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10797 m->signature->pinvoke = 1;
10799 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10801 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10802 g_assert (mono_error_ok (&error));
10803 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10804 g_assert (mono_error_ok (&error));
10806 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10808 if (image_is_dynamic (klass->image))
10809 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10811 mono_loader_unlock ();
10814 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10815 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10816 MonoMethodHeader *header;
10818 gint32 max_stack, i;
10819 gint32 num_locals = 0;
10820 gint32 num_clauses = 0;
10824 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10825 code_size = rmb->ilgen->code_len;
10826 max_stack = rmb->ilgen->max_stack;
10827 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10828 if (rmb->ilgen->ex_handlers)
10829 num_clauses = method_count_clauses (rmb->ilgen);
10832 code = mono_array_addr (rmb->code, guint8, 0);
10833 code_size = mono_array_length (rmb->code);
10834 /* we probably need to run a verifier on the code... */
10844 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10845 header->code_size = code_size;
10846 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10847 memcpy ((char*)header->code, code, code_size);
10848 header->max_stack = max_stack;
10849 header->init_locals = rmb->init_locals;
10850 header->num_locals = num_locals;
10852 for (i = 0; i < num_locals; ++i) {
10853 MonoReflectionLocalBuilder *lb =
10854 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10856 header->locals [i] = image_g_new0 (image, MonoType, 1);
10857 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10860 header->num_clauses = num_clauses;
10862 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10863 rmb->ilgen, num_clauses);
10866 wrapperm->header = header;
10869 if (rmb->generic_params) {
10870 int count = mono_array_length (rmb->generic_params);
10871 MonoGenericContainer *container = rmb->generic_container;
10873 g_assert (container);
10875 container->type_argc = count;
10876 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10877 container->owner.method = m;
10878 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10880 m->is_generic = TRUE;
10881 mono_method_set_generic_container (m, container);
10883 for (i = 0; i < count; i++) {
10884 MonoReflectionGenericParam *gp =
10885 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10886 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10887 container->type_params [i] = *param;
10891 * The method signature might have pointers to generic parameters that belong to other methods.
10892 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10893 * generic parameters.
10895 for (i = 0; i < m->signature->param_count; ++i) {
10896 MonoType *t = m->signature->params [i];
10897 if (t->type == MONO_TYPE_MVAR) {
10898 MonoGenericParam *gparam = t->data.generic_param;
10899 if (gparam->num < count) {
10900 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10901 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10907 if (klass->generic_container) {
10908 container->parent = klass->generic_container;
10909 container->context.class_inst = klass->generic_container->context.class_inst;
10911 container->context.method_inst = mono_get_shared_generic_inst (container);
10915 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10919 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10921 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10922 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10923 for (i = 0; i < rmb->nrefs; ++i)
10924 data [i + 1] = rmb->refs [i];
10929 /* Parameter info */
10932 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10933 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10934 for (i = 0; i <= m->signature->param_count; ++i) {
10935 MonoReflectionParamBuilder *pb;
10936 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10937 if ((i > 0) && (pb->attrs)) {
10938 /* Make a copy since it might point to a shared type structure */
10939 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10940 m->signature->params [i - 1]->attrs = pb->attrs;
10943 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10944 MonoDynamicImage *assembly;
10946 MonoTypeEnum def_type;
10950 if (!method_aux->param_defaults) {
10951 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10952 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10954 assembly = (MonoDynamicImage*)klass->image;
10955 idx = encode_constant (assembly, pb->def_value, &def_type);
10956 /* Copy the data from the blob since it might get realloc-ed */
10957 p = assembly->blob.data + idx;
10958 len = mono_metadata_decode_blob_size (p, &p2);
10960 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10961 method_aux->param_default_types [i] = def_type;
10962 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10966 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10967 g_assert (mono_error_ok (&error));
10970 if (!method_aux->param_cattr)
10971 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10972 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10978 /* Parameter marshalling */
10981 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10982 MonoReflectionParamBuilder *pb;
10983 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10984 if (pb->marshal_info) {
10986 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10987 specs [pb->position] =
10988 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10992 if (specs != NULL) {
10994 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10995 method_aux->param_marshall = specs;
10998 if (image_is_dynamic (klass->image) && method_aux)
10999 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11001 mono_loader_unlock ();
11007 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11009 ReflectionMethodBuilder rmb;
11010 MonoMethodSignature *sig;
11012 mono_loader_lock ();
11013 sig = ctor_builder_to_signature (klass->image, mb);
11014 mono_loader_unlock ();
11016 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11018 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11019 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11021 /* If we are in a generic class, we might be called multiple times from inflate_method */
11022 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11023 /* ilgen is no longer needed */
11027 return mb->mhandle;
11031 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11033 ReflectionMethodBuilder rmb;
11034 MonoMethodSignature *sig;
11036 mono_loader_lock ();
11037 sig = method_builder_to_signature (klass->image, mb);
11038 mono_loader_unlock ();
11040 reflection_methodbuilder_from_method_builder (&rmb, mb);
11042 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11043 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11045 /* If we are in a generic class, we might be called multiple times from inflate_method */
11046 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11047 /* ilgen is no longer needed */
11050 return mb->mhandle;
11053 static MonoClassField*
11054 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11056 MonoClassField *field;
11060 field = g_new0 (MonoClassField, 1);
11062 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11063 g_assert (mono_error_ok (&error));
11064 if (fb->attrs || fb->modreq || fb->modopt) {
11065 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11066 field->type->attrs = fb->attrs;
11068 g_assert (image_is_dynamic (klass->image));
11069 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11070 g_free (field->type);
11071 field->type = mono_metadata_type_dup (klass->image, custom);
11074 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11076 if (fb->offset != -1)
11077 field->offset = fb->offset;
11078 field->parent = klass;
11079 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11081 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11088 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11091 MonoReflectionTypeBuilder *tb = NULL;
11092 gboolean is_dynamic = FALSE;
11093 MonoClass *geninst;
11095 mono_loader_lock ();
11097 if (is_sre_type_builder (mono_object_class (type))) {
11098 tb = (MonoReflectionTypeBuilder *) type;
11101 } else if (is_sre_generic_instance (mono_object_class (type))) {
11102 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11103 MonoReflectionType *gtd = rgi->generic_type;
11105 if (is_sre_type_builder (mono_object_class (gtd))) {
11106 tb = (MonoReflectionTypeBuilder *)gtd;
11111 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11112 if (tb && tb->generic_container)
11113 mono_reflection_create_generic_class (tb);
11115 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11116 if (!klass->generic_container) {
11117 mono_loader_unlock ();
11121 if (klass->wastypebuilder) {
11122 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11127 mono_loader_unlock ();
11129 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11131 return &geninst->byval_arg;
11135 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11137 MonoGenericClass *gclass;
11138 MonoGenericInst *inst;
11140 g_assert (klass->generic_container);
11142 inst = mono_metadata_get_generic_inst (type_argc, types);
11143 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11145 return mono_generic_class_get_class (gclass);
11148 MonoReflectionMethod*
11149 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11153 MonoMethod *method, *inflated;
11154 MonoMethodInflated *imethod;
11155 MonoGenericContext tmp_context;
11156 MonoGenericInst *ginst;
11157 MonoType **type_argv;
11160 /*FIXME but this no longer should happen*/
11161 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11162 #ifndef DISABLE_REFLECTION_EMIT
11163 MonoReflectionMethodBuilder *mb = NULL;
11164 MonoReflectionTypeBuilder *tb;
11167 mb = (MonoReflectionMethodBuilder *) rmethod;
11168 tb = (MonoReflectionTypeBuilder *) mb->type;
11169 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11171 method = methodbuilder_to_mono_method (klass, mb);
11173 g_assert_not_reached ();
11177 method = rmethod->method;
11180 klass = method->klass;
11182 if (method->is_inflated)
11183 method = ((MonoMethodInflated *) method)->declaring;
11185 count = mono_method_signature (method)->generic_param_count;
11186 if (count != mono_array_length (types))
11189 type_argv = g_new0 (MonoType *, count);
11190 for (i = 0; i < count; i++) {
11191 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11192 type_argv [i] = mono_reflection_type_get_handle (garg);
11194 ginst = mono_metadata_get_generic_inst (count, type_argv);
11195 g_free (type_argv);
11197 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11198 tmp_context.method_inst = ginst;
11200 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11201 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11202 imethod = (MonoMethodInflated *) inflated;
11204 /*FIXME but I think this is no longer necessary*/
11205 if (image_is_dynamic (method->klass->image)) {
11206 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11208 * This table maps metadata structures representing inflated methods/fields
11209 * to the reflection objects representing their generic definitions.
11211 mono_image_lock ((MonoImage*)image);
11212 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11213 mono_image_unlock ((MonoImage*)image);
11216 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11217 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11219 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11222 #ifndef DISABLE_REFLECTION_EMIT
11224 static MonoMethod *
11225 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11227 MonoMethodInflated *imethod;
11228 MonoGenericContext *context;
11232 * With generic code sharing the klass might not be inflated.
11233 * This can happen because classes inflated with their own
11234 * type arguments are "normalized" to the uninflated class.
11236 if (!klass->generic_class)
11239 context = mono_class_get_context (klass);
11241 if (klass->method.count && klass->methods) {
11242 /* Find the already created inflated method */
11243 for (i = 0; i < klass->method.count; ++i) {
11244 g_assert (klass->methods [i]->is_inflated);
11245 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11248 g_assert (i < klass->method.count);
11249 imethod = (MonoMethodInflated*)klass->methods [i];
11252 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11253 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11256 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11257 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11259 mono_image_lock ((MonoImage*)image);
11260 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11261 mono_image_unlock ((MonoImage*)image);
11263 return (MonoMethod *) imethod;
11266 static MonoMethod *
11267 inflate_method (MonoReflectionType *type, MonoObject *obj)
11269 MonoMethod *method;
11272 MonoClass *type_class = mono_object_class (type);
11274 if (is_sre_generic_instance (type_class)) {
11275 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11276 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11277 } else if (is_sre_type_builder (type_class)) {
11278 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11279 } else if (type->type) {
11280 gklass = mono_class_from_mono_type (type->type);
11281 gklass = mono_class_get_generic_type_definition (gklass);
11283 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11286 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11287 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11288 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11290 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11291 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11292 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11293 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11294 method = ((MonoReflectionMethod *) obj)->method;
11296 method = NULL; /* prevent compiler warning */
11297 g_error ("can't handle type %s", obj->vtable->klass->name);
11300 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11303 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11305 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11307 MonoGenericClass *gclass;
11308 MonoDynamicGenericClass *dgclass;
11309 MonoClass *klass, *gklass;
11313 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11314 klass = mono_class_from_mono_type (gtype);
11315 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11316 gclass = gtype->data.generic_class;
11318 if (!gclass->is_dynamic)
11321 dgclass = (MonoDynamicGenericClass *) gclass;
11323 if (dgclass->initialized)
11326 gklass = gclass->container_class;
11327 mono_class_init (gklass);
11329 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11331 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11332 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11333 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11335 for (i = 0; i < dgclass->count_fields; i++) {
11336 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11337 MonoClassField *field, *inflated_field = NULL;
11339 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11340 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11341 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11342 field = ((MonoReflectionField *) obj)->field;
11344 field = NULL; /* prevent compiler warning */
11345 g_assert_not_reached ();
11348 dgclass->fields [i] = *field;
11349 dgclass->fields [i].parent = klass;
11350 dgclass->fields [i].type = mono_class_inflate_generic_type (
11351 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11352 dgclass->field_generic_types [i] = field->type;
11353 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11354 dgclass->field_objects [i] = obj;
11356 if (inflated_field) {
11357 g_free (inflated_field);
11359 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11363 dgclass->initialized = TRUE;
11367 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11369 MonoDynamicGenericClass *dgclass;
11372 g_assert (gclass->is_dynamic);
11374 dgclass = (MonoDynamicGenericClass *)gclass;
11376 for (i = 0; i < dgclass->count_fields; ++i) {
11377 MonoClassField *field = dgclass->fields + i;
11378 mono_metadata_free_type (field->type);
11379 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11384 fix_partial_generic_class (MonoClass *klass)
11386 MonoClass *gklass = klass->generic_class->container_class;
11387 MonoDynamicGenericClass *dgclass;
11390 if (klass->wastypebuilder)
11393 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11394 if (klass->parent != gklass->parent) {
11396 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11397 if (mono_error_ok (&error)) {
11398 MonoClass *parent = mono_class_from_mono_type (parent_type);
11399 mono_metadata_free_type (parent_type);
11400 if (parent != klass->parent) {
11401 /*fool mono_class_setup_parent*/
11402 klass->supertypes = NULL;
11403 mono_class_setup_parent (klass, parent);
11406 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11407 mono_error_cleanup (&error);
11408 if (gklass->wastypebuilder)
11409 klass->wastypebuilder = TRUE;
11414 if (!dgclass->initialized)
11417 if (klass->method.count != gklass->method.count) {
11418 klass->method.count = gklass->method.count;
11419 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11421 for (i = 0; i < klass->method.count; i++) {
11423 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11424 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11425 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11429 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11430 klass->interface_count = gklass->interface_count;
11431 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11432 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11434 for (i = 0; i < gklass->interface_count; ++i) {
11435 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11436 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11437 mono_metadata_free_type (iface_type);
11439 ensure_runtime_vtable (klass->interfaces [i]);
11441 klass->interfaces_inited = 1;
11444 if (klass->field.count != gklass->field.count) {
11445 klass->field.count = gklass->field.count;
11446 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11448 for (i = 0; i < klass->field.count; i++) {
11449 klass->fields [i] = gklass->fields [i];
11450 klass->fields [i].parent = klass;
11451 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11455 /*We can only finish with this klass once it's parent has as well*/
11456 if (gklass->wastypebuilder)
11457 klass->wastypebuilder = TRUE;
11462 ensure_generic_class_runtime_vtable (MonoClass *klass)
11464 MonoClass *gklass = klass->generic_class->container_class;
11466 ensure_runtime_vtable (gklass);
11468 fix_partial_generic_class (klass);
11472 ensure_runtime_vtable (MonoClass *klass)
11474 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11477 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11480 ensure_runtime_vtable (klass->parent);
11483 num = tb->ctors? mono_array_length (tb->ctors): 0;
11484 num += tb->num_methods;
11485 klass->method.count = num;
11486 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11487 num = tb->ctors? mono_array_length (tb->ctors): 0;
11488 for (i = 0; i < num; ++i)
11489 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11490 num = tb->num_methods;
11492 for (i = 0; i < num; ++i)
11493 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11495 if (tb->interfaces) {
11496 klass->interface_count = mono_array_length (tb->interfaces);
11497 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11498 for (i = 0; i < klass->interface_count; ++i) {
11499 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11500 klass->interfaces [i] = mono_class_from_mono_type (iface);
11501 ensure_runtime_vtable (klass->interfaces [i]);
11503 klass->interfaces_inited = 1;
11505 } else if (klass->generic_class){
11506 ensure_generic_class_runtime_vtable (klass);
11509 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11511 for (i = 0; i < klass->method.count; ++i) {
11512 MonoMethod *im = klass->methods [i];
11513 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11514 im->slot = slot_num++;
11517 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11518 mono_class_setup_interface_offsets (klass);
11519 mono_class_setup_interface_id (klass);
11523 * The generic vtable is needed even if image->run is not set since some
11524 * runtime code like ves_icall_Type_GetMethodsByName depends on
11525 * method->slot being defined.
11529 * tb->methods could not be freed since it is used for determining
11530 * overrides during dynamic vtable construction.
11535 mono_reflection_method_get_handle (MonoObject *method)
11537 MonoClass *klass = mono_object_class (method);
11538 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11539 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11540 return sr_method->method;
11542 if (is_sre_method_builder (klass)) {
11543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11544 return mb->mhandle;
11546 if (is_sre_method_on_tb_inst (klass)) {
11547 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11548 MonoMethod *result;
11549 /*FIXME move this to a proper method and unify with resolve_object*/
11550 if (m->method_args) {
11551 result = mono_reflection_method_on_tb_inst_get_handle (m);
11553 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11554 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11555 MonoMethod *mono_method;
11557 if (is_sre_method_builder (mono_object_class (m->mb)))
11558 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11559 else if (is_sr_mono_method (mono_object_class (m->mb)))
11560 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11562 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)));
11564 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11569 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11574 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11576 MonoReflectionTypeBuilder *tb;
11578 MonoReflectionMethod *m;
11581 *num_overrides = 0;
11583 g_assert (image_is_dynamic (klass->image));
11585 if (!mono_class_get_ref_info (klass))
11588 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11590 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11594 for (i = 0; i < tb->num_methods; ++i) {
11595 MonoReflectionMethodBuilder *mb =
11596 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11597 if (mb->override_methods)
11598 onum += mono_array_length (mb->override_methods);
11603 *overrides = g_new0 (MonoMethod*, onum * 2);
11606 for (i = 0; i < tb->num_methods; ++i) {
11607 MonoReflectionMethodBuilder *mb =
11608 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11609 if (mb->override_methods) {
11610 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11611 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11613 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11614 (*overrides) [onum * 2 + 1] = mb->mhandle;
11616 g_assert (mb->mhandle);
11624 *num_overrides = onum;
11628 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11630 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11631 MonoReflectionFieldBuilder *fb;
11632 MonoClassField *field;
11633 MonoImage *image = klass->image;
11634 const char *p, *p2;
11636 guint32 len, idx, real_size = 0;
11638 klass->field.count = tb->num_fields;
11639 klass->field.first = 0;
11641 mono_error_init (error);
11643 if (tb->class_size) {
11644 if ((tb->packing_size & 0xffffff00) != 0) {
11645 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11646 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11649 klass->packing_size = tb->packing_size;
11650 real_size = klass->instance_size + tb->class_size;
11653 if (!klass->field.count) {
11654 klass->instance_size = MAX (klass->instance_size, real_size);
11658 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11659 mono_class_alloc_ext (klass);
11660 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11662 This is, guess what, a hack.
11663 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11664 On the static path no field class is resolved, only types are built. This is the right thing to do
11666 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11668 klass->size_inited = 1;
11670 for (i = 0; i < klass->field.count; ++i) {
11671 MonoArray *rva_data;
11672 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11673 field = &klass->fields [i];
11674 field->name = mono_string_to_utf8_image (image, fb->name, error);
11675 if (!mono_error_ok (error))
11678 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11679 field->type->attrs = fb->attrs;
11681 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11684 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11685 char *base = mono_array_addr (rva_data, char, 0);
11686 size_t size = mono_array_length (rva_data);
11687 char *data = (char *)mono_image_alloc (klass->image, size);
11688 memcpy (data, base, size);
11689 klass->ext->field_def_values [i].data = data;
11691 if (fb->offset != -1)
11692 field->offset = fb->offset;
11693 field->parent = klass;
11694 fb->handle = field;
11695 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11697 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11698 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11700 if (fb->def_value) {
11701 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11702 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11703 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11704 /* Copy the data from the blob since it might get realloc-ed */
11705 p = assembly->blob.data + idx;
11706 len = mono_metadata_decode_blob_size (p, &p2);
11708 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11709 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11713 klass->instance_size = MAX (klass->instance_size, real_size);
11714 mono_class_layout_fields (klass);
11718 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11720 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11721 MonoReflectionPropertyBuilder *pb;
11722 MonoImage *image = klass->image;
11723 MonoProperty *properties;
11726 mono_error_init (error);
11729 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11731 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11732 klass->ext->property.first = 0;
11734 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11735 klass->ext->properties = properties;
11736 for (i = 0; i < klass->ext->property.count; ++i) {
11737 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11738 properties [i].parent = klass;
11739 properties [i].attrs = pb->attrs;
11740 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11741 if (!mono_error_ok (error))
11743 if (pb->get_method)
11744 properties [i].get = pb->get_method->mhandle;
11745 if (pb->set_method)
11746 properties [i].set = pb->set_method->mhandle;
11748 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11749 if (pb->def_value) {
11751 const char *p, *p2;
11752 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11753 if (!klass->ext->prop_def_values)
11754 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11755 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11756 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11757 /* Copy the data from the blob since it might get realloc-ed */
11758 p = assembly->blob.data + idx;
11759 len = mono_metadata_decode_blob_size (p, &p2);
11761 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11762 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11767 MonoReflectionEvent *
11768 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11770 MonoEvent *event = g_new0 (MonoEvent, 1);
11773 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11775 event->parent = klass;
11776 event->attrs = eb->attrs;
11777 event->name = mono_string_to_utf8 (eb->name);
11778 if (eb->add_method)
11779 event->add = eb->add_method->mhandle;
11780 if (eb->remove_method)
11781 event->remove = eb->remove_method->mhandle;
11782 if (eb->raise_method)
11783 event->raise = eb->raise_method->mhandle;
11785 #ifndef MONO_SMALL_CONFIG
11786 if (eb->other_methods) {
11788 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11789 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11790 MonoReflectionMethodBuilder *mb =
11791 mono_array_get (eb->other_methods,
11792 MonoReflectionMethodBuilder*, j);
11793 event->other [j] = mb->mhandle;
11798 return mono_event_get_object (mono_object_domain (tb), klass, event);
11802 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11804 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11805 MonoReflectionEventBuilder *eb;
11806 MonoImage *image = klass->image;
11810 mono_error_init (error);
11813 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11815 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11816 klass->ext->event.first = 0;
11818 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11819 klass->ext->events = events;
11820 for (i = 0; i < klass->ext->event.count; ++i) {
11821 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11822 events [i].parent = klass;
11823 events [i].attrs = eb->attrs;
11824 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11825 if (!mono_error_ok (error))
11827 if (eb->add_method)
11828 events [i].add = eb->add_method->mhandle;
11829 if (eb->remove_method)
11830 events [i].remove = eb->remove_method->mhandle;
11831 if (eb->raise_method)
11832 events [i].raise = eb->raise_method->mhandle;
11834 #ifndef MONO_SMALL_CONFIG
11835 if (eb->other_methods) {
11837 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11838 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11839 MonoReflectionMethodBuilder *mb =
11840 mono_array_get (eb->other_methods,
11841 MonoReflectionMethodBuilder*, j);
11842 events [i].other [j] = mb->mhandle;
11846 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11851 remove_instantiations_of_and_ensure_contents (gpointer key,
11853 gpointer user_data)
11855 MonoType *type = (MonoType*)key;
11856 MonoClass *klass = (MonoClass*)user_data;
11858 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11859 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11866 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11868 mono_error_init (error);
11874 for (i = 0; i < mono_array_length (arr); ++i) {
11875 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11876 if (!mono_error_ok (error))
11881 MonoReflectionType*
11882 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11886 MonoDomain* domain;
11887 MonoReflectionType* res;
11890 domain = mono_object_domain (tb);
11891 klass = mono_class_from_mono_type (tb->type.type);
11894 * Check for user defined Type subclasses.
11896 RESOLVE_TYPE (tb->parent, &error);
11897 mono_error_raise_exception (&error); /* FIXME don't raise here */
11898 check_array_for_usertypes (tb->interfaces, &error);
11899 mono_error_raise_exception (&error); /*FIXME don't raise here */
11901 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11902 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11904 RESOLVE_TYPE (fb->type, &error);
11905 mono_error_raise_exception (&error); /* FIXME don't raise here */
11906 check_array_for_usertypes (fb->modreq, &error);
11907 mono_error_raise_exception (&error); /*FIXME don't raise here */
11908 check_array_for_usertypes (fb->modopt, &error);
11909 mono_error_raise_exception (&error); /*FIXME don't raise here */
11910 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11911 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11912 mono_error_raise_exception (&error); /* FIXME don't raise here */
11918 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11919 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11921 RESOLVE_TYPE (mb->rtype, &error);
11922 mono_error_raise_exception (&error); /* FIXME don't raise here */
11923 check_array_for_usertypes (mb->return_modreq, &error);
11924 mono_error_raise_exception (&error); /*FIXME don't raise here */
11925 check_array_for_usertypes (mb->return_modopt, &error);
11926 mono_error_raise_exception (&error); /*FIXME don't raise here */
11927 check_array_for_usertypes (mb->parameters, &error);
11928 mono_error_raise_exception (&error); /*FIXME don't raise here */
11929 if (mb->param_modreq)
11930 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11931 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11932 mono_error_raise_exception (&error); /*FIXME don't raise here */
11934 if (mb->param_modopt)
11935 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11936 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11937 mono_error_raise_exception (&error); /*FIXME don't raise here */
11943 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11944 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11946 check_array_for_usertypes (mb->parameters, &error);
11947 mono_error_raise_exception (&error); /*FIXME don't raise here */
11948 if (mb->param_modreq)
11949 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11950 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11951 mono_error_raise_exception (&error); /*FIXME don't raise here */
11953 if (mb->param_modopt)
11954 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11955 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11956 mono_error_raise_exception (&error); /*FIXME don't raise here */
11962 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11965 * we need to lock the domain because the lock will be taken inside
11966 * So, we need to keep the locking order correct.
11968 mono_loader_lock ();
11969 mono_domain_lock (domain);
11970 if (klass->wastypebuilder) {
11971 mono_domain_unlock (domain);
11972 mono_loader_unlock ();
11974 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11975 mono_error_raise_exception (&error); /* FIXME don't raise here */
11980 * Fields to set in klass:
11981 * the various flags: delegate/unicode/contextbound etc.
11983 klass->flags = tb->attrs;
11984 klass->has_cctor = 1;
11985 klass->has_finalize = 1;
11986 klass->has_finalize_inited = 1;
11988 mono_class_setup_parent (klass, klass->parent);
11989 /* fool mono_class_setup_supertypes */
11990 klass->supertypes = NULL;
11991 mono_class_setup_supertypes (klass);
11992 mono_class_setup_mono_type (klass);
11995 if (!((MonoDynamicImage*)klass->image)->run) {
11996 if (klass->generic_container) {
11997 /* FIXME: The code below can't handle generic classes */
11998 klass->wastypebuilder = TRUE;
11999 mono_loader_unlock ();
12000 mono_domain_unlock (domain);
12002 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12003 mono_error_raise_exception (&error); /* FIXME don't raise here */
12010 /* enums are done right away */
12011 if (!klass->enumtype)
12012 ensure_runtime_vtable (klass);
12014 if (tb->subtypes) {
12015 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12016 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12017 mono_class_alloc_ext (klass);
12018 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)));
12022 klass->nested_classes_inited = TRUE;
12024 /* fields and object layout */
12025 if (klass->parent) {
12026 if (!klass->parent->size_inited)
12027 mono_class_init (klass->parent);
12028 klass->instance_size = klass->parent->instance_size;
12029 klass->sizes.class_size = 0;
12030 klass->min_align = klass->parent->min_align;
12031 /* if the type has no fields we won't call the field_setup
12032 * routine which sets up klass->has_references.
12034 klass->has_references |= klass->parent->has_references;
12036 klass->instance_size = sizeof (MonoObject);
12037 klass->min_align = 1;
12040 /* FIXME: handle packing_size and instance_size */
12041 typebuilder_setup_fields (klass, &error);
12042 if (!mono_error_ok (&error))
12044 typebuilder_setup_properties (klass, &error);
12045 if (!mono_error_ok (&error))
12048 typebuilder_setup_events (klass, &error);
12049 if (!mono_error_ok (&error))
12052 klass->wastypebuilder = TRUE;
12055 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12056 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12057 * we want to return normal System.MonoType objects, so clear these out from the cache.
12059 * Together with this we must ensure the contents of all instances to match the created type.
12061 if (domain->type_hash && klass->generic_container)
12062 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12064 mono_domain_unlock (domain);
12065 mono_loader_unlock ();
12067 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12068 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12069 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12072 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12073 mono_error_raise_exception (&error); /* FIXME don't raise here */
12075 g_assert (res != (MonoReflectionType*)tb);
12080 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12081 klass->wastypebuilder = TRUE;
12082 mono_domain_unlock (domain);
12083 mono_loader_unlock ();
12084 mono_error_raise_exception (&error);
12089 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12091 MonoGenericParamFull *param;
12096 image = &gparam->tbuilder->module->dynamic_image->image;
12098 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12100 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12101 g_assert (mono_error_ok (&error));
12102 param->param.num = gparam->index;
12104 if (gparam->mbuilder) {
12105 if (!gparam->mbuilder->generic_container) {
12106 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12107 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12108 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12109 gparam->mbuilder->generic_container->is_method = TRUE;
12111 * Cannot set owner.method, since the MonoMethod is not created yet.
12112 * Set the image field instead, so type_in_image () works.
12114 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12115 gparam->mbuilder->generic_container->owner.image = klass->image;
12117 param->param.owner = gparam->mbuilder->generic_container;
12118 } else if (gparam->tbuilder) {
12119 if (!gparam->tbuilder->generic_container) {
12120 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12121 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12122 gparam->tbuilder->generic_container->owner.klass = klass;
12124 param->param.owner = gparam->tbuilder->generic_container;
12127 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12129 gparam->type.type = &pklass->byval_arg;
12131 mono_class_set_ref_info (pklass, gparam);
12132 mono_image_append_class_to_reflection_info_set (pklass);
12136 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12139 MonoReflectionModuleBuilder *module = sig->module;
12140 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12141 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12146 check_array_for_usertypes (sig->arguments, &error);
12147 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12149 sigbuffer_init (&buf, 32);
12151 sigbuffer_add_value (&buf, 0x07);
12152 sigbuffer_add_value (&buf, na);
12153 if (assembly != NULL){
12154 for (i = 0; i < na; ++i) {
12155 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12156 encode_reflection_type (assembly, type, &buf);
12160 buflen = buf.p - buf.buf;
12161 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12162 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12163 sigbuffer_free (&buf);
12169 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12172 MonoDynamicImage *assembly = sig->module->dynamic_image;
12173 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12178 check_array_for_usertypes (sig->arguments, &error);
12179 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12181 sigbuffer_init (&buf, 32);
12183 sigbuffer_add_value (&buf, 0x06);
12184 for (i = 0; i < na; ++i) {
12185 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12186 encode_reflection_type (assembly, type, &buf);
12189 buflen = buf.p - buf.buf;
12190 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12191 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12192 sigbuffer_free (&buf);
12198 MonoMethod *handle;
12199 MonoDomain *domain;
12200 } DynamicMethodReleaseData;
12203 * The runtime automatically clean up those after finalization.
12205 static MonoReferenceQueue *dynamic_method_queue;
12208 free_dynamic_method (void *dynamic_method)
12210 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12211 MonoDomain *domain = data->domain;
12212 MonoMethod *method = data->handle;
12215 mono_domain_lock (domain);
12216 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12217 g_hash_table_remove (domain->method_to_dyn_method, method);
12218 mono_domain_unlock (domain);
12219 g_assert (dis_link);
12220 mono_gchandle_free (dis_link);
12222 mono_runtime_free_method (domain, method);
12227 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12229 MonoReferenceQueue *queue;
12230 MonoMethod *handle;
12231 DynamicMethodReleaseData *release_data;
12232 ReflectionMethodBuilder rmb;
12233 MonoMethodSignature *sig;
12235 MonoDomain *domain;
12239 if (mono_runtime_is_shutting_down ())
12240 mono_raise_exception (mono_get_exception_invalid_operation (""));
12242 if (!(queue = dynamic_method_queue)) {
12243 mono_loader_lock ();
12244 if (!(queue = dynamic_method_queue))
12245 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12246 mono_loader_unlock ();
12249 sig = dynamic_method_to_signature (mb);
12251 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12254 * Resolve references.
12257 * Every second entry in the refs array is reserved for storing handle_class,
12258 * which is needed by the ldtoken implementation in the JIT.
12260 rmb.nrefs = mb->nrefs;
12261 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12262 for (i = 0; i < mb->nrefs; i += 2) {
12263 MonoClass *handle_class;
12265 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12267 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12268 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12270 * The referenced DynamicMethod should already be created by the managed
12271 * code, except in the case of circular references. In that case, we store
12272 * method in the refs array, and fix it up later when the referenced
12273 * DynamicMethod is created.
12275 if (method->mhandle) {
12276 ref = method->mhandle;
12278 /* FIXME: GC object stored in unmanaged memory */
12281 /* FIXME: GC object stored in unmanaged memory */
12282 method->referenced_by = g_slist_append (method->referenced_by, mb);
12284 handle_class = mono_defaults.methodhandle_class;
12286 MonoException *ex = NULL;
12287 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12289 ex = mono_get_exception_type_load (NULL, NULL);
12290 else if (mono_security_core_clr_enabled ())
12291 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12295 mono_raise_exception (ex);
12300 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12301 rmb.refs [i + 1] = handle_class;
12304 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12306 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12307 release_data = g_new (DynamicMethodReleaseData, 1);
12308 release_data->handle = handle;
12309 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12310 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12311 g_free (release_data);
12313 /* Fix up refs entries pointing at us */
12314 for (l = mb->referenced_by; l; l = l->next) {
12315 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12316 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12319 g_assert (method->mhandle);
12321 data = (gpointer*)wrapper->method_data;
12322 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12323 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12324 data [i + 1] = mb->mhandle;
12327 g_slist_free (mb->referenced_by);
12331 /* ilgen is no longer needed */
12334 domain = mono_domain_get ();
12335 mono_domain_lock (domain);
12336 if (!domain->method_to_dyn_method)
12337 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12338 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12339 mono_domain_unlock (domain);
12342 #endif /* DISABLE_REFLECTION_EMIT */
12346 * mono_reflection_is_valid_dynamic_token:
12348 * Returns TRUE if token is valid.
12352 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12354 return lookup_dyn_token (image, token) != NULL;
12357 MonoMethodSignature *
12358 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12360 MonoMethodSignature *sig;
12361 g_assert (image_is_dynamic (image));
12363 mono_error_init (error);
12365 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12369 return mono_method_signature_checked (method, error);
12372 #ifndef DISABLE_REFLECTION_EMIT
12375 * mono_reflection_lookup_dynamic_token:
12377 * Finish the Builder object pointed to by TOKEN and return the corresponding
12378 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12379 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12382 * LOCKING: Take the loader lock
12385 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12387 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12391 obj = lookup_dyn_token (assembly, token);
12394 g_error ("Could not find required dynamic token 0x%08x", token);
12400 handle_class = &klass;
12401 return resolve_object (image, obj, handle_class, context);
12405 * ensure_complete_type:
12407 * Ensure that KLASS is completed if it is a dynamic type, or references
12411 ensure_complete_type (MonoClass *klass)
12413 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12414 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12416 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12418 // Asserting here could break a lot of code
12419 //g_assert (klass->wastypebuilder);
12422 if (klass->generic_class) {
12423 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12426 for (i = 0; i < inst->type_argc; ++i) {
12427 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12433 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12435 gpointer result = NULL;
12437 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12438 result = mono_string_intern ((MonoString*)obj);
12439 *handle_class = mono_defaults.string_class;
12441 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12442 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12443 MonoClass *mc = mono_class_from_mono_type (type);
12444 if (!mono_class_init (mc))
12445 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12448 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12449 result = mono_class_from_mono_type (inflated);
12450 mono_metadata_free_type (inflated);
12452 result = mono_class_from_mono_type (type);
12454 *handle_class = mono_defaults.typehandle_class;
12456 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12457 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12458 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12459 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12460 result = ((MonoReflectionMethod*)obj)->method;
12463 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12464 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12466 *handle_class = mono_defaults.methodhandle_class;
12468 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12469 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12470 result = mb->mhandle;
12472 /* Type is not yet created */
12473 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12475 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12478 * Hopefully this has been filled in by calling CreateType() on the
12482 * TODO: This won't work if the application finishes another
12483 * TypeBuilder instance instead of this one.
12485 result = mb->mhandle;
12489 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12490 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12492 *handle_class = mono_defaults.methodhandle_class;
12493 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12494 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12496 result = cb->mhandle;
12498 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12500 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12501 result = cb->mhandle;
12505 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12506 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12508 *handle_class = mono_defaults.methodhandle_class;
12509 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12510 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12512 ensure_complete_type (field->parent);
12514 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12515 MonoClass *klass = mono_class_from_mono_type (inflated);
12516 MonoClassField *inflated_field;
12517 gpointer iter = NULL;
12518 mono_metadata_free_type (inflated);
12519 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12520 if (!strcmp (field->name, inflated_field->name))
12523 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12524 result = inflated_field;
12528 *handle_class = mono_defaults.fieldhandle_class;
12530 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12531 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12532 result = fb->handle;
12535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12537 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12538 result = fb->handle;
12541 if (fb->handle && fb->handle->parent->generic_container) {
12542 MonoClass *klass = fb->handle->parent;
12543 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12544 MonoClass *inflated = mono_class_from_mono_type (type);
12546 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12548 mono_metadata_free_type (type);
12550 *handle_class = mono_defaults.fieldhandle_class;
12551 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12553 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12556 klass = type->data.klass;
12557 if (klass->wastypebuilder) {
12558 /* Already created */
12562 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12563 result = type->data.klass;
12566 *handle_class = mono_defaults.typehandle_class;
12567 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12568 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12569 MonoMethodSignature *sig;
12572 if (helper->arguments)
12573 nargs = mono_array_length (helper->arguments);
12577 sig = mono_metadata_signature_alloc (image, nargs);
12578 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12579 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12581 if (helper->unmanaged_call_conv) { /* unmanaged */
12582 sig->call_convention = helper->unmanaged_call_conv - 1;
12583 sig->pinvoke = TRUE;
12584 } else if (helper->call_conv & 0x02) {
12585 sig->call_convention = MONO_CALL_VARARG;
12587 sig->call_convention = MONO_CALL_DEFAULT;
12590 sig->param_count = nargs;
12591 /* TODO: Copy type ? */
12592 sig->ret = helper->return_type->type;
12593 for (i = 0; i < nargs; ++i)
12594 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12597 *handle_class = NULL;
12598 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12599 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12600 /* Already created by the managed code */
12601 g_assert (method->mhandle);
12602 result = method->mhandle;
12603 *handle_class = mono_defaults.methodhandle_class;
12604 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12605 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12606 type = mono_class_inflate_generic_type (type, context);
12607 result = mono_class_from_mono_type (type);
12608 *handle_class = mono_defaults.typehandle_class;
12610 mono_metadata_free_type (type);
12611 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12612 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12613 type = mono_class_inflate_generic_type (type, context);
12614 result = mono_class_from_mono_type (type);
12615 *handle_class = mono_defaults.typehandle_class;
12617 mono_metadata_free_type (type);
12618 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12619 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12620 MonoClass *inflated;
12622 MonoClassField *field;
12624 if (is_sre_field_builder (mono_object_class (f->fb)))
12625 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12626 else if (is_sr_mono_field (mono_object_class (f->fb)))
12627 field = ((MonoReflectionField*)f->fb)->field;
12629 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)));
12631 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12632 inflated = mono_class_from_mono_type (type);
12634 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12635 ensure_complete_type (field->parent);
12637 mono_metadata_free_type (type);
12638 *handle_class = mono_defaults.fieldhandle_class;
12639 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12640 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12641 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12642 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12643 MonoMethod *method;
12645 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12646 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12647 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12648 method = ((MonoReflectionMethod *)c->cb)->method;
12650 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)));
12652 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12653 *handle_class = mono_defaults.methodhandle_class;
12654 mono_metadata_free_type (type);
12655 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12656 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12657 if (m->method_args) {
12658 result = mono_reflection_method_on_tb_inst_get_handle (m);
12661 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12662 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12665 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12666 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12667 MonoMethod *method;
12669 if (is_sre_method_builder (mono_object_class (m->mb)))
12670 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12671 else if (is_sr_mono_method (mono_object_class (m->mb)))
12672 method = ((MonoReflectionMethod *)m->mb)->method;
12674 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)));
12676 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12677 mono_metadata_free_type (type);
12679 *handle_class = mono_defaults.methodhandle_class;
12680 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12681 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12684 MonoMethod *method;
12688 mtype = mono_reflection_type_get_handle (m->parent);
12689 klass = mono_class_from_mono_type (mtype);
12691 /* Find the method */
12693 name = mono_string_to_utf8 (m->name);
12695 while ((method = mono_class_get_methods (klass, &iter))) {
12696 if (!strcmp (method->name, name))
12703 // FIXME: Check parameters/return value etc. match
12706 *handle_class = mono_defaults.methodhandle_class;
12707 } else if (is_sre_array (mono_object_get_class(obj)) ||
12708 is_sre_byref (mono_object_get_class(obj)) ||
12709 is_sre_pointer (mono_object_get_class(obj))) {
12710 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12711 MonoType *type = mono_reflection_type_get_handle (ref_type);
12714 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12715 result = mono_class_from_mono_type (inflated);
12716 mono_metadata_free_type (inflated);
12718 result = mono_class_from_mono_type (type);
12720 *handle_class = mono_defaults.typehandle_class;
12722 g_print ("%s\n", obj->vtable->klass->name);
12723 g_assert_not_reached ();
12728 #else /* DISABLE_REFLECTION_EMIT */
12731 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12733 g_assert_not_reached ();
12738 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12740 g_assert_not_reached ();
12744 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12746 g_assert_not_reached ();
12750 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12752 g_assert_not_reached ();
12756 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12758 g_assert_not_reached ();
12762 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12764 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12768 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12770 g_assert_not_reached ();
12774 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12776 g_assert_not_reached ();
12779 MonoReflectionModule *
12780 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12782 g_assert_not_reached ();
12787 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12789 g_assert_not_reached ();
12794 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12796 g_assert_not_reached ();
12801 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12802 gboolean create_open_instance, gboolean register_token)
12804 g_assert_not_reached ();
12809 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12814 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12816 g_assert_not_reached ();
12820 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12823 *num_overrides = 0;
12826 MonoReflectionEvent *
12827 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12829 g_assert_not_reached ();
12833 MonoReflectionType*
12834 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12836 g_assert_not_reached ();
12841 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12843 g_assert_not_reached ();
12847 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12849 g_assert_not_reached ();
12854 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12856 g_assert_not_reached ();
12861 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12866 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12872 mono_reflection_type_get_handle (MonoReflectionType* ref)
12880 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12882 g_assert_not_reached ();
12885 #endif /* DISABLE_REFLECTION_EMIT */
12887 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12888 const static guint32 declsec_flags_map[] = {
12889 0x00000000, /* empty */
12890 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12891 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12892 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12893 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12894 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12895 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12896 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12897 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12898 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12899 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12900 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12901 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12902 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12903 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12904 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12905 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12906 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12907 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12911 * Returns flags that includes all available security action associated to the handle.
12912 * @token: metadata token (either for a class or a method)
12913 * @image: image where resides the metadata.
12916 mono_declsec_get_flags (MonoImage *image, guint32 token)
12918 int index = mono_metadata_declsec_from_index (image, token);
12919 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12920 guint32 result = 0;
12924 /* HasSecurity can be present for other, not specially encoded, attributes,
12925 e.g. SuppressUnmanagedCodeSecurityAttribute */
12929 for (i = index; i < t->rows; i++) {
12930 guint32 cols [MONO_DECL_SECURITY_SIZE];
12932 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12933 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12936 action = cols [MONO_DECL_SECURITY_ACTION];
12937 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12938 result |= declsec_flags_map [action];
12940 g_assert_not_reached ();
12947 * Get the security actions (in the form of flags) associated with the specified method.
12949 * @method: The method for which we want the declarative security flags.
12950 * Return the declarative security flags for the method (only).
12952 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12953 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12956 mono_declsec_flags_from_method (MonoMethod *method)
12958 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12959 /* FIXME: No cache (for the moment) */
12960 guint32 idx = mono_method_get_index (method);
12961 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12962 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12963 return mono_declsec_get_flags (method->klass->image, idx);
12969 * Get the security actions (in the form of flags) associated with the specified class.
12971 * @klass: The class for which we want the declarative security flags.
12972 * Return the declarative security flags for the class.
12974 * Note: We cache the flags inside the MonoClass structure as this will get
12975 * called very often (at least for each method).
12978 mono_declsec_flags_from_class (MonoClass *klass)
12980 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12981 if (!klass->ext || !klass->ext->declsec_flags) {
12984 idx = mono_metadata_token_index (klass->type_token);
12985 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12986 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12987 mono_loader_lock ();
12988 mono_class_alloc_ext (klass);
12989 mono_loader_unlock ();
12990 /* we cache the flags on classes */
12991 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12993 return klass->ext->declsec_flags;
12999 * Get the security actions (in the form of flags) associated with the specified assembly.
13001 * @assembly: The assembly for which we want the declarative security flags.
13002 * Return the declarative security flags for the assembly.
13005 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13007 guint32 idx = 1; /* there is only one assembly */
13008 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13009 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13010 return mono_declsec_get_flags (assembly->image, idx);
13015 * Fill actions for the specific index (which may either be an encoded class token or
13016 * an encoded method token) from the metadata image.
13017 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13020 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13021 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13023 MonoBoolean result = FALSE;
13025 guint32 cols [MONO_DECL_SECURITY_SIZE];
13026 int index = mono_metadata_declsec_from_index (image, token);
13029 t = &image->tables [MONO_TABLE_DECLSECURITY];
13030 for (i = index; i < t->rows; i++) {
13031 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13033 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13036 /* if present only replace (class) permissions with method permissions */
13037 /* if empty accept either class or method permissions */
13038 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13039 if (!actions->demand.blob) {
13040 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13041 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13042 actions->demand.blob = (char*) (blob + 2);
13043 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13046 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13047 if (!actions->noncasdemand.blob) {
13048 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13049 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13050 actions->noncasdemand.blob = (char*) (blob + 2);
13051 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13054 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13055 if (!actions->demandchoice.blob) {
13056 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13057 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13058 actions->demandchoice.blob = (char*) (blob + 2);
13059 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13069 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13070 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13072 guint32 idx = mono_metadata_token_index (klass->type_token);
13073 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13074 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13075 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13079 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13080 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13082 guint32 idx = mono_method_get_index (method);
13083 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13084 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13085 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13089 * Collect all actions (that requires to generate code in mini) assigned for
13090 * the specified method.
13091 * Note: Don't use the content of actions if the function return FALSE.
13094 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13096 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13097 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13098 MonoBoolean result = FALSE;
13101 /* quick exit if no declarative security is present in the metadata */
13102 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13105 /* we want the original as the wrapper is "free" of the security informations */
13106 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13107 method = mono_marshal_method_from_wrapper (method);
13112 /* First we look for method-level attributes */
13113 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13114 mono_class_init (method->klass);
13115 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13117 result = mono_declsec_get_method_demands_params (method, demands,
13118 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13121 /* Here we use (or create) the class declarative cache to look for demands */
13122 flags = mono_declsec_flags_from_class (method->klass);
13123 if (flags & mask) {
13125 mono_class_init (method->klass);
13126 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13128 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13129 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13132 /* The boolean return value is used as a shortcut in case nothing needs to
13133 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13139 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13141 * Note: Don't use the content of actions if the function return FALSE.
13144 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13146 MonoBoolean result = FALSE;
13149 /* quick exit if no declarative security is present in the metadata */
13150 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13153 /* we want the original as the wrapper is "free" of the security informations */
13154 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13155 method = mono_marshal_method_from_wrapper (method);
13160 /* results are independant - zeroize both */
13161 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13162 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13164 /* First we look for method-level attributes */
13165 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13166 mono_class_init (method->klass);
13168 result = mono_declsec_get_method_demands_params (method, cmethod,
13169 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13172 /* Here we use (or create) the class declarative cache to look for demands */
13173 flags = mono_declsec_flags_from_class (method->klass);
13174 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13175 mono_class_init (method->klass);
13177 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13178 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13185 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13187 * @klass The inherited class - this is the class that provides the security check (attributes)
13189 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13191 * Note: Don't use the content of actions if the function return FALSE.
13194 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13196 MonoBoolean result = FALSE;
13199 /* quick exit if no declarative security is present in the metadata */
13200 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13203 /* Here we use (or create) the class declarative cache to look for demands */
13204 flags = mono_declsec_flags_from_class (klass);
13205 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13206 mono_class_init (klass);
13207 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13209 result |= mono_declsec_get_class_demands_params (klass, demands,
13210 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13217 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13219 * Note: Don't use the content of actions if the function return FALSE.
13222 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13224 /* quick exit if no declarative security is present in the metadata */
13225 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13228 /* we want the original as the wrapper is "free" of the security informations */
13229 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13230 method = mono_marshal_method_from_wrapper (method);
13235 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13236 mono_class_init (method->klass);
13237 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13239 return mono_declsec_get_method_demands_params (method, demands,
13240 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13247 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13249 guint32 cols [MONO_DECL_SECURITY_SIZE];
13253 int index = mono_metadata_declsec_from_index (image, token);
13257 t = &image->tables [MONO_TABLE_DECLSECURITY];
13258 for (i = index; i < t->rows; i++) {
13259 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13261 /* shortcut - index are ordered */
13262 if (token != cols [MONO_DECL_SECURITY_PARENT])
13265 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13266 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13267 entry->blob = (char*) (metadata + 2);
13268 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13277 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13279 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13280 guint32 idx = mono_method_get_index (method);
13281 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13282 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13283 return get_declsec_action (method->klass->image, idx, action, entry);
13289 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13292 guint32 flags = mono_declsec_flags_from_class (klass);
13293 if (declsec_flags_map [action] & flags) {
13294 guint32 idx = mono_metadata_token_index (klass->type_token);
13295 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13296 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13297 return get_declsec_action (klass->image, idx, action, entry);
13303 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13305 guint32 idx = 1; /* there is only one assembly */
13306 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13307 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13309 return get_declsec_action (assembly->image, idx, action, entry);
13313 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13316 MonoObject *res, *exc;
13318 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13319 static MonoMethod *method = NULL;
13321 if (!System_Reflection_Emit_TypeBuilder) {
13322 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13323 g_assert (System_Reflection_Emit_TypeBuilder);
13325 if (method == NULL) {
13326 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13331 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13332 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13334 g_assert (mono_class_get_ref_info (klass));
13335 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13337 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13338 mono_error_raise_exception (&error); /* FIXME don't raise here */
13340 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13344 return *(MonoBoolean*)mono_object_unbox (res);
13348 * mono_reflection_type_get_type:
13349 * @reftype: the System.Type object
13351 * Returns the MonoType* associated with the C# System.Type object @reftype.
13354 mono_reflection_type_get_type (MonoReflectionType *reftype)
13356 g_assert (reftype);
13358 return mono_reflection_type_get_handle (reftype);
13362 * mono_reflection_assembly_get_assembly:
13363 * @refassembly: the System.Reflection.Assembly object
13365 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13368 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13370 g_assert (refassembly);
13372 return refassembly->assembly;