2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
226 dynamic_images_lock (void)
228 mono_os_mutex_lock (&dynamic_images_mutex);
232 dynamic_images_unlock (void)
234 mono_os_mutex_unlock (&dynamic_images_mutex);
238 * mono_find_dynamic_image_owner:
240 * Find the dynamic image, if any, which a given pointer is located in the memory of.
243 mono_find_dynamic_image_owner (void *ptr)
245 MonoImage *owner = NULL;
248 dynamic_images_lock ();
252 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254 if (mono_mempool_contains_addr (image->mempool, ptr))
259 dynamic_images_unlock ();
265 mono_reflection_init (void)
267 mono_os_mutex_init (&dynamic_images_mutex);
271 dynamic_image_lock (MonoDynamicImage *image)
273 MONO_PREPARE_BLOCKING;
274 mono_image_lock ((MonoImage*)image);
275 MONO_FINISH_BLOCKING;
279 dynamic_image_unlock (MonoDynamicImage *image)
281 mono_image_unlock ((MonoImage*)image);
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
287 MONO_REQ_GC_UNSAFE_MODE;
289 dynamic_image_lock (assembly);
290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291 dynamic_image_unlock (assembly);
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
297 MONO_REQ_GC_UNSAFE_MODE;
301 dynamic_image_lock (assembly);
302 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303 dynamic_image_unlock (assembly);
309 sigbuffer_init (SigBuffer *buf, int size)
311 MONO_REQ_GC_NEUTRAL_MODE;
313 buf->buf = (char *)g_malloc (size);
315 buf->end = buf->buf + size;
319 sigbuffer_make_room (SigBuffer *buf, int size)
321 MONO_REQ_GC_NEUTRAL_MODE;
323 if (buf->end - buf->p < size) {
324 int new_size = buf->end - buf->buf + size + 32;
325 char *p = (char *)g_realloc (buf->buf, new_size);
326 size = buf->p - buf->buf;
329 buf->end = buf->buf + new_size;
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
336 MONO_REQ_GC_NEUTRAL_MODE;
338 sigbuffer_make_room (buf, 6);
339 mono_metadata_encode_value (val, buf->p, &buf->p);
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 sigbuffer_make_room (buf, 1);
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
355 MONO_REQ_GC_NEUTRAL_MODE;
357 sigbuffer_make_room (buf, size);
358 memcpy (buf->p, p, size);
363 sigbuffer_free (SigBuffer *buf)
365 MONO_REQ_GC_NEUTRAL_MODE;
370 #ifndef DISABLE_REFLECTION_EMIT
374 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
378 image_g_malloc (MonoImage *image, guint size)
380 MONO_REQ_GC_NEUTRAL_MODE;
383 return mono_image_alloc (image, size);
385 return g_malloc (size);
387 #endif /* !DISABLE_REFLECTION_EMIT */
392 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 image_g_malloc0 (MonoImage *image, guint size)
398 MONO_REQ_GC_NEUTRAL_MODE;
401 return mono_image_alloc0 (image, size);
403 return g_malloc0 (size);
406 #ifndef DISABLE_REFLECTION_EMIT
408 image_strdup (MonoImage *image, const char *s)
410 MONO_REQ_GC_NEUTRAL_MODE;
413 return mono_image_strdup (image, s);
419 #define image_g_new(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
422 #define image_g_new0(image,struct_type, n_structs) \
423 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
427 alloc_table (MonoDynamicTable *table, guint nrows)
429 MONO_REQ_GC_NEUTRAL_MODE;
432 g_assert (table->columns);
433 if (nrows + 1 >= table->alloc_rows) {
434 while (nrows + 1 >= table->alloc_rows) {
435 if (table->alloc_rows == 0)
436 table->alloc_rows = 16;
438 table->alloc_rows *= 2;
441 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
446 make_room_in_stream (MonoDynamicStream *stream, int size)
448 MONO_REQ_GC_NEUTRAL_MODE;
450 if (size <= stream->alloc_size)
453 while (stream->alloc_size <= size) {
454 if (stream->alloc_size < 4096)
455 stream->alloc_size = 4096;
457 stream->alloc_size *= 2;
460 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
466 MONO_REQ_GC_NEUTRAL_MODE;
470 gpointer oldkey, oldval;
472 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473 return GPOINTER_TO_UINT (oldval);
475 len = strlen (str) + 1;
478 make_room_in_stream (sh, idx + len);
481 * We strdup the string even if we already copy them in sh->data
482 * so that the string pointers in the hash remain valid even if
483 * we need to realloc sh->data. We may want to avoid that later.
485 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486 memcpy (sh->data + idx, str, len);
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
494 MONO_REQ_GC_UNSAFE_MODE;
496 char *name = mono_string_to_utf8 (str);
498 idx = string_heap_insert (sh, name);
503 #ifndef DISABLE_REFLECTION_EMIT
505 string_heap_init (MonoDynamicStream *sh)
507 MONO_REQ_GC_NEUTRAL_MODE;
510 sh->alloc_size = 4096;
511 sh->data = (char *)g_malloc (4096);
512 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513 string_heap_insert (sh, "");
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 make_room_in_stream (stream, stream->index + len);
525 memcpy (stream->data + stream->index, data, len);
527 stream->index += len;
529 * align index? Not without adding an additional param that controls it since
530 * we may store a blob value in pieces.
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
538 MONO_REQ_GC_NEUTRAL_MODE;
542 make_room_in_stream (stream, stream->index + len);
543 memset (stream->data + stream->index, 0, len);
545 stream->index += len;
550 stream_data_align (MonoDynamicStream *stream)
552 MONO_REQ_GC_NEUTRAL_MODE;
555 guint32 count = stream->index % 4;
557 /* we assume the stream data will be aligned */
559 mono_image_add_stream_data (stream, buf, 4 - count);
562 #ifndef DISABLE_REFLECTION_EMIT
564 mono_blob_entry_hash (const char* str)
566 MONO_REQ_GC_NEUTRAL_MODE;
570 len = mono_metadata_decode_blob_size (str, &str);
574 for (str += 1; str < end; str++)
575 h = (h << 5) - h + *str;
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584 MONO_REQ_GC_NEUTRAL_MODE;
589 len = mono_metadata_decode_blob_size (str1, &end1);
590 len2 = mono_metadata_decode_blob_size (str2, &end2);
593 return memcmp (end1, end2, len) == 0;
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
599 MONO_REQ_GC_NEUTRAL_MODE;
603 gpointer oldkey, oldval;
605 copy = (char *)g_malloc (s1+s2);
606 memcpy (copy, b1, s1);
607 memcpy (copy + s1, b2, s2);
608 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
610 idx = GPOINTER_TO_UINT (oldval);
612 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613 mono_image_add_stream_data (&assembly->blob, b2, s2);
614 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
622 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 size = buf->p - buf->buf;
628 g_assert (size <= (buf->end - buf->buf));
629 mono_metadata_encode_value (size, b, &b);
630 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
634 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635 * dest may be misaligned.
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639 MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
643 for (elem = 0; elem < nelem; ++elem) {
669 g_assert_not_reached ();
675 memcpy (dest, val, len * nelem);
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
682 MONO_REQ_GC_UNSAFE_MODE;
686 guint32 idx = 0, len;
688 len = str->length * 2;
689 mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
692 char *swapped = g_malloc (2 * mono_string_length (str));
693 const char *p = (const char*)mono_string_chars (str);
695 swap_with_size (swapped, p, 2, mono_string_length (str));
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
700 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
705 #ifndef DISABLE_REFLECTION_EMIT
707 default_class_from_mono_type (MonoType *type)
709 MONO_REQ_GC_NEUTRAL_MODE;
711 switch (type->type) {
712 case MONO_TYPE_OBJECT:
713 return mono_defaults.object_class;
715 return mono_defaults.void_class;
716 case MONO_TYPE_BOOLEAN:
717 return mono_defaults.boolean_class;
719 return mono_defaults.char_class;
721 return mono_defaults.sbyte_class;
723 return mono_defaults.byte_class;
725 return mono_defaults.int16_class;
727 return mono_defaults.uint16_class;
729 return mono_defaults.int32_class;
731 return mono_defaults.uint32_class;
733 return mono_defaults.int_class;
735 return mono_defaults.uint_class;
737 return mono_defaults.int64_class;
739 return mono_defaults.uint64_class;
741 return mono_defaults.single_class;
743 return mono_defaults.double_class;
744 case MONO_TYPE_STRING:
745 return mono_defaults.string_class;
747 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748 g_assert_not_reached ();
756 * mono_class_get_ref_info:
758 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
761 mono_class_get_ref_info (MonoClass *klass)
763 MONO_REQ_GC_UNSAFE_MODE;
765 if (klass->ref_info_handle == 0)
768 return mono_gchandle_get_target (klass->ref_info_handle);
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
774 MONO_REQ_GC_UNSAFE_MODE;
776 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777 g_assert (klass->ref_info_handle != 0);
781 mono_class_free_ref_info (MonoClass *klass)
783 MONO_REQ_GC_NEUTRAL_MODE;
785 if (klass->ref_info_handle) {
786 mono_gchandle_free (klass->ref_info_handle);
787 klass->ref_info_handle = 0;
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
794 MONO_REQ_GC_NEUTRAL_MODE;
797 MonoGenericInst *class_inst;
802 class_inst = gclass->context.class_inst;
804 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805 klass = gclass->container_class;
806 sigbuffer_add_value (buf, klass->byval_arg.type);
807 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
809 sigbuffer_add_value (buf, class_inst->type_argc);
810 for (i = 0; i < class_inst->type_argc; ++i)
811 encode_type (assembly, class_inst->type_argv [i], buf);
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
818 MONO_REQ_GC_NEUTRAL_MODE;
821 g_assert_not_reached ();
826 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
830 case MONO_TYPE_BOOLEAN:
844 case MONO_TYPE_STRING:
845 case MONO_TYPE_OBJECT:
846 case MONO_TYPE_TYPEDBYREF:
847 sigbuffer_add_value (buf, type->type);
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, type->data.type, buf);
853 case MONO_TYPE_SZARRAY:
854 sigbuffer_add_value (buf, type->type);
855 encode_type (assembly, &type->data.klass->byval_arg, buf);
857 case MONO_TYPE_VALUETYPE:
858 case MONO_TYPE_CLASS: {
859 MonoClass *k = mono_class_from_mono_type (type);
861 if (k->generic_container) {
862 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863 encode_generic_class (assembly, gclass, buf);
866 * Make sure we use the correct type.
868 sigbuffer_add_value (buf, k->byval_arg.type);
870 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871 * otherwise two typerefs could point to the same type, leading to
872 * verification errors.
874 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
878 case MONO_TYPE_ARRAY:
879 sigbuffer_add_value (buf, type->type);
880 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881 sigbuffer_add_value (buf, type->data.array->rank);
882 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883 sigbuffer_add_value (buf, 0);
885 case MONO_TYPE_GENERICINST:
886 encode_generic_class (assembly, type->data.generic_class, buf);
890 sigbuffer_add_value (buf, type->type);
891 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
894 g_error ("need to encode type %x", type->type);
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
901 MONO_REQ_GC_UNSAFE_MODE;
904 sigbuffer_add_value (buf, MONO_TYPE_VOID);
908 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
914 MONO_REQ_GC_UNSAFE_MODE;
919 for (i = 0; i < mono_array_length (modreq); ++i) {
920 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926 for (i = 0; i < mono_array_length (modopt); ++i) {
927 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
934 #ifndef DISABLE_REFLECTION_EMIT
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
938 MONO_REQ_GC_UNSAFE_MODE;
942 guint32 nparams = sig->param_count;
948 sigbuffer_init (&buf, 32);
950 * FIXME: vararg, explicit_this, differenc call_conv values...
952 idx = sig->call_convention;
954 idx |= 0x20; /* hasthis */
955 if (sig->generic_param_count)
956 idx |= 0x10; /* generic */
957 sigbuffer_add_byte (&buf, idx);
958 if (sig->generic_param_count)
959 sigbuffer_add_value (&buf, sig->generic_param_count);
960 sigbuffer_add_value (&buf, nparams);
961 encode_type (assembly, sig->ret, &buf);
962 for (i = 0; i < nparams; ++i) {
963 if (i == sig->sentinelpos)
964 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965 encode_type (assembly, sig->params [i], &buf);
967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968 sigbuffer_free (&buf);
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
976 MONO_REQ_GC_UNSAFE_MODE;
979 * FIXME: reuse code from method_encode_signature().
983 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
984 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
988 sigbuffer_init (&buf, 32);
989 /* LAMESPEC: all the call conv spec is foobared */
990 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991 if (mb->call_conv & 2)
992 idx |= 0x5; /* vararg */
993 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994 idx |= 0x20; /* hasthis */
996 idx |= 0x10; /* generic */
997 sigbuffer_add_byte (&buf, idx);
999 sigbuffer_add_value (&buf, ngparams);
1000 sigbuffer_add_value (&buf, nparams + notypes);
1001 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002 encode_reflection_type (assembly, mb->rtype, &buf);
1003 for (i = 0; i < nparams; ++i) {
1004 MonoArray *modreq = NULL;
1005 MonoArray *modopt = NULL;
1006 MonoReflectionType *pt;
1008 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014 encode_reflection_type (assembly, pt, &buf);
1017 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018 for (i = 0; i < notypes; ++i) {
1019 MonoReflectionType *pt;
1021 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022 encode_reflection_type (assembly, pt, &buf);
1025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026 sigbuffer_free (&buf);
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1033 MONO_REQ_GC_UNSAFE_MODE;
1035 MonoDynamicTable *table;
1037 guint32 idx, sig_idx;
1038 guint nl = mono_array_length (ilgen->locals);
1042 sigbuffer_init (&buf, 32);
1043 sigbuffer_add_value (&buf, 0x07);
1044 sigbuffer_add_value (&buf, nl);
1045 for (i = 0; i < nl; ++i) {
1046 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1049 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1051 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1053 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1056 if (assembly->standalonesig_cache == NULL)
1057 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1062 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063 idx = table->next_idx ++;
1065 alloc_table (table, table->rows);
1066 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1068 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1070 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1078 MONO_REQ_GC_UNSAFE_MODE;
1080 guint32 num_clauses = 0;
1083 MonoILExceptionInfo *ex_info;
1084 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086 if (ex_info->handlers)
1087 num_clauses += mono_array_length (ex_info->handlers);
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 MonoExceptionClause *clauses;
1102 MonoExceptionClause *clause;
1103 MonoILExceptionInfo *ex_info;
1104 MonoILExceptionBlock *ex_block;
1105 guint32 finally_start;
1106 int i, j, clause_index;;
1108 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1111 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113 finally_start = ex_info->start + ex_info->len;
1114 if (!ex_info->handlers)
1116 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118 clause = &(clauses [clause_index]);
1120 clause->flags = ex_block->type;
1121 clause->try_offset = ex_info->start;
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124 clause->try_len = finally_start - ex_info->start;
1126 clause->try_len = ex_info->len;
1127 clause->handler_offset = ex_block->start;
1128 clause->handler_len = ex_block->len;
1129 if (ex_block->extype) {
1130 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1132 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133 clause->data.filter_offset = ex_block->filter_offset;
1135 clause->data.filter_offset = 0;
1137 finally_start = ex_block->start + ex_block->len;
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1148 * method_encode_code:
1150 * @assembly the assembly
1151 * @mb the managed MethodBuilder
1152 * @error set on error
1154 * Note that the return value is not sensible if @error is set.
1157 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1159 MONO_REQ_GC_UNSAFE_MODE;
1164 gint32 max_stack, i;
1165 gint32 num_locals = 0;
1166 gint32 num_exception = 0;
1169 char fat_header [12];
1171 guint16 short_value;
1172 guint32 local_sig = 0;
1173 guint32 header_size = 12;
1176 mono_error_init (error);
1178 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1179 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1183 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1185 code = mb->ilgen->code;
1186 code_size = mb->ilgen->code_len;
1187 max_stack = mb->ilgen->max_stack;
1188 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1189 if (mb->ilgen->ex_handlers)
1190 num_exception = method_count_clauses (mb->ilgen);
1194 char *name = mono_string_to_utf8 (mb->name);
1195 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1196 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1202 code_size = mono_array_length (code);
1203 max_stack = 8; /* we probably need to run a verifier on the code... */
1206 stream_data_align (&assembly->code);
1208 /* check for exceptions, maxstack, locals */
1209 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1211 if (code_size < 64 && !(code_size & 1)) {
1212 flags = (code_size << 2) | 0x2;
1213 } else if (code_size < 32 && (code_size & 1)) {
1214 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1218 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1219 /* add to the fixup todo list */
1220 if (mb->ilgen && mb->ilgen->num_token_fixups)
1221 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1222 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1223 return assembly->text_rva + idx;
1227 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1229 * FIXME: need to set also the header size in fat_flags.
1230 * (and more sects and init locals flags)
1234 fat_flags |= METHOD_HEADER_MORE_SECTS;
1235 if (mb->init_locals)
1236 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1237 fat_header [0] = fat_flags;
1238 fat_header [1] = (header_size / 4 ) << 4;
1239 short_value = GUINT16_TO_LE (max_stack);
1240 memcpy (fat_header + 2, &short_value, 2);
1241 int_value = GUINT32_TO_LE (code_size);
1242 memcpy (fat_header + 4, &int_value, 4);
1243 int_value = GUINT32_TO_LE (local_sig);
1244 memcpy (fat_header + 8, &int_value, 4);
1245 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1246 /* add to the fixup todo list */
1247 if (mb->ilgen && mb->ilgen->num_token_fixups)
1248 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1250 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1251 if (num_exception) {
1252 unsigned char sheader [4];
1253 MonoILExceptionInfo * ex_info;
1254 MonoILExceptionBlock * ex_block;
1257 stream_data_align (&assembly->code);
1258 /* always use fat format for now */
1259 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1260 num_exception *= 6 * sizeof (guint32);
1261 num_exception += 4; /* include the size of the header */
1262 sheader [1] = num_exception & 0xff;
1263 sheader [2] = (num_exception >> 8) & 0xff;
1264 sheader [3] = (num_exception >> 16) & 0xff;
1265 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1266 /* fat header, so we are already aligned */
1268 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1269 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1270 if (ex_info->handlers) {
1271 int finally_start = ex_info->start + ex_info->len;
1272 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1274 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1276 val = GUINT32_TO_LE (ex_block->type);
1277 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279 val = GUINT32_TO_LE (ex_info->start);
1280 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1281 /* need fault, too, probably */
1282 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1283 val = GUINT32_TO_LE (finally_start - ex_info->start);
1285 val = GUINT32_TO_LE (ex_info->len);
1286 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1287 /* handler offset */
1288 val = GUINT32_TO_LE (ex_block->start);
1289 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1291 val = GUINT32_TO_LE (ex_block->len);
1292 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293 finally_start = ex_block->start + ex_block->len;
1294 if (ex_block->extype) {
1295 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1297 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1298 val = ex_block->filter_offset;
1302 val = GUINT32_TO_LE (val);
1303 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1304 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1305 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1308 g_error ("No clauses for ex info block %d", i);
1312 return assembly->text_rva + idx;
1316 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1318 MONO_REQ_GC_NEUTRAL_MODE;
1321 MonoDynamicTable *table;
1324 table = &assembly->tables [table_idx];
1326 g_assert (col < table->columns);
1328 values = table->values + table->columns;
1329 for (i = 1; i <= table->rows; ++i) {
1330 if (values [col] == token)
1332 values += table->columns;
1338 * LOCKING: Acquires the loader lock.
1340 static MonoCustomAttrInfo*
1341 lookup_custom_attr (MonoImage *image, gpointer member)
1343 MONO_REQ_GC_NEUTRAL_MODE;
1345 MonoCustomAttrInfo* res;
1347 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1352 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1358 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1360 MONO_REQ_GC_UNSAFE_MODE;
1362 /* FIXME: Need to do more checks */
1363 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1364 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1366 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1373 static MonoCustomAttrInfo*
1374 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1376 MONO_REQ_GC_UNSAFE_MODE;
1378 int i, index, count, not_visible;
1379 MonoCustomAttrInfo *ainfo;
1380 MonoReflectionCustomAttr *cattr;
1384 /* FIXME: check in assembly the Run flag is set */
1386 count = mono_array_length (cattrs);
1388 /* Skip nonpublic attributes since MS.NET seems to do the same */
1389 /* FIXME: This needs to be done more globally */
1391 for (i = 0; i < count; ++i) {
1392 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1393 if (!custom_attr_visible (image, cattr))
1396 count -= not_visible;
1398 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1400 ainfo->image = image;
1401 ainfo->num_attrs = count;
1402 ainfo->cached = alloc_img != NULL;
1404 for (i = 0; i < count; ++i) {
1405 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1406 if (custom_attr_visible (image, cattr)) {
1407 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1408 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1409 ainfo->attrs [index].ctor = cattr->ctor->method;
1410 ainfo->attrs [index].data = saved;
1411 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1419 #ifndef DISABLE_REFLECTION_EMIT
1421 * LOCKING: Acquires the loader lock.
1424 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1426 MONO_REQ_GC_UNSAFE_MODE;
1428 MonoCustomAttrInfo *ainfo, *tmp;
1430 if (!cattrs || !mono_array_length (cattrs))
1433 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1435 mono_loader_lock ();
1436 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1438 mono_custom_attrs_free (tmp);
1439 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1440 mono_loader_unlock ();
1446 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1448 MONO_REQ_GC_NEUTRAL_MODE;
1455 * idx is the table index of the object
1456 * type is one of MONO_CUSTOM_ATTR_*
1459 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1461 MONO_REQ_GC_UNSAFE_MODE;
1463 MonoDynamicTable *table;
1464 MonoReflectionCustomAttr *cattr;
1466 guint32 count, i, token;
1468 char *p = blob_size;
1470 mono_error_init (error);
1472 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1475 count = mono_array_length (cattrs);
1476 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1477 table->rows += count;
1478 alloc_table (table, table->rows);
1479 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1480 idx <<= MONO_CUSTOM_ATTR_BITS;
1482 for (i = 0; i < count; ++i) {
1483 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1485 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1486 if (!mono_error_ok (error)) goto fail;
1487 type = mono_metadata_token_index (token);
1488 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1489 switch (mono_metadata_token_table (token)) {
1490 case MONO_TABLE_METHOD:
1491 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1493 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1494 * method, not the one returned by mono_image_create_token ().
1496 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1498 case MONO_TABLE_MEMBERREF:
1499 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1502 g_warning ("got wrong token in custom attr");
1505 values [MONO_CUSTOM_ATTR_TYPE] = type;
1507 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1508 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1509 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1510 values += MONO_CUSTOM_ATTR_SIZE;
1521 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1523 MONO_REQ_GC_UNSAFE_MODE;
1525 MonoDynamicTable *table;
1527 guint32 count, i, idx;
1528 MonoReflectionPermissionSet *perm;
1533 count = mono_array_length (permissions);
1534 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1535 table->rows += count;
1536 alloc_table (table, table->rows);
1538 for (i = 0; i < mono_array_length (permissions); ++i) {
1539 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1541 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1543 idx = mono_metadata_token_index (parent_token);
1544 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1545 switch (mono_metadata_token_table (parent_token)) {
1546 case MONO_TABLE_TYPEDEF:
1547 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1549 case MONO_TABLE_METHOD:
1550 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1552 case MONO_TABLE_ASSEMBLY:
1553 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1556 g_assert_not_reached ();
1559 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1560 values [MONO_DECL_SECURITY_PARENT] = idx;
1561 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1568 * Fill in the MethodDef and ParamDef tables for a method.
1569 * This is used for both normal methods and constructors.
1572 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1574 MONO_REQ_GC_UNSAFE_MODE;
1576 MonoDynamicTable *table;
1580 mono_error_init (error);
1582 /* room in this table is already allocated */
1583 table = &assembly->tables [MONO_TABLE_METHOD];
1584 *mb->table_idx = table->next_idx ++;
1585 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1586 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1587 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1588 values [MONO_METHOD_FLAGS] = mb->attrs;
1589 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1590 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1591 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1592 if (!mono_error_ok (error))
1595 table = &assembly->tables [MONO_TABLE_PARAM];
1596 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1598 mono_image_add_decl_security (assembly,
1599 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1602 MonoDynamicTable *mtable;
1605 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1606 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1609 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1610 if (mono_array_get (mb->pinfo, gpointer, i))
1613 table->rows += count;
1614 alloc_table (table, table->rows);
1615 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1616 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1617 MonoReflectionParamBuilder *pb;
1618 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1619 values [MONO_PARAM_FLAGS] = pb->attrs;
1620 values [MONO_PARAM_SEQUENCE] = i;
1621 if (pb->name != NULL) {
1622 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1624 values [MONO_PARAM_NAME] = 0;
1626 values += MONO_PARAM_SIZE;
1627 if (pb->marshal_info) {
1629 alloc_table (mtable, mtable->rows);
1630 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1631 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1632 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1634 pb->table_idx = table->next_idx++;
1635 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1636 guint32 field_type = 0;
1637 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1639 alloc_table (mtable, mtable->rows);
1640 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1641 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1642 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1643 mvalues [MONO_CONSTANT_TYPE] = field_type;
1644 mvalues [MONO_CONSTANT_PADDING] = 0;
1653 #ifndef DISABLE_REFLECTION_EMIT
1655 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1657 MONO_REQ_GC_UNSAFE_MODE;
1659 mono_error_init (error);
1660 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1662 rmb->ilgen = mb->ilgen;
1663 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1664 return_val_if_nok (error, FALSE);
1665 rmb->parameters = mb->parameters;
1666 rmb->generic_params = mb->generic_params;
1667 rmb->generic_container = mb->generic_container;
1668 rmb->opt_types = NULL;
1669 rmb->pinfo = mb->pinfo;
1670 rmb->attrs = mb->attrs;
1671 rmb->iattrs = mb->iattrs;
1672 rmb->call_conv = mb->call_conv;
1673 rmb->code = mb->code;
1674 rmb->type = mb->type;
1675 rmb->name = mb->name;
1676 rmb->table_idx = &mb->table_idx;
1677 rmb->init_locals = mb->init_locals;
1678 rmb->skip_visibility = FALSE;
1679 rmb->return_modreq = mb->return_modreq;
1680 rmb->return_modopt = mb->return_modopt;
1681 rmb->param_modreq = mb->param_modreq;
1682 rmb->param_modopt = mb->param_modopt;
1683 rmb->permissions = mb->permissions;
1684 rmb->mhandle = mb->mhandle;
1689 rmb->charset = mb->charset;
1690 rmb->extra_flags = mb->extra_flags;
1691 rmb->native_cc = mb->native_cc;
1692 rmb->dllentry = mb->dllentry;
1700 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1702 MONO_REQ_GC_UNSAFE_MODE;
1704 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1706 mono_error_init (error);
1708 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1710 rmb->ilgen = mb->ilgen;
1711 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1712 return_val_if_nok (error, FALSE);
1713 rmb->parameters = mb->parameters;
1714 rmb->generic_params = NULL;
1715 rmb->generic_container = NULL;
1716 rmb->opt_types = NULL;
1717 rmb->pinfo = mb->pinfo;
1718 rmb->attrs = mb->attrs;
1719 rmb->iattrs = mb->iattrs;
1720 rmb->call_conv = mb->call_conv;
1722 rmb->type = mb->type;
1723 rmb->name = mono_string_new (mono_domain_get (), name);
1724 rmb->table_idx = &mb->table_idx;
1725 rmb->init_locals = mb->init_locals;
1726 rmb->skip_visibility = FALSE;
1727 rmb->return_modreq = NULL;
1728 rmb->return_modopt = NULL;
1729 rmb->param_modreq = mb->param_modreq;
1730 rmb->param_modopt = mb->param_modopt;
1731 rmb->permissions = mb->permissions;
1732 rmb->mhandle = mb->mhandle;
1740 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1742 MONO_REQ_GC_UNSAFE_MODE;
1744 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1746 rmb->ilgen = mb->ilgen;
1747 rmb->rtype = mb->rtype;
1748 rmb->parameters = mb->parameters;
1749 rmb->generic_params = NULL;
1750 rmb->generic_container = NULL;
1751 rmb->opt_types = NULL;
1753 rmb->attrs = mb->attrs;
1755 rmb->call_conv = mb->call_conv;
1757 rmb->type = (MonoObject *) mb->owner;
1758 rmb->name = mb->name;
1759 rmb->table_idx = NULL;
1760 rmb->init_locals = mb->init_locals;
1761 rmb->skip_visibility = mb->skip_visibility;
1762 rmb->return_modreq = NULL;
1763 rmb->return_modopt = NULL;
1764 rmb->param_modreq = NULL;
1765 rmb->param_modopt = NULL;
1766 rmb->permissions = NULL;
1767 rmb->mhandle = mb->mhandle;
1774 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1776 MONO_REQ_GC_UNSAFE_MODE;
1778 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1779 MonoDynamicTable *table;
1782 MonoReflectionMethod *m;
1785 mono_error_init (error);
1787 if (!mb->override_methods)
1790 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1791 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1793 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1795 alloc_table (table, table->rows);
1796 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1797 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1798 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1800 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1801 return_val_if_nok (error, FALSE);
1803 switch (mono_metadata_token_table (tok)) {
1804 case MONO_TABLE_MEMBERREF:
1805 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1807 case MONO_TABLE_METHOD:
1808 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1811 g_assert_not_reached ();
1813 values [MONO_METHODIMPL_DECLARATION] = tok;
1819 #ifndef DISABLE_REFLECTION_EMIT
1821 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1823 MONO_REQ_GC_UNSAFE_MODE;
1825 MonoDynamicTable *table;
1827 ReflectionMethodBuilder rmb;
1830 mono_error_init (error);
1832 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1833 !mono_image_basic_method (&rmb, assembly, error))
1836 mb->table_idx = *rmb.table_idx;
1838 if (mb->dll) { /* It's a P/Invoke method */
1840 /* map CharSet values to on-disk values */
1841 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1842 int extra_flags = mb->extra_flags;
1843 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1845 alloc_table (table, table->rows);
1846 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1848 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1849 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1851 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1853 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1854 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1855 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1856 table = &assembly->tables [MONO_TABLE_MODULEREF];
1858 alloc_table (table, table->rows);
1859 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1860 values [MONO_IMPLMAP_SCOPE] = table->rows;
1864 if (mb->generic_params) {
1865 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1866 table->rows += mono_array_length (mb->generic_params);
1867 alloc_table (table, table->rows);
1868 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1869 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1871 mono_image_get_generic_param_info (
1872 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1880 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1882 MONO_REQ_GC_UNSAFE_MODE;
1884 ReflectionMethodBuilder rmb;
1886 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1889 if (!mono_image_basic_method (&rmb, assembly, error))
1892 mb->table_idx = *rmb.table_idx;
1899 type_get_fully_qualified_name (MonoType *type)
1901 MONO_REQ_GC_NEUTRAL_MODE;
1903 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1907 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1909 MONO_REQ_GC_UNSAFE_MODE;
1914 klass = mono_class_from_mono_type (type);
1916 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1917 ta = klass->image->assembly;
1918 if (assembly_is_dynamic (ta) || (ta == ass)) {
1919 if (klass->generic_class || klass->generic_container)
1920 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1921 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1923 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1926 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1929 #ifndef DISABLE_REFLECTION_EMIT
1930 /*field_image is the image to which the eventual custom mods have been encoded against*/
1932 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1934 MONO_REQ_GC_NEUTRAL_MODE;
1937 guint32 idx, i, token;
1939 if (!assembly->save)
1942 sigbuffer_init (&buf, 32);
1944 sigbuffer_add_value (&buf, 0x06);
1945 /* encode custom attributes before the type */
1946 if (type->num_mods) {
1947 for (i = 0; i < type->num_mods; ++i) {
1950 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1951 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1953 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1955 token = type->modifiers [i].token;
1958 if (type->modifiers [i].required)
1959 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1961 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1963 sigbuffer_add_value (&buf, token);
1966 encode_type (assembly, type, &buf);
1967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1968 sigbuffer_free (&buf);
1974 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1976 MONO_REQ_GC_UNSAFE_MODE;
1980 guint32 typespec = 0;
1984 init_type_builder_generics (fb->type);
1986 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1987 klass = mono_class_from_mono_type (type);
1989 sigbuffer_init (&buf, 32);
1991 sigbuffer_add_value (&buf, 0x06);
1992 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1993 /* encode custom attributes before the type */
1995 if (klass->generic_container)
1996 typespec = create_typespec (assembly, type);
1999 MonoGenericClass *gclass;
2000 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2001 encode_generic_class (assembly, gclass, &buf);
2003 encode_type (assembly, type, &buf);
2005 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2006 sigbuffer_free (&buf);
2011 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2013 MONO_REQ_GC_UNSAFE_MODE;
2015 char blob_size [64];
2016 char *b = blob_size;
2019 guint32 idx = 0, len = 0, dummy = 0;
2021 buf = (char *)g_malloc (64);
2023 *ret_type = MONO_TYPE_CLASS;
2025 box_val = (char*)&dummy;
2027 box_val = ((char*)val) + sizeof (MonoObject);
2028 *ret_type = val->vtable->klass->byval_arg.type;
2031 switch (*ret_type) {
2032 case MONO_TYPE_BOOLEAN:
2037 case MONO_TYPE_CHAR:
2054 case MONO_TYPE_VALUETYPE: {
2055 MonoClass *klass = val->vtable->klass;
2057 if (klass->enumtype) {
2058 *ret_type = mono_class_enum_basetype (klass)->type;
2060 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2063 g_error ("we can't encode valuetypes, we should have never reached this line");
2066 case MONO_TYPE_CLASS:
2068 case MONO_TYPE_STRING: {
2069 MonoString *str = (MonoString*)val;
2070 /* there is no signature */
2071 len = str->length * 2;
2072 mono_metadata_encode_value (len, b, &b);
2073 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2075 char *swapped = g_malloc (2 * mono_string_length (str));
2076 const char *p = (const char*)mono_string_chars (str);
2078 swap_with_size (swapped, p, 2, mono_string_length (str));
2079 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2083 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2089 case MONO_TYPE_GENERICINST:
2090 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2093 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2096 /* there is no signature */
2097 mono_metadata_encode_value (len, b, &b);
2098 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2099 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2100 swap_with_size (blob_size, box_val, len, 1);
2101 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2103 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2111 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2113 MONO_REQ_GC_UNSAFE_MODE;
2119 sigbuffer_init (&buf, 32);
2121 sigbuffer_add_value (&buf, minfo->type);
2123 switch (minfo->type) {
2124 case MONO_NATIVE_BYVALTSTR:
2125 case MONO_NATIVE_BYVALARRAY:
2126 sigbuffer_add_value (&buf, minfo->count);
2128 case MONO_NATIVE_LPARRAY:
2129 if (minfo->eltype || minfo->has_size) {
2130 sigbuffer_add_value (&buf, minfo->eltype);
2131 if (minfo->has_size) {
2132 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2133 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2135 /* LAMESPEC: ElemMult is undocumented */
2136 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2140 case MONO_NATIVE_SAFEARRAY:
2142 sigbuffer_add_value (&buf, minfo->eltype);
2144 case MONO_NATIVE_CUSTOM:
2146 str = mono_string_to_utf8 (minfo->guid);
2148 sigbuffer_add_value (&buf, len);
2149 sigbuffer_add_mem (&buf, str, len);
2152 sigbuffer_add_value (&buf, 0);
2154 /* native type name */
2155 sigbuffer_add_value (&buf, 0);
2156 /* custom marshaler type name */
2157 if (minfo->marshaltype || minfo->marshaltyperef) {
2158 if (minfo->marshaltyperef)
2159 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2161 str = mono_string_to_utf8 (minfo->marshaltype);
2163 sigbuffer_add_value (&buf, len);
2164 sigbuffer_add_mem (&buf, str, len);
2167 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2168 sigbuffer_add_value (&buf, 0);
2170 if (minfo->mcookie) {
2171 str = mono_string_to_utf8 (minfo->mcookie);
2173 sigbuffer_add_value (&buf, len);
2174 sigbuffer_add_mem (&buf, str, len);
2177 sigbuffer_add_value (&buf, 0);
2183 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2184 sigbuffer_free (&buf);
2189 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2191 MONO_REQ_GC_UNSAFE_MODE;
2193 MonoDynamicTable *table;
2196 /* maybe this fixup should be done in the C# code */
2197 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2198 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2199 table = &assembly->tables [MONO_TABLE_FIELD];
2200 fb->table_idx = table->next_idx ++;
2201 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2202 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2203 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2204 values [MONO_FIELD_FLAGS] = fb->attrs;
2205 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2207 if (fb->offset != -1) {
2208 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2210 alloc_table (table, table->rows);
2211 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2212 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2213 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2215 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2216 MonoTypeEnum field_type = (MonoTypeEnum)0;
2217 table = &assembly->tables [MONO_TABLE_CONSTANT];
2219 alloc_table (table, table->rows);
2220 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2221 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2222 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2223 values [MONO_CONSTANT_TYPE] = field_type;
2224 values [MONO_CONSTANT_PADDING] = 0;
2226 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2228 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2230 alloc_table (table, table->rows);
2231 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2232 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2234 * We store it in the code section because it's simpler for now.
2237 if (mono_array_length (fb->rva_data) >= 10)
2238 stream_data_align (&assembly->code);
2239 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2241 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2242 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2244 if (fb->marshal_info) {
2245 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2247 alloc_table (table, table->rows);
2248 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2249 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2250 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2255 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2257 MONO_REQ_GC_UNSAFE_MODE;
2260 guint32 nparams = 0;
2261 MonoReflectionMethodBuilder *mb = fb->get_method;
2262 MonoReflectionMethodBuilder *smb = fb->set_method;
2265 if (mb && mb->parameters)
2266 nparams = mono_array_length (mb->parameters);
2267 if (!mb && smb && smb->parameters)
2268 nparams = mono_array_length (smb->parameters) - 1;
2269 sigbuffer_init (&buf, 32);
2270 if (fb->call_conv & 0x20)
2271 sigbuffer_add_byte (&buf, 0x28);
2273 sigbuffer_add_byte (&buf, 0x08);
2274 sigbuffer_add_value (&buf, nparams);
2276 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2277 for (i = 0; i < nparams; ++i) {
2278 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2279 encode_reflection_type (assembly, pt, &buf);
2281 } else if (smb && smb->parameters) {
2282 /* the property type is the last param */
2283 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2284 for (i = 0; i < nparams; ++i) {
2285 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2286 encode_reflection_type (assembly, pt, &buf);
2289 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2292 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2293 sigbuffer_free (&buf);
2298 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2300 MONO_REQ_GC_UNSAFE_MODE;
2302 MonoDynamicTable *table;
2304 guint num_methods = 0;
2308 * we need to set things in the following tables:
2309 * PROPERTYMAP (info already filled in _get_type_info ())
2310 * PROPERTY (rows already preallocated in _get_type_info ())
2311 * METHOD (method info already done with the generic method code)
2315 table = &assembly->tables [MONO_TABLE_PROPERTY];
2316 pb->table_idx = table->next_idx ++;
2317 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2318 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2319 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2320 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2322 /* FIXME: we still don't handle 'other' methods */
2323 if (pb->get_method) num_methods ++;
2324 if (pb->set_method) num_methods ++;
2326 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2327 table->rows += num_methods;
2328 alloc_table (table, table->rows);
2330 if (pb->get_method) {
2331 semaidx = table->next_idx ++;
2332 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2333 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2334 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2335 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2337 if (pb->set_method) {
2338 semaidx = table->next_idx ++;
2339 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2340 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2341 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2342 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2344 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2345 MonoTypeEnum field_type = (MonoTypeEnum)0;
2346 table = &assembly->tables [MONO_TABLE_CONSTANT];
2348 alloc_table (table, table->rows);
2349 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2350 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2351 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2352 values [MONO_CONSTANT_TYPE] = field_type;
2353 values [MONO_CONSTANT_PADDING] = 0;
2358 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2360 MONO_REQ_GC_UNSAFE_MODE;
2362 MonoDynamicTable *table;
2364 guint num_methods = 0;
2368 * we need to set things in the following tables:
2369 * EVENTMAP (info already filled in _get_type_info ())
2370 * EVENT (rows already preallocated in _get_type_info ())
2371 * METHOD (method info already done with the generic method code)
2374 table = &assembly->tables [MONO_TABLE_EVENT];
2375 eb->table_idx = table->next_idx ++;
2376 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2377 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2378 values [MONO_EVENT_FLAGS] = eb->attrs;
2379 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2382 * FIXME: we still don't handle 'other' methods
2384 if (eb->add_method) num_methods ++;
2385 if (eb->remove_method) num_methods ++;
2386 if (eb->raise_method) num_methods ++;
2388 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2389 table->rows += num_methods;
2390 alloc_table (table, table->rows);
2392 if (eb->add_method) {
2393 semaidx = table->next_idx ++;
2394 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2395 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2396 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2397 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2399 if (eb->remove_method) {
2400 semaidx = table->next_idx ++;
2401 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2402 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2403 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2404 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2406 if (eb->raise_method) {
2407 semaidx = table->next_idx ++;
2408 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2409 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2410 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2411 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2416 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2418 MONO_REQ_GC_UNSAFE_MODE;
2420 MonoDynamicTable *table;
2421 guint32 num_constraints, i;
2425 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2426 num_constraints = gparam->iface_constraints ?
2427 mono_array_length (gparam->iface_constraints) : 0;
2428 table->rows += num_constraints;
2429 if (gparam->base_type)
2431 alloc_table (table, table->rows);
2433 if (gparam->base_type) {
2434 table_idx = table->next_idx ++;
2435 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2437 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2438 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2439 assembly, mono_reflection_type_get_handle (gparam->base_type));
2442 for (i = 0; i < num_constraints; i++) {
2443 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2444 gparam->iface_constraints, gpointer, i);
2446 table_idx = table->next_idx ++;
2447 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2449 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2450 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2451 assembly, mono_reflection_type_get_handle (constraint));
2456 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2458 MONO_REQ_GC_UNSAFE_MODE;
2460 GenericParamTableEntry *entry;
2463 * The GenericParam table must be sorted according to the `owner' field.
2464 * We need to do this sorting prior to writing the GenericParamConstraint
2465 * table, since we have to use the final GenericParam table indices there
2466 * and they must also be sorted.
2469 entry = g_new0 (GenericParamTableEntry, 1);
2470 entry->owner = owner;
2471 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2472 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2473 entry->gparam = gparam;
2475 g_ptr_array_add (assembly->gen_params, entry);
2479 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2481 MONO_REQ_GC_UNSAFE_MODE;
2483 MonoDynamicTable *table;
2484 MonoGenericParam *param;
2488 mono_error_init (error);
2490 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2491 table_idx = table->next_idx ++;
2492 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2494 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2496 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2497 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2498 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2499 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2501 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2504 encode_constraints (entry->gparam, table_idx, assembly);
2510 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2512 MONO_REQ_GC_UNSAFE_MODE;
2514 MonoDynamicTable *table;
2517 guint32 cols [MONO_ASSEMBLY_SIZE];
2521 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2524 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2525 table = &assembly->tables [MONO_TABLE_MODULEREF];
2526 token = table->next_idx ++;
2528 alloc_table (table, table->rows);
2529 values = table->values + token * MONO_MODULEREF_SIZE;
2530 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2532 token <<= MONO_RESOLUTION_SCOPE_BITS;
2533 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2534 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2539 if (assembly_is_dynamic (image->assembly))
2541 memset (cols, 0, sizeof (cols));
2543 /* image->assembly->image is the manifest module */
2544 image = image->assembly->image;
2545 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2548 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2549 token = table->next_idx ++;
2551 alloc_table (table, table->rows);
2552 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2553 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2554 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2555 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2556 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2557 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2558 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2559 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2560 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2562 if (strcmp ("", image->assembly->aname.culture)) {
2563 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2564 image->assembly->aname.culture);
2567 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2568 guchar pubtoken [9];
2570 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2571 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2573 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2575 token <<= MONO_RESOLUTION_SCOPE_BITS;
2576 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2577 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2582 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2584 MONO_REQ_GC_NEUTRAL_MODE;
2586 MonoDynamicTable *table;
2591 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2594 sigbuffer_init (&buf, 32);
2595 switch (type->type) {
2596 case MONO_TYPE_FNPTR:
2598 case MONO_TYPE_SZARRAY:
2599 case MONO_TYPE_ARRAY:
2601 case MONO_TYPE_MVAR:
2602 case MONO_TYPE_GENERICINST:
2603 encode_type (assembly, type, &buf);
2605 case MONO_TYPE_CLASS:
2606 case MONO_TYPE_VALUETYPE: {
2607 MonoClass *k = mono_class_from_mono_type (type);
2608 if (!k || !k->generic_container) {
2609 sigbuffer_free (&buf);
2612 encode_type (assembly, type, &buf);
2616 sigbuffer_free (&buf);
2620 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2621 if (assembly->save) {
2622 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2623 alloc_table (table, table->rows + 1);
2624 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2625 values [MONO_TYPESPEC_SIGNATURE] = token;
2627 sigbuffer_free (&buf);
2629 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2630 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2636 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2638 MONO_REQ_GC_UNSAFE_MODE;
2640 MonoDynamicTable *table;
2642 guint32 token, scope, enclosing;
2645 /* if the type requires a typespec, we must try that first*/
2646 if (try_typespec && (token = create_typespec (assembly, type)))
2648 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2651 klass = mono_class_from_mono_type (type);
2653 klass = mono_class_from_mono_type (type);
2656 * If it's in the same module and not a generic type parameter:
2658 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2659 (type->type != MONO_TYPE_MVAR)) {
2660 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2661 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2662 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2666 if (klass->nested_in) {
2667 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2668 /* get the typeref idx of the enclosing type */
2669 enclosing >>= MONO_TYPEDEFORREF_BITS;
2670 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2672 scope = resolution_scope_from_image (assembly, klass->image);
2674 table = &assembly->tables [MONO_TABLE_TYPEREF];
2675 if (assembly->save) {
2676 alloc_table (table, table->rows + 1);
2677 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2678 values [MONO_TYPEREF_SCOPE] = scope;
2679 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2680 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2682 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2683 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2685 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2690 * Despite the name, we handle also TypeSpec (with the above helper).
2693 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2695 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2698 #ifndef DISABLE_REFLECTION_EMIT
2700 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2702 MONO_REQ_GC_NEUTRAL_MODE;
2704 MonoDynamicTable *table;
2706 guint32 token, pclass;
2708 switch (parent & MONO_TYPEDEFORREF_MASK) {
2709 case MONO_TYPEDEFORREF_TYPEREF:
2710 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2712 case MONO_TYPEDEFORREF_TYPESPEC:
2713 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2715 case MONO_TYPEDEFORREF_TYPEDEF:
2716 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2719 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2722 /* extract the index */
2723 parent >>= MONO_TYPEDEFORREF_BITS;
2725 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2727 if (assembly->save) {
2728 alloc_table (table, table->rows + 1);
2729 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2730 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2731 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2732 values [MONO_MEMBERREF_SIGNATURE] = sig;
2735 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2742 * Insert a memberef row into the metadata: the token that point to the memberref
2743 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2744 * mono_image_get_fieldref_token()).
2745 * The sig param is an index to an already built signature.
2748 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2750 MONO_REQ_GC_NEUTRAL_MODE;
2752 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2753 return mono_image_add_memberef_row (assembly, parent, name, sig);
2758 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2760 MONO_REQ_GC_NEUTRAL_MODE;
2763 MonoMethodSignature *sig;
2765 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2767 if (create_typespec) {
2768 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2773 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2774 if (token && !create_typespec)
2777 g_assert (!method->is_inflated);
2780 * A methodref signature can't contain an unmanaged calling convention.
2782 sig = mono_metadata_signature_dup (mono_method_signature (method));
2783 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2784 sig->call_convention = MONO_CALL_DEFAULT;
2785 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2786 method->name, method_encode_signature (assembly, sig));
2788 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2791 if (create_typespec) {
2792 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2793 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2794 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2796 if (assembly->save) {
2799 alloc_table (table, table->rows + 1);
2800 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2801 values [MONO_METHODSPEC_METHOD] = token;
2802 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2805 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2807 /*methodspec and memberef tokens are diferent, */
2808 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2815 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2817 guint32 token, parent, sig;
2818 ReflectionMethodBuilder rmb;
2819 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2821 mono_error_init (error);
2822 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2826 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2830 * A methodref signature can't contain an unmanaged calling convention.
2831 * Since some flags are encoded as part of call_conv, we need to check against it.
2833 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2834 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2836 sig = method_builder_encode_signature (assembly, &rmb);
2838 if (tb->generic_params)
2839 parent = create_generic_typespec (assembly, tb);
2841 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2843 char *name = mono_string_to_utf8 (method->name);
2845 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2848 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2854 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2855 const gchar *name, guint32 sig)
2857 MonoDynamicTable *table;
2861 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2863 if (assembly->save) {
2864 alloc_table (table, table->rows + 1);
2865 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2866 values [MONO_MEMBERREF_CLASS] = original;
2867 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2868 values [MONO_MEMBERREF_SIGNATURE] = sig;
2871 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2878 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2882 guint32 nparams = mono_array_length (mb->generic_params);
2885 if (!assembly->save)
2888 sigbuffer_init (&buf, 32);
2890 sigbuffer_add_value (&buf, 0xa);
2891 sigbuffer_add_value (&buf, nparams);
2893 for (i = 0; i < nparams; i++) {
2894 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2895 sigbuffer_add_value (&buf, i);
2898 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2899 sigbuffer_free (&buf);
2904 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2906 MonoDynamicTable *table;
2908 guint32 token, mtoken = 0;
2910 mono_error_init (error);
2911 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2915 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2917 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2918 if (!mono_error_ok (error))
2921 switch (mono_metadata_token_table (mtoken)) {
2922 case MONO_TABLE_MEMBERREF:
2923 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2925 case MONO_TABLE_METHOD:
2926 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2929 g_assert_not_reached ();
2932 if (assembly->save) {
2933 alloc_table (table, table->rows + 1);
2934 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2935 values [MONO_METHODSPEC_METHOD] = mtoken;
2936 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2939 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2942 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2947 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2951 mono_error_init (error);
2953 if (mb->generic_params && create_methodspec)
2954 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2956 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2960 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2961 if (!mono_error_ok (error))
2963 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2968 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2970 guint32 token, parent, sig;
2971 ReflectionMethodBuilder rmb;
2973 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2975 mono_error_init (error);
2977 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2981 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
2984 if (tb->generic_params)
2985 parent = create_generic_typespec (assembly, tb);
2987 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2989 name = mono_string_to_utf8 (rmb.name);
2990 sig = method_builder_encode_signature (assembly, &rmb);
2992 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2995 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3001 is_field_on_inst (MonoClassField *field)
3003 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3007 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3010 get_field_on_inst_generic_type (MonoClassField *field)
3012 MonoClass *klass, *gtd;
3013 MonoDynamicGenericClass *dgclass;
3016 g_assert (is_field_on_inst (field));
3018 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3020 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3021 field_index = field - dgclass->fields;
3022 return dgclass->field_generic_types [field_index];
3025 klass = field->parent;
3026 gtd = klass->generic_class->container_class;
3028 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3029 field_index = field - klass->fields;
3030 return gtd->fields [field_index].type;
3033 g_assert_not_reached ();
3037 #ifndef DISABLE_REFLECTION_EMIT
3039 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3045 g_assert (field->parent);
3047 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3051 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3052 int index = field - field->parent->fields;
3053 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3055 if (is_field_on_inst (field))
3056 type = get_field_on_inst_generic_type (field);
3058 type = mono_field_get_type (field);
3060 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3061 mono_field_get_name (field),
3062 fieldref_encode_signature (assembly, field->parent->image, type));
3063 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3068 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3072 MonoGenericClass *gclass;
3076 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3079 if (is_sre_field_builder (mono_object_class (f->fb))) {
3080 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3081 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3082 klass = mono_class_from_mono_type (type);
3083 gclass = type->data.generic_class;
3084 g_assert (gclass->is_dynamic);
3086 name = mono_string_to_utf8 (fb->name);
3087 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3088 field_encode_signature (assembly, fb));
3090 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3092 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3094 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3095 klass = mono_class_from_mono_type (type);
3097 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3098 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3100 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3101 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3104 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3109 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3113 MonoGenericClass *gclass;
3116 mono_error_init (error);
3118 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3120 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3124 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3125 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3126 ReflectionMethodBuilder rmb;
3129 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3130 klass = mono_class_from_mono_type (type);
3132 gclass = type->data.generic_class;
3133 g_assert (gclass->is_dynamic);
3135 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3138 name = mono_string_to_utf8 (rmb.name);
3140 sig = method_builder_encode_signature (assembly, &rmb);
3142 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3144 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3145 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3147 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3148 klass = mono_class_from_mono_type (type);
3150 sig = method_encode_signature (assembly, mono_method_signature (mm));
3151 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3153 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3154 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3158 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3163 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3167 MonoGenericContext tmp_context;
3168 MonoType **type_argv;
3169 MonoGenericInst *ginst;
3170 MonoMethod *method, *inflated;
3173 init_type_builder_generics ((MonoObject*)m->inst);
3175 method = inflate_method (m->inst, (MonoObject*)m->mb, &error);
3176 mono_error_raise_exception (&error); /* FIXME don't raise here */
3178 klass = method->klass;
3180 if (m->method_args == NULL)
3183 if (method->is_inflated)
3184 method = ((MonoMethodInflated *) method)->declaring;
3186 count = mono_array_length (m->method_args);
3188 type_argv = g_new0 (MonoType *, count);
3189 for (i = 0; i < count; i++) {
3190 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3191 type_argv [i] = mono_reflection_type_get_handle (garg);
3193 ginst = mono_metadata_get_generic_inst (count, type_argv);
3196 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3197 tmp_context.method_inst = ginst;
3199 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3200 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3205 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3207 guint32 sig, token = 0;
3211 mono_error_init (error);
3213 if (m->method_args) {
3214 MonoMethod *inflated;
3216 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3217 if (create_methodspec)
3218 token = mono_image_get_methodspec_token (assembly, inflated);
3220 token = mono_image_get_inflated_method_token (assembly, inflated);
3224 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3228 if (is_sre_method_builder (mono_object_class (m->mb))) {
3229 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3230 MonoGenericClass *gclass;
3231 ReflectionMethodBuilder rmb;
3234 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3235 klass = mono_class_from_mono_type (type);
3236 gclass = type->data.generic_class;
3237 g_assert (gclass->is_dynamic);
3239 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3242 name = mono_string_to_utf8 (rmb.name);
3244 sig = method_builder_encode_signature (assembly, &rmb);
3246 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3248 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3249 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3251 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3252 klass = mono_class_from_mono_type (type);
3254 sig = method_encode_signature (assembly, mono_method_signature (mm));
3255 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3257 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3258 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3261 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3266 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3270 guint32 nparams = context->method_inst->type_argc;
3273 if (!assembly->save)
3276 sigbuffer_init (&buf, 32);
3278 * FIXME: vararg, explicit_this, differenc call_conv values...
3280 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3281 sigbuffer_add_value (&buf, nparams);
3283 for (i = 0; i < nparams; i++)
3284 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3286 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287 sigbuffer_free (&buf);
3292 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3294 MonoDynamicTable *table;
3296 guint32 token, mtoken = 0, sig;
3297 MonoMethodInflated *imethod;
3298 MonoMethod *declaring;
3300 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3302 g_assert (method->is_inflated);
3303 imethod = (MonoMethodInflated *) method;
3304 declaring = imethod->declaring;
3306 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3307 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3309 if (!mono_method_signature (declaring)->generic_param_count)
3312 switch (mono_metadata_token_table (mtoken)) {
3313 case MONO_TABLE_MEMBERREF:
3314 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3316 case MONO_TABLE_METHOD:
3317 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3320 g_assert_not_reached ();
3323 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3325 if (assembly->save) {
3326 alloc_table (table, table->rows + 1);
3327 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3328 values [MONO_METHODSPEC_METHOD] = mtoken;
3329 values [MONO_METHODSPEC_SIGNATURE] = sig;
3332 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3339 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3341 MonoMethodInflated *imethod;
3344 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3348 g_assert (method->is_inflated);
3349 imethod = (MonoMethodInflated *) method;
3351 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3352 token = method_encode_methodspec (assembly, method);
3354 guint32 sig = method_encode_signature (
3355 assembly, mono_method_signature (imethod->declaring));
3356 token = mono_image_get_memberref_token (
3357 assembly, &method->klass->byval_arg, method->name, sig);
3360 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3365 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3367 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3370 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3371 token = mono_image_get_memberref_token (
3372 assembly, &m->klass->byval_arg, m->name, sig);
3378 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3380 MonoDynamicTable *table;
3389 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3390 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3391 * Because of this, we must not insert it into the `typeref' hash table.
3393 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3394 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3398 sigbuffer_init (&buf, 32);
3400 g_assert (tb->generic_params);
3401 klass = mono_class_from_mono_type (type);
3403 if (tb->generic_container)
3404 mono_reflection_create_generic_class (tb);
3406 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3407 g_assert (klass->generic_container);
3408 sigbuffer_add_value (&buf, klass->byval_arg.type);
3409 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3411 count = mono_array_length (tb->generic_params);
3412 sigbuffer_add_value (&buf, count);
3413 for (i = 0; i < count; i++) {
3414 MonoReflectionGenericParam *gparam;
3416 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3418 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3421 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3423 if (assembly->save) {
3424 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3425 alloc_table (table, table->rows + 1);
3426 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3427 values [MONO_TYPESPEC_SIGNATURE] = token;
3429 sigbuffer_free (&buf);
3431 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3432 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3438 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3441 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3443 int i, count, len, pos;
3448 count += mono_array_length (modreq);
3450 count += mono_array_length (modopt);
3453 return mono_metadata_type_dup (NULL, type);
3455 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3456 t = (MonoType *)g_malloc (len);
3457 memcpy (t, type, MONO_SIZEOF_TYPE);
3459 t->num_mods = count;
3462 for (i = 0; i < mono_array_length (modreq); ++i) {
3463 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3464 t->modifiers [pos].required = 1;
3465 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3470 for (i = 0; i < mono_array_length (modopt); ++i) {
3471 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3472 t->modifiers [pos].required = 0;
3473 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3482 init_type_builder_generics (MonoObject *type)
3484 MonoReflectionTypeBuilder *tb;
3486 if (!is_sre_type_builder(mono_object_class (type)))
3488 tb = (MonoReflectionTypeBuilder *)type;
3490 if (tb && tb->generic_container)
3491 mono_reflection_create_generic_class (tb);
3495 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3497 MonoDynamicTable *table;
3498 MonoType *custom = NULL, *type;
3500 guint32 token, pclass, parent, sig;
3503 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3507 /* FIXME: is this call necessary? */
3508 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3509 name = mono_string_to_utf8 (fb->name);
3511 /*FIXME this is one more layer of ugliness due how types are created.*/
3512 init_type_builder_generics (fb->type);
3514 /* fb->type does not include the custom modifiers */
3515 /* FIXME: We should do this in one place when a fieldbuilder is created */
3516 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3517 if (fb->modreq || fb->modopt)
3518 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3520 sig = fieldref_encode_signature (assembly, NULL, type);
3523 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3524 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3526 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3527 parent >>= MONO_TYPEDEFORREF_BITS;
3529 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3531 if (assembly->save) {
3532 alloc_table (table, table->rows + 1);
3533 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3534 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3535 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3536 values [MONO_MEMBERREF_SIGNATURE] = sig;
3539 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3541 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3547 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3553 if (!assembly->save)
3556 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3557 g_assert (helper->type == 2);
3559 if (helper->arguments)
3560 nargs = mono_array_length (helper->arguments);
3564 sigbuffer_init (&buf, 32);
3566 /* Encode calling convention */
3567 /* Change Any to Standard */
3568 if ((helper->call_conv & 0x03) == 0x03)
3569 helper->call_conv = 0x01;
3570 /* explicit_this implies has_this */
3571 if (helper->call_conv & 0x40)
3572 helper->call_conv &= 0x20;
3574 if (helper->call_conv == 0) { /* Unmanaged */
3575 idx = helper->unmanaged_call_conv - 1;
3578 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3579 if (helper->call_conv & 0x02) /* varargs */
3583 sigbuffer_add_byte (&buf, idx);
3584 sigbuffer_add_value (&buf, nargs);
3585 encode_reflection_type (assembly, helper->return_type, &buf);
3586 for (i = 0; i < nargs; ++i) {
3587 MonoArray *modreqs = NULL;
3588 MonoArray *modopts = NULL;
3589 MonoReflectionType *pt;
3591 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3592 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3593 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3594 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3596 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3597 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3598 encode_reflection_type (assembly, pt, &buf);
3600 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3601 sigbuffer_free (&buf);
3607 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3610 MonoDynamicTable *table;
3613 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3614 idx = table->next_idx ++;
3616 alloc_table (table, table->rows);
3617 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3619 values [MONO_STAND_ALONE_SIGNATURE] =
3620 mono_reflection_encode_sighelper (assembly, helper);
3626 reflection_cc_to_file (int call_conv) {
3627 switch (call_conv & 0x3) {
3629 case 1: return MONO_CALL_DEFAULT;
3630 case 2: return MONO_CALL_VARARG;
3632 g_assert_not_reached ();
3636 #endif /* !DISABLE_REFLECTION_EMIT */
3640 MonoMethodSignature *sig;
3645 #ifndef DISABLE_REFLECTION_EMIT
3647 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3652 MonoMethodSignature *sig;
3656 name = mono_string_to_utf8 (m->name);
3657 nparams = mono_array_length (m->parameters);
3658 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3660 sig->sentinelpos = -1;
3661 sig->call_convention = reflection_cc_to_file (m->call_conv);
3662 sig->param_count = nparams;
3663 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3664 mtype = mono_reflection_type_get_handle (m->parent);
3665 for (i = 0; i < nparams; ++i)
3666 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3668 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3669 am = (ArrayMethod *)tmp->data;
3670 if (strcmp (name, am->name) == 0 &&
3671 mono_metadata_type_equal (am->parent, mtype) &&
3672 mono_metadata_signature_equal (am->sig, sig)) {
3675 m->table_idx = am->token & 0xffffff;
3679 am = g_new0 (ArrayMethod, 1);
3683 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3684 method_encode_signature (assembly, sig));
3685 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3686 m->table_idx = am->token & 0xffffff;
3691 * Insert into the metadata tables all the info about the TypeBuilder tb.
3692 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3695 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3697 MonoDynamicTable *table;
3699 int i, is_object = 0, is_system = 0;
3702 mono_error_init (error);
3704 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3705 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3706 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3707 n = mono_string_to_utf8 (tb->name);
3708 if (strcmp (n, "Object") == 0)
3710 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3712 n = mono_string_to_utf8 (tb->nspace);
3713 if (strcmp (n, "System") == 0)
3715 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3717 if (tb->parent && !(is_system && is_object) &&
3718 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3719 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3721 values [MONO_TYPEDEF_EXTENDS] = 0;
3723 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3724 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3727 * if we have explicitlayout or sequentiallayouts, output data in the
3728 * ClassLayout table.
3730 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3731 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3732 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3734 alloc_table (table, table->rows);
3735 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3736 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3737 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3738 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3741 /* handle interfaces */
3742 if (tb->interfaces) {
3743 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3745 table->rows += mono_array_length (tb->interfaces);
3746 alloc_table (table, table->rows);
3747 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3748 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3749 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3750 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3751 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3752 values += MONO_INTERFACEIMPL_SIZE;
3758 table = &assembly->tables [MONO_TABLE_FIELD];
3759 table->rows += tb->num_fields;
3760 alloc_table (table, table->rows);
3761 for (i = 0; i < tb->num_fields; ++i)
3762 mono_image_get_field_info (
3763 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3766 /* handle constructors */
3768 table = &assembly->tables [MONO_TABLE_METHOD];
3769 table->rows += mono_array_length (tb->ctors);
3770 alloc_table (table, table->rows);
3771 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3772 if (!mono_image_get_ctor_info (domain,
3773 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3779 /* handle methods */
3781 table = &assembly->tables [MONO_TABLE_METHOD];
3782 table->rows += tb->num_methods;
3783 alloc_table (table, table->rows);
3784 for (i = 0; i < tb->num_methods; ++i) {
3785 if (!mono_image_get_method_info (
3786 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3791 /* Do the same with properties etc.. */
3792 if (tb->events && mono_array_length (tb->events)) {
3793 table = &assembly->tables [MONO_TABLE_EVENT];
3794 table->rows += mono_array_length (tb->events);
3795 alloc_table (table, table->rows);
3796 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3798 alloc_table (table, table->rows);
3799 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3800 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3801 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3802 for (i = 0; i < mono_array_length (tb->events); ++i)
3803 mono_image_get_event_info (
3804 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3806 if (tb->properties && mono_array_length (tb->properties)) {
3807 table = &assembly->tables [MONO_TABLE_PROPERTY];
3808 table->rows += mono_array_length (tb->properties);
3809 alloc_table (table, table->rows);
3810 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3812 alloc_table (table, table->rows);
3813 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3814 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3815 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3816 for (i = 0; i < mono_array_length (tb->properties); ++i)
3817 mono_image_get_property_info (
3818 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3821 /* handle generic parameters */
3822 if (tb->generic_params) {
3823 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3824 table->rows += mono_array_length (tb->generic_params);
3825 alloc_table (table, table->rows);
3826 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3827 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3829 mono_image_get_generic_param_info (
3830 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3834 mono_image_add_decl_security (assembly,
3835 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3838 MonoDynamicTable *ntable;
3840 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3841 ntable->rows += mono_array_length (tb->subtypes);
3842 alloc_table (ntable, ntable->rows);
3843 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3845 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3846 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3848 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3849 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3850 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3851 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3852 mono_string_to_utf8 (tb->name), tb->table_idx,
3853 ntable->next_idx, ntable->rows);*/
3854 values += MONO_NESTED_CLASS_SIZE;
3864 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3868 mono_ptr_array_append (*types, type);
3870 if (!type->subtypes)
3873 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3874 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3875 collect_types (types, subtype);
3880 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3882 if ((*type1)->table_idx < (*type2)->table_idx)
3885 if ((*type1)->table_idx > (*type2)->table_idx)
3892 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3895 mono_error_init (error);
3898 for (i = 0; i < mono_array_length (pinfo); ++i) {
3899 MonoReflectionParamBuilder *pb;
3900 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3903 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3911 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3914 mono_error_init (error);
3916 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3919 for (i = 0; i < tb->num_fields; ++i) {
3920 MonoReflectionFieldBuilder* fb;
3921 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3922 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3927 for (i = 0; i < mono_array_length (tb->events); ++i) {
3928 MonoReflectionEventBuilder* eb;
3929 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3930 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3934 if (tb->properties) {
3935 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3936 MonoReflectionPropertyBuilder* pb;
3937 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3938 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3943 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3944 MonoReflectionCtorBuilder* cb;
3945 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3946 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3947 !params_add_cattrs (assembly, cb->pinfo, error))
3953 for (i = 0; i < tb->num_methods; ++i) {
3954 MonoReflectionMethodBuilder* mb;
3955 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3956 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3957 !params_add_cattrs (assembly, mb->pinfo, error))
3963 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3964 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3973 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3977 mono_error_init (error);
3979 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3982 if (moduleb->global_methods) {
3983 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3984 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3985 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3986 !params_add_cattrs (assembly, mb->pinfo, error))
3991 if (moduleb->global_fields) {
3992 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3993 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3994 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3999 if (moduleb->types) {
4000 for (i = 0; i < moduleb->num_types; ++i) {
4001 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4010 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4012 MonoDynamicTable *table;
4016 char *b = blob_size;
4019 table = &assembly->tables [MONO_TABLE_FILE];
4021 alloc_table (table, table->rows);
4022 values = table->values + table->next_idx * MONO_FILE_SIZE;
4023 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4024 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4025 if (image_is_dynamic (module->image)) {
4026 /* This depends on the fact that the main module is emitted last */
4027 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4028 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4031 path = g_strdup (module->image->name);
4033 mono_sha1_get_digest_from_file (path, hash);
4036 mono_metadata_encode_value (20, b, &b);
4037 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4038 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4043 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4045 MonoDynamicTable *table;
4048 table = &assembly->tables [MONO_TABLE_MODULE];
4049 mb->table_idx = table->next_idx ++;
4050 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4051 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4054 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4055 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4056 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4057 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4061 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4062 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4064 MonoDynamicTable *table;
4068 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4069 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4072 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4074 alloc_table (table, table->rows);
4075 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4077 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4078 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4079 if (klass->nested_in)
4080 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4082 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4083 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4084 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4086 res = table->next_idx;
4090 /* Emit nested types */
4091 if (klass->ext && klass->ext->nested_classes) {
4094 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4095 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4102 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4103 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4108 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4110 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4112 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4113 parent_index, assembly);
4117 * We need to do this ourselves since klass->nested_classes is not set up.
4120 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4121 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4126 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4127 guint32 module_index, MonoDynamicImage *assembly)
4129 MonoImage *image = module->image;
4133 t = &image->tables [MONO_TABLE_TYPEDEF];
4135 for (i = 0; i < t->rows; ++i) {
4137 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4138 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4140 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4141 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4146 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4148 MonoDynamicTable *table;
4150 guint32 scope, scope_idx, impl, current_idx;
4151 gboolean forwarder = TRUE;
4152 gpointer iter = NULL;
4155 if (klass->nested_in) {
4156 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4159 scope = resolution_scope_from_image (assembly, klass->image);
4160 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4161 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4162 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4165 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4168 alloc_table (table, table->rows);
4169 current_idx = table->next_idx;
4170 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4172 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4173 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4174 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4175 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4176 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4180 while ((nested = mono_class_get_nested_types (klass, &iter)))
4181 add_exported_type (assemblyb, assembly, nested, current_idx);
4185 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4190 if (!assemblyb->type_forwarders)
4193 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4194 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4199 type = mono_reflection_type_get_handle (t);
4202 klass = mono_class_from_mono_type (type);
4204 add_exported_type (assemblyb, assembly, klass, 0);
4208 #define align_pointer(base,p)\
4210 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4212 (p) += 4 - (__diff & 3);\
4216 compare_constants (const void *a, const void *b)
4218 const guint32 *a_values = (const guint32 *)a;
4219 const guint32 *b_values = (const guint32 *)b;
4220 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4224 compare_semantics (const void *a, const void *b)
4226 const guint32 *a_values = (const guint32 *)a;
4227 const guint32 *b_values = (const guint32 *)b;
4228 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4231 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4235 compare_custom_attrs (const void *a, const void *b)
4237 const guint32 *a_values = (const guint32 *)a;
4238 const guint32 *b_values = (const guint32 *)b;
4240 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4244 compare_field_marshal (const void *a, const void *b)
4246 const guint32 *a_values = (const guint32 *)a;
4247 const guint32 *b_values = (const guint32 *)b;
4249 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4253 compare_nested (const void *a, const void *b)
4255 const guint32 *a_values = (const guint32 *)a;
4256 const guint32 *b_values = (const guint32 *)b;
4258 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4262 compare_genericparam (const void *a, const void *b)
4264 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4265 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4267 if ((*b_entry)->owner == (*a_entry)->owner)
4269 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4270 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4272 return (*a_entry)->owner - (*b_entry)->owner;
4276 compare_declsecurity_attrs (const void *a, const void *b)
4278 const guint32 *a_values = (const guint32 *)a;
4279 const guint32 *b_values = (const guint32 *)b;
4281 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4285 compare_interface_impl (const void *a, const void *b)
4287 const guint32 *a_values = (const guint32 *)a;
4288 const guint32 *b_values = (const guint32 *)b;
4290 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4294 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4298 pad_heap (MonoDynamicStream *sh)
4300 if (sh->index & 3) {
4301 int sz = 4 - (sh->index & 3);
4302 memset (sh->data + sh->index, 0, sz);
4309 MonoDynamicStream *stream;
4313 * build_compressed_metadata() fills in the blob of data that represents the
4314 * raw metadata as it will be saved in the PE file. The five streams are output
4315 * and the metadata tables are comnpressed from the guint32 array representation,
4316 * to the compressed on-disk format.
4319 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4321 MonoDynamicTable *table;
4323 guint64 valid_mask = 0;
4324 guint64 sorted_mask;
4325 guint32 heapt_size = 0;
4326 guint32 meta_size = 256; /* allow for header and other stuff */
4327 guint32 table_offset;
4328 guint32 ntables = 0;
4334 struct StreamDesc stream_desc [5];
4336 mono_error_init (error);
4338 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4339 for (i = 0; i < assembly->gen_params->len; i++) {
4340 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4341 if (!write_generic_param_entry (assembly, entry, error))
4345 stream_desc [0].name = "#~";
4346 stream_desc [0].stream = &assembly->tstream;
4347 stream_desc [1].name = "#Strings";
4348 stream_desc [1].stream = &assembly->sheap;
4349 stream_desc [2].name = "#US";
4350 stream_desc [2].stream = &assembly->us;
4351 stream_desc [3].name = "#Blob";
4352 stream_desc [3].stream = &assembly->blob;
4353 stream_desc [4].name = "#GUID";
4354 stream_desc [4].stream = &assembly->guid;
4356 /* tables that are sorted */
4357 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4358 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4359 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4360 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4361 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4362 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4363 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4365 /* Compute table sizes */
4366 /* the MonoImage has already been created in mono_image_basic_init() */
4367 meta = &assembly->image;
4369 /* sizes should be multiple of 4 */
4370 pad_heap (&assembly->blob);
4371 pad_heap (&assembly->guid);
4372 pad_heap (&assembly->sheap);
4373 pad_heap (&assembly->us);
4375 /* Setup the info used by compute_sizes () */
4376 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4377 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4378 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4380 meta_size += assembly->blob.index;
4381 meta_size += assembly->guid.index;
4382 meta_size += assembly->sheap.index;
4383 meta_size += assembly->us.index;
4385 for (i=0; i < MONO_TABLE_NUM; ++i)
4386 meta->tables [i].rows = assembly->tables [i].rows;
4388 for (i = 0; i < MONO_TABLE_NUM; i++){
4389 if (meta->tables [i].rows == 0)
4391 valid_mask |= (guint64)1 << i;
4393 meta->tables [i].row_size = mono_metadata_compute_size (
4394 meta, i, &meta->tables [i].size_bitfield);
4395 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4397 heapt_size += 24; /* #~ header size */
4398 heapt_size += ntables * 4;
4399 /* make multiple of 4 */
4402 meta_size += heapt_size;
4403 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4404 p = (unsigned char*)meta->raw_metadata;
4405 /* the metadata signature */
4406 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4407 /* version numbers and 4 bytes reserved */
4408 int16val = (guint16*)p;
4409 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4410 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4412 /* version string */
4413 int32val = (guint32*)p;
4414 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4416 memcpy (p, meta->version, strlen (meta->version));
4417 p += GUINT32_FROM_LE (*int32val);
4418 align_pointer (meta->raw_metadata, p);
4419 int16val = (guint16*)p;
4420 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4421 *int16val = GUINT16_TO_LE (5); /* number of streams */
4425 * write the stream info.
4427 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4428 table_offset += 3; table_offset &= ~3;
4430 assembly->tstream.index = heapt_size;
4431 for (i = 0; i < 5; ++i) {
4432 int32val = (guint32*)p;
4433 stream_desc [i].stream->offset = table_offset;
4434 *int32val++ = GUINT32_TO_LE (table_offset);
4435 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4436 table_offset += GUINT32_FROM_LE (*int32val);
4437 table_offset += 3; table_offset &= ~3;
4439 strcpy ((char*)p, stream_desc [i].name);
4440 p += strlen (stream_desc [i].name) + 1;
4441 align_pointer (meta->raw_metadata, p);
4444 * now copy the data, the table stream header and contents goes first.
4446 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4447 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4448 int32val = (guint32*)p;
4449 *int32val = GUINT32_TO_LE (0); /* reserved */
4452 *p++ = 2; /* version */
4455 if (meta->idx_string_wide)
4457 if (meta->idx_guid_wide)
4459 if (meta->idx_blob_wide)
4462 *p++ = 1; /* reserved */
4463 int64val = (guint64*)p;
4464 *int64val++ = GUINT64_TO_LE (valid_mask);
4465 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4467 int32val = (guint32*)p;
4468 for (i = 0; i < MONO_TABLE_NUM; i++){
4469 if (meta->tables [i].rows == 0)
4471 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4473 p = (unsigned char*)int32val;
4475 /* sort the tables that still need sorting */
4476 table = &assembly->tables [MONO_TABLE_CONSTANT];
4478 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4479 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4481 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4482 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4484 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4485 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4487 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4488 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4490 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4491 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4492 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4494 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4495 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4497 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4499 /* compress the tables */
4500 for (i = 0; i < MONO_TABLE_NUM; i++){
4503 guint32 bitfield = meta->tables [i].size_bitfield;
4504 if (!meta->tables [i].rows)
4506 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4507 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4508 meta->tables [i].base = (char*)p;
4509 for (row = 1; row <= meta->tables [i].rows; ++row) {
4510 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4511 for (col = 0; col < assembly->tables [i].columns; ++col) {
4512 switch (mono_metadata_table_size (bitfield, col)) {
4514 *p++ = values [col];
4517 *p++ = values [col] & 0xff;
4518 *p++ = (values [col] >> 8) & 0xff;
4521 *p++ = values [col] & 0xff;
4522 *p++ = (values [col] >> 8) & 0xff;
4523 *p++ = (values [col] >> 16) & 0xff;
4524 *p++ = (values [col] >> 24) & 0xff;
4527 g_assert_not_reached ();
4531 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4534 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4535 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4536 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4537 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4538 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4540 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4546 * Some tables in metadata need to be sorted according to some criteria, but
4547 * when methods and fields are first created with reflection, they may be assigned a token
4548 * that doesn't correspond to the final token they will get assigned after the sorting.
4549 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4550 * with the reflection objects that represent them. Once all the tables are set up, the
4551 * reflection objects will contains the correct table index. fixup_method() will fixup the
4552 * tokens for the method with ILGenerator @ilgen.
4555 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4557 guint32 code_idx = GPOINTER_TO_UINT (value);
4558 MonoReflectionILTokenInfo *iltoken;
4559 MonoReflectionFieldBuilder *field;
4560 MonoReflectionCtorBuilder *ctor;
4561 MonoReflectionMethodBuilder *method;
4562 MonoReflectionTypeBuilder *tb;
4563 MonoReflectionArrayMethod *am;
4565 unsigned char *target;
4567 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4568 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4569 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4570 switch (target [3]) {
4571 case MONO_TABLE_FIELD:
4572 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4573 field = (MonoReflectionFieldBuilder *)iltoken->member;
4574 idx = field->table_idx;
4575 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4576 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4577 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4579 g_assert_not_reached ();
4582 case MONO_TABLE_METHOD:
4583 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4584 method = (MonoReflectionMethodBuilder *)iltoken->member;
4585 idx = method->table_idx;
4586 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4587 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4588 idx = ctor->table_idx;
4589 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4590 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4591 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4592 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4594 g_assert_not_reached ();
4597 case MONO_TABLE_TYPEDEF:
4598 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4599 g_assert_not_reached ();
4600 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4601 idx = tb->table_idx;
4603 case MONO_TABLE_MEMBERREF:
4604 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4605 am = (MonoReflectionArrayMethod*)iltoken->member;
4606 idx = am->table_idx;
4607 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4608 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4609 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4610 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4611 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4612 g_assert (m->klass->generic_class || m->klass->generic_container);
4614 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4616 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4617 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4618 g_assert (is_field_on_inst (f));
4620 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4621 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4623 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4625 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4627 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4630 g_assert_not_reached ();
4633 case MONO_TABLE_METHODSPEC:
4634 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4635 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636 g_assert (mono_method_signature (m)->generic_param_count);
4638 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4640 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4643 g_assert_not_reached ();
4647 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4649 target [0] = idx & 0xff;
4650 target [1] = (idx >> 8) & 0xff;
4651 target [2] = (idx >> 16) & 0xff;
4658 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4659 * value is not known when the table is emitted.
4662 fixup_cattrs (MonoDynamicImage *assembly)
4664 MonoDynamicTable *table;
4666 guint32 type, i, idx, token;
4669 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4671 for (i = 0; i < table->rows; ++i) {
4672 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4674 type = values [MONO_CUSTOM_ATTR_TYPE];
4675 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4676 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4677 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4678 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4681 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4682 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4683 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4684 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4685 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4686 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4687 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4688 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4695 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4697 MonoDynamicTable *table;
4700 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4702 alloc_table (table, table->rows);
4703 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4704 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4705 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4706 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4707 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4712 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4714 MonoDynamicTable *table;
4718 char *b = blob_size;
4720 guint32 idx, offset;
4722 if (rsrc->filename) {
4723 name = mono_string_to_utf8 (rsrc->filename);
4724 sname = g_path_get_basename (name);
4726 table = &assembly->tables [MONO_TABLE_FILE];
4728 alloc_table (table, table->rows);
4729 values = table->values + table->next_idx * MONO_FILE_SIZE;
4730 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4731 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4734 mono_sha1_get_digest_from_file (name, hash);
4735 mono_metadata_encode_value (20, b, &b);
4736 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4737 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4739 idx = table->next_idx++;
4741 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4747 data = mono_array_addr (rsrc->data, char, 0);
4748 len = mono_array_length (rsrc->data);
4754 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4755 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4756 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4757 mono_image_add_stream_data (&assembly->resources, data, len);
4761 * The entry should be emitted into the MANIFESTRESOURCE table of
4762 * the main module, but that needs to reference the FILE table
4763 * which isn't emitted yet.
4770 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4774 set_version_from_string (MonoString *version, guint32 *values)
4776 gchar *ver, *p, *str;
4779 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4780 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4781 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4782 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4785 ver = str = mono_string_to_utf8 (version);
4786 for (i = 0; i < 4; ++i) {
4787 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4793 /* handle Revision and Build */
4803 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4807 char *b = blob_size;
4812 len = mono_array_length (pkey);
4813 mono_metadata_encode_value (len, b, &b);
4814 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4815 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4817 assembly->public_key = (guint8 *)g_malloc (len);
4818 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4819 assembly->public_key_len = len;
4821 /* Special case: check for ECMA key (16 bytes) */
4822 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4823 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4824 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4825 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4826 /* minimum key size (in 2.0) is 384 bits */
4827 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4829 /* FIXME - verifier */
4830 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4831 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4833 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4839 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4841 MonoDynamicTable *table;
4842 MonoDynamicImage *assembly;
4843 MonoReflectionAssemblyBuilder *assemblyb;
4847 guint32 module_index;
4849 assemblyb = moduleb->assemblyb;
4850 assembly = moduleb->dynamic_image;
4851 domain = mono_object_domain (assemblyb);
4853 /* Emit ASSEMBLY table */
4854 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4855 alloc_table (table, 1);
4856 values = table->values + MONO_ASSEMBLY_SIZE;
4857 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4858 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4859 if (assemblyb->culture) {
4860 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4862 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4864 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4865 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4866 set_version_from_string (assemblyb->version, values);
4868 /* Emit FILE + EXPORTED_TYPE table */
4870 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4872 MonoReflectionModuleBuilder *file_module =
4873 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4874 if (file_module != moduleb) {
4875 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4877 if (file_module->types) {
4878 for (j = 0; j < file_module->num_types; ++j) {
4879 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4880 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4885 if (assemblyb->loaded_modules) {
4886 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4887 MonoReflectionModule *file_module =
4888 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4889 mono_image_fill_file_table (domain, file_module, assembly);
4891 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4894 if (assemblyb->type_forwarders)
4895 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4897 /* Emit MANIFESTRESOURCE table */
4899 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4901 MonoReflectionModuleBuilder *file_module =
4902 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4903 /* The table for the main module is emitted later */
4904 if (file_module != moduleb) {
4906 if (file_module->resources) {
4907 int len = mono_array_length (file_module->resources);
4908 for (j = 0; j < len; ++j) {
4909 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4910 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4917 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4920 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4921 * for the modulebuilder @moduleb.
4922 * At the end of the process, method and field tokens are fixed up and the
4923 * on-disk compressed metadata representation is created.
4924 * Return TRUE on success, or FALSE on failure and sets @error
4927 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4929 MonoDynamicTable *table;
4930 MonoDynamicImage *assembly;
4931 MonoReflectionAssemblyBuilder *assemblyb;
4937 mono_error_init (error);
4939 assemblyb = moduleb->assemblyb;
4940 assembly = moduleb->dynamic_image;
4941 domain = mono_object_domain (assemblyb);
4943 if (assembly->text_rva)
4946 assembly->text_rva = START_TEXT_RVA;
4948 if (moduleb->is_main) {
4949 mono_image_emit_manifest (moduleb);
4952 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4953 table->rows = 1; /* .<Module> */
4955 alloc_table (table, table->rows);
4957 * Set the first entry.
4959 values = table->values + table->columns;
4960 values [MONO_TYPEDEF_FLAGS] = 0;
4961 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4962 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4963 values [MONO_TYPEDEF_EXTENDS] = 0;
4964 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4965 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4968 * handle global methods
4969 * FIXME: test what to do when global methods are defined in multiple modules.
4971 if (moduleb->global_methods) {
4972 table = &assembly->tables [MONO_TABLE_METHOD];
4973 table->rows += mono_array_length (moduleb->global_methods);
4974 alloc_table (table, table->rows);
4975 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4976 if (!mono_image_get_method_info (
4977 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
4981 if (moduleb->global_fields) {
4982 table = &assembly->tables [MONO_TABLE_FIELD];
4983 table->rows += mono_array_length (moduleb->global_fields);
4984 alloc_table (table, table->rows);
4985 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4986 mono_image_get_field_info (
4987 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4990 table = &assembly->tables [MONO_TABLE_MODULE];
4991 alloc_table (table, 1);
4992 mono_image_fill_module_table (domain, moduleb, assembly);
4994 /* Collect all types into a list sorted by their table_idx */
4995 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4998 for (i = 0; i < moduleb->num_types; ++i) {
4999 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5000 collect_types (&types, type);
5003 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5004 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5005 table->rows += mono_ptr_array_size (types);
5006 alloc_table (table, table->rows);
5009 * Emit type names + namespaces at one place inside the string heap,
5010 * so load_class_names () needs to touch fewer pages.
5012 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5013 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5014 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5016 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5017 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5018 string_heap_insert_mstring (&assembly->sheap, tb->name);
5021 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5022 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5023 if (!mono_image_get_type_info (domain, type, assembly, error))
5028 * table->rows is already set above and in mono_image_fill_module_table.
5030 /* add all the custom attributes at the end, once all the indexes are stable */
5031 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5034 /* CAS assembly permissions */
5035 if (assemblyb->permissions_minimum)
5036 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5037 if (assemblyb->permissions_optional)
5038 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5039 if (assemblyb->permissions_refused)
5040 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5042 if (!module_add_cattrs (assembly, moduleb, error))
5046 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5048 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5049 * the final tokens and don't need another fixup pass. */
5051 if (moduleb->global_methods) {
5052 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5053 MonoReflectionMethodBuilder *mb = mono_array_get (
5054 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5055 if (!mono_image_add_methodimpl (assembly, mb, error))
5060 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5061 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5062 if (type->methods) {
5063 for (j = 0; j < type->num_methods; ++j) {
5064 MonoReflectionMethodBuilder *mb = mono_array_get (
5065 type->methods, MonoReflectionMethodBuilder*, j);
5067 if (!mono_image_add_methodimpl (assembly, mb, error))
5073 fixup_cattrs (assembly);
5076 mono_ptr_array_destroy (types);
5079 return mono_error_ok (error);
5082 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5085 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5087 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5090 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5094 guint32 import_lookup_table;
5098 guint32 import_address_table_rva;
5106 #ifndef DISABLE_REFLECTION_EMIT
5109 * mono_image_insert_string:
5110 * @module: module builder object
5113 * Insert @str into the user string stream of @module.
5116 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5118 MonoDynamicImage *assembly;
5123 if (!module->dynamic_image)
5124 mono_image_module_basic_init (module);
5126 assembly = module->dynamic_image;
5128 if (assembly->save) {
5129 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5130 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5131 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5133 char *swapped = g_malloc (2 * mono_string_length (str));
5134 const char *p = (const char*)mono_string_chars (str);
5136 swap_with_size (swapped, p, 2, mono_string_length (str));
5137 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5141 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5143 mono_image_add_stream_data (&assembly->us, "", 1);
5145 idx = assembly->us.index ++;
5148 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5150 return MONO_TOKEN_STRING | idx;
5154 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5158 MonoMethodSignature *sig;
5160 mono_error_init (error);
5162 klass = obj->vtable->klass;
5163 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5164 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5165 MonoMethodSignature *old;
5166 guint32 sig_token, parent;
5169 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5171 nargs = mono_array_length (opt_param_types);
5172 old = mono_method_signature (method);
5173 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5175 sig->hasthis = old->hasthis;
5176 sig->explicit_this = old->explicit_this;
5177 sig->call_convention = old->call_convention;
5178 sig->generic_param_count = old->generic_param_count;
5179 sig->param_count = old->param_count + nargs;
5180 sig->sentinelpos = old->param_count;
5181 sig->ret = old->ret;
5183 for (i = 0; i < old->param_count; i++)
5184 sig->params [i] = old->params [i];
5186 for (i = 0; i < nargs; i++) {
5187 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5188 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5191 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5192 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5193 parent >>= MONO_TYPEDEFORREF_BITS;
5195 parent <<= MONO_MEMBERREF_PARENT_BITS;
5196 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5198 sig_token = method_encode_signature (assembly, sig);
5199 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5200 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5201 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5202 ReflectionMethodBuilder rmb;
5203 guint32 parent, sig_token;
5204 int nopt_args, nparams, ngparams, i;
5206 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5209 rmb.opt_types = opt_param_types;
5210 nopt_args = mono_array_length (opt_param_types);
5212 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5213 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5214 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5216 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5217 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5218 sig->call_convention = rmb.call_conv;
5219 sig->generic_param_count = ngparams;
5220 sig->param_count = nparams + nopt_args;
5221 sig->sentinelpos = nparams;
5222 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5224 for (i = 0; i < nparams; i++) {
5225 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5226 sig->params [i] = mono_reflection_type_get_handle (rt);
5229 for (i = 0; i < nopt_args; i++) {
5230 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5231 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5234 sig_token = method_builder_encode_signature (assembly, &rmb);
5236 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5237 if (!mono_error_ok (error))
5239 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5241 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5242 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5244 char *name = mono_string_to_utf8 (rmb.name);
5245 token = mono_image_get_varargs_method_token (
5246 assembly, parent, name, sig_token);
5249 g_error ("requested method token for %s\n", klass->name);
5252 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5253 register_dyn_token (assembly, token, obj);
5256 g_assert (!mono_error_ok (error));
5261 * mono_image_create_token:
5262 * @assembly: a dynamic assembly
5264 * @register_token: Whenever to register the token in the assembly->tokens hash.
5266 * Get a token to insert in the IL code stream for the given MemberInfo.
5267 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5268 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5272 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5273 gboolean create_open_instance, gboolean register_token,
5279 mono_error_init (error);
5281 klass = obj->vtable->klass;
5283 /* Check for user defined reflection objects */
5284 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5285 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5286 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5290 if (strcmp (klass->name, "MethodBuilder") == 0) {
5291 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5292 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5294 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5295 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5297 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5298 if (!mono_error_ok (error))
5301 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5302 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5303 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5304 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5306 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5307 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5309 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5310 if (!mono_error_ok (error))
5313 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5314 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5315 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5317 if (tb->generic_params) {
5318 token = mono_image_get_generic_field_token (assembly, fb);
5320 if (tb->module->dynamic_image == assembly) {
5321 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5323 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5326 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5327 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5328 if (create_open_instance && tb->generic_params) {
5330 init_type_builder_generics (obj);
5331 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5332 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5333 token = mono_metadata_token_from_dor (token);
5334 } else if (tb->module->dynamic_image == assembly) {
5335 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5338 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5339 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5341 } else if (strcmp (klass->name, "MonoType") == 0) {
5342 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5343 MonoClass *mc = mono_class_from_mono_type (type);
5344 token = mono_metadata_token_from_dor (
5345 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5346 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5347 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5348 token = mono_metadata_token_from_dor (
5349 mono_image_typedef_or_ref (assembly, type));
5350 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5351 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5352 token = mono_metadata_token_from_dor (
5353 mono_image_typedef_or_ref (assembly, type));
5354 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5355 strcmp (klass->name, "MonoMethod") == 0 ||
5356 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5357 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5358 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5359 if (m->method->is_inflated) {
5360 if (create_open_instance)
5361 token = mono_image_get_methodspec_token (assembly, m->method);
5363 token = mono_image_get_inflated_method_token (assembly, m->method);
5364 } else if ((m->method->klass->image == &assembly->image) &&
5365 !m->method->klass->generic_class) {
5366 static guint32 method_table_idx = 0xffffff;
5367 if (m->method->klass->wastypebuilder) {
5368 /* we use the same token as the one that was assigned
5369 * to the Methodbuilder.
5370 * FIXME: do the equivalent for Fields.
5372 token = m->method->token;
5375 * Each token should have a unique index, but the indexes are
5376 * assigned by managed code, so we don't know about them. An
5377 * easy solution is to count backwards...
5379 method_table_idx --;
5380 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5383 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5385 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5386 } else if (strcmp (klass->name, "MonoField") == 0) {
5387 MonoReflectionField *f = (MonoReflectionField *)obj;
5388 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5389 static guint32 field_table_idx = 0xffffff;
5391 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5393 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5395 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5396 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5397 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5398 token = mono_image_get_array_token (assembly, m);
5399 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5400 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5401 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5402 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5403 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5404 token = mono_metadata_token_from_dor (
5405 mono_image_typedef_or_ref (assembly, type));
5406 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5407 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5408 token = mono_image_get_field_on_inst_token (assembly, f);
5409 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5410 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5411 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5412 if (!mono_error_ok (error))
5414 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5415 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5416 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5417 if (!mono_error_ok (error))
5419 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5420 MonoReflectionType *type = (MonoReflectionType *)obj;
5421 token = mono_metadata_token_from_dor (
5422 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5424 g_error ("requested token for %s\n", klass->name);
5428 mono_image_register_token (assembly, token, obj);
5434 * mono_image_register_token:
5436 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5437 * the Module.ResolveXXXToken () methods to work.
5440 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5444 dynamic_image_lock (assembly);
5445 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5447 /* There could be multiple MethodInfo objects with the same token */
5448 //g_assert (prev == obj);
5450 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5452 dynamic_image_unlock (assembly);
5455 static MonoDynamicImage*
5456 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5458 static const guchar entrycode [16] = {0xff, 0x25, 0};
5459 MonoDynamicImage *image;
5462 const char *version;
5464 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5465 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5467 version = mono_get_runtime_info ()->runtime_version;
5470 /* The MonoGHashTable's need GC tracking */
5471 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5473 image = g_new0 (MonoDynamicImage, 1);
5476 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5478 /*g_print ("created image %p\n", image);*/
5479 /* keep in sync with image.c */
5480 image->image.name = assembly_name;
5481 image->image.assembly_name = image->image.name; /* they may be different */
5482 image->image.module_name = module_name;
5483 image->image.version = g_strdup (version);
5484 image->image.md_version_major = 1;
5485 image->image.md_version_minor = 1;
5486 image->image.dynamic = TRUE;
5488 image->image.references = g_new0 (MonoAssembly*, 1);
5489 image->image.references [0] = NULL;
5491 mono_image_init (&image->image);
5493 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");
5494 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5495 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5496 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5497 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5498 image->handleref = g_hash_table_new (NULL, NULL);
5499 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");
5500 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5501 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");
5502 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");
5503 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5504 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5505 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5506 image->gen_params = g_ptr_array_new ();
5507 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5509 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5510 string_heap_init (&image->sheap);
5511 mono_image_add_stream_data (&image->us, "", 1);
5512 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5513 /* import tables... */
5514 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5515 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5516 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5517 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5518 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5519 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5520 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5521 stream_data_align (&image->code);
5523 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5525 for (i=0; i < MONO_TABLE_NUM; ++i) {
5526 image->tables [i].next_idx = 1;
5527 image->tables [i].columns = table_sizes [i];
5530 image->image.assembly = (MonoAssembly*)assembly;
5531 image->run = assembly->run;
5532 image->save = assembly->save;
5533 image->pe_kind = 0x1; /* ILOnly */
5534 image->machine = 0x14c; /* I386 */
5536 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5538 dynamic_images_lock ();
5540 if (!dynamic_images)
5541 dynamic_images = g_ptr_array_new ();
5543 g_ptr_array_add (dynamic_images, image);
5545 dynamic_images_unlock ();
5552 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5558 release_hashtable (MonoGHashTable **hash)
5561 mono_g_hash_table_destroy (*hash);
5567 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5569 release_hashtable (&image->token_fixups);
5570 release_hashtable (&image->handleref_managed);
5571 release_hashtable (&image->tokens);
5572 release_hashtable (&image->remapped_tokens);
5573 release_hashtable (&image->generic_def_objects);
5574 release_hashtable (&image->methodspec);
5577 // Free dynamic image pass one: Free resources but not image itself
5579 mono_dynamic_image_free (MonoDynamicImage *image)
5581 MonoDynamicImage *di = image;
5586 mono_g_hash_table_destroy (di->methodspec);
5588 g_hash_table_destroy (di->typespec);
5590 g_hash_table_destroy (di->typeref);
5592 g_hash_table_destroy (di->handleref);
5593 if (di->handleref_managed)
5594 mono_g_hash_table_destroy (di->handleref_managed);
5596 mono_g_hash_table_destroy (di->tokens);
5597 if (di->remapped_tokens)
5598 mono_g_hash_table_destroy (di->remapped_tokens);
5599 if (di->generic_def_objects)
5600 mono_g_hash_table_destroy (di->generic_def_objects);
5601 if (di->blob_cache) {
5602 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5603 g_hash_table_destroy (di->blob_cache);
5605 if (di->standalonesig_cache)
5606 g_hash_table_destroy (di->standalonesig_cache);
5607 for (list = di->array_methods; list; list = list->next) {
5608 ArrayMethod *am = (ArrayMethod *)list->data;
5613 g_list_free (di->array_methods);
5614 if (di->gen_params) {
5615 for (i = 0; i < di->gen_params->len; i++) {
5616 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5617 mono_gc_deregister_root ((char*) &entry->gparam);
5620 g_ptr_array_free (di->gen_params, TRUE);
5622 if (di->token_fixups)
5623 mono_g_hash_table_destroy (di->token_fixups);
5624 if (di->method_to_table_idx)
5625 g_hash_table_destroy (di->method_to_table_idx);
5626 if (di->field_to_table_idx)
5627 g_hash_table_destroy (di->field_to_table_idx);
5628 if (di->method_aux_hash)
5629 g_hash_table_destroy (di->method_aux_hash);
5630 if (di->vararg_aux_hash)
5631 g_hash_table_destroy (di->vararg_aux_hash);
5632 g_free (di->strong_name);
5633 g_free (di->win32_res);
5635 g_free (di->public_key);
5637 /*g_print ("string heap destroy for image %p\n", di);*/
5638 mono_dynamic_stream_reset (&di->sheap);
5639 mono_dynamic_stream_reset (&di->code);
5640 mono_dynamic_stream_reset (&di->resources);
5641 mono_dynamic_stream_reset (&di->us);
5642 mono_dynamic_stream_reset (&di->blob);
5643 mono_dynamic_stream_reset (&di->tstream);
5644 mono_dynamic_stream_reset (&di->guid);
5645 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5646 g_free (di->tables [i].values);
5649 dynamic_images_lock ();
5652 g_ptr_array_remove (dynamic_images, di);
5654 dynamic_images_unlock ();
5657 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5659 mono_dynamic_image_free_image (MonoDynamicImage *image)
5661 /* See create_dynamic_mono_image () */
5663 /* Allocated using GC_MALLOC */
5669 #ifndef DISABLE_REFLECTION_EMIT
5672 * mono_image_basic_init:
5673 * @assembly: an assembly builder object
5675 * Create the MonoImage that represents the assembly builder and setup some
5676 * of the helper hash table and the basic metadata streams.
5679 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5681 MonoDynamicAssembly *assembly;
5682 MonoDynamicImage *image;
5683 MonoDomain *domain = mono_object_domain (assemblyb);
5685 if (assemblyb->dynamic_assembly)
5689 /* assembly->assembly.image might be GC allocated */
5690 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5692 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5695 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5697 assembly->assembly.ref_count = 1;
5698 assembly->assembly.dynamic = TRUE;
5699 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5700 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5701 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5702 if (assemblyb->culture)
5703 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5705 assembly->assembly.aname.culture = g_strdup ("");
5707 if (assemblyb->version) {
5708 char *vstr = mono_string_to_utf8 (assemblyb->version);
5709 char **version = g_strsplit (vstr, ".", 4);
5710 char **parts = version;
5711 assembly->assembly.aname.major = atoi (*parts++);
5712 assembly->assembly.aname.minor = atoi (*parts++);
5713 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5714 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5716 g_strfreev (version);
5719 assembly->assembly.aname.major = 0;
5720 assembly->assembly.aname.minor = 0;
5721 assembly->assembly.aname.build = 0;
5722 assembly->assembly.aname.revision = 0;
5725 assembly->run = assemblyb->access != 2;
5726 assembly->save = assemblyb->access != 1;
5727 assembly->domain = domain;
5729 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5730 image->initial_image = TRUE;
5731 assembly->assembly.aname.name = image->image.name;
5732 assembly->assembly.image = &image->image;
5733 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5734 /* -1 to correct for the trailing NULL byte */
5735 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5736 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5738 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5741 mono_domain_assemblies_lock (domain);
5742 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5743 mono_domain_assemblies_unlock (domain);
5745 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5747 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5749 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5752 #endif /* !DISABLE_REFLECTION_EMIT */
5754 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5757 calc_section_size (MonoDynamicImage *assembly)
5761 /* alignment constraints */
5762 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5763 g_assert ((assembly->code.index % 4) == 0);
5764 assembly->meta_size += 3;
5765 assembly->meta_size &= ~3;
5766 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5767 g_assert ((assembly->resources.index % 4) == 0);
5769 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5770 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5773 if (assembly->win32_res) {
5774 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5776 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5777 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5781 assembly->sections [MONO_SECTION_RELOC].size = 12;
5782 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5792 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5796 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5798 ResTreeNode *t1 = (ResTreeNode*)a;
5799 ResTreeNode *t2 = (ResTreeNode*)b;
5801 return t1->id - t2->id;
5805 * resource_tree_create:
5807 * Organize the resources into a resource tree.
5809 static ResTreeNode *
5810 resource_tree_create (MonoArray *win32_resources)
5812 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5816 tree = g_new0 (ResTreeNode, 1);
5818 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5819 MonoReflectionWin32Resource *win32_res =
5820 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5824 /* FIXME: BUG: this stores managed references in unmanaged memory */
5825 lang_node = g_new0 (ResTreeNode, 1);
5826 lang_node->id = win32_res->lang_id;
5827 lang_node->win32_res = win32_res;
5829 /* Create type node if neccesary */
5831 for (l = tree->children; l; l = l->next)
5832 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5833 type_node = (ResTreeNode*)l->data;
5838 type_node = g_new0 (ResTreeNode, 1);
5839 type_node->id = win32_res->res_type;
5842 * The resource types have to be sorted otherwise
5843 * Windows Explorer can't display the version information.
5845 tree->children = g_slist_insert_sorted (tree->children,
5846 type_node, resource_tree_compare_by_id);
5849 /* Create res node if neccesary */
5851 for (l = type_node->children; l; l = l->next)
5852 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5853 res_node = (ResTreeNode*)l->data;
5858 res_node = g_new0 (ResTreeNode, 1);
5859 res_node->id = win32_res->res_id;
5860 type_node->children = g_slist_append (type_node->children, res_node);
5863 res_node->children = g_slist_append (res_node->children, lang_node);
5870 * resource_tree_encode:
5872 * Encode the resource tree into the format used in the PE file.
5875 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5878 MonoPEResourceDir dir;
5879 MonoPEResourceDirEntry dir_entry;
5880 MonoPEResourceDataEntry data_entry;
5882 guint32 res_id_entries;
5885 * For the format of the resource directory, see the article
5886 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5890 memset (&dir, 0, sizeof (dir));
5891 memset (&dir_entry, 0, sizeof (dir_entry));
5892 memset (&data_entry, 0, sizeof (data_entry));
5894 g_assert (sizeof (dir) == 16);
5895 g_assert (sizeof (dir_entry) == 8);
5896 g_assert (sizeof (data_entry) == 16);
5898 node->offset = p - begin;
5900 /* IMAGE_RESOURCE_DIRECTORY */
5901 res_id_entries = g_slist_length (node->children);
5902 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5904 memcpy (p, &dir, sizeof (dir));
5907 /* Reserve space for entries */
5909 p += sizeof (dir_entry) * res_id_entries;
5911 /* Write children */
5912 for (l = node->children; l; l = l->next) {
5913 ResTreeNode *child = (ResTreeNode*)l->data;
5915 if (child->win32_res) {
5918 child->offset = p - begin;
5920 /* IMAGE_RESOURCE_DATA_ENTRY */
5921 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5922 size = mono_array_length (child->win32_res->res_data);
5923 data_entry.rde_size = GUINT32_TO_LE (size);
5925 memcpy (p, &data_entry, sizeof (data_entry));
5926 p += sizeof (data_entry);
5928 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5931 resource_tree_encode (child, begin, p, &p);
5935 /* IMAGE_RESOURCE_ENTRY */
5936 for (l = node->children; l; l = l->next) {
5937 ResTreeNode *child = (ResTreeNode*)l->data;
5939 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5940 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5942 memcpy (entries, &dir_entry, sizeof (dir_entry));
5943 entries += sizeof (dir_entry);
5950 resource_tree_free (ResTreeNode * node)
5953 for (list = node->children; list; list = list->next)
5954 resource_tree_free ((ResTreeNode*)list->data);
5955 g_slist_free(node->children);
5960 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5965 MonoReflectionWin32Resource *win32_res;
5968 if (!assemblyb->win32_resources)
5972 * Resources are stored in a three level tree inside the PE file.
5973 * - level one contains a node for each type of resource
5974 * - level two contains a node for each resource
5975 * - level three contains a node for each instance of a resource for a
5976 * specific language.
5979 tree = resource_tree_create (assemblyb->win32_resources);
5981 /* Estimate the size of the encoded tree */
5983 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5984 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5985 size += mono_array_length (win32_res->res_data);
5987 /* Directory structure */
5988 size += mono_array_length (assemblyb->win32_resources) * 256;
5989 p = buf = (char *)g_malloc (size);
5991 resource_tree_encode (tree, p, p, &p);
5993 g_assert (p - buf <= size);
5995 assembly->win32_res = (char *)g_malloc (p - buf);
5996 assembly->win32_res_size = p - buf;
5997 memcpy (assembly->win32_res, buf, p - buf);
6000 resource_tree_free (tree);
6004 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6006 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6009 p += sizeof (MonoPEResourceDir);
6010 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6011 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6012 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6013 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6014 fixup_resource_directory (res_section, child, rva);
6016 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6017 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6020 p += sizeof (MonoPEResourceDirEntry);
6025 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6028 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6029 g_error ("WriteFile returned %d\n", GetLastError ());
6033 * mono_image_create_pefile:
6034 * @mb: a module builder object
6036 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6037 * assembly->pefile where it can be easily retrieved later in chunks.
6040 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6042 MonoMSDOSHeader *msdos;
6043 MonoDotNetHeader *header;
6044 MonoSectionTable *section;
6045 MonoCLIHeader *cli_header;
6046 guint32 size, image_size, virtual_base, text_offset;
6047 guint32 header_start, section_start, file_offset, virtual_offset;
6048 MonoDynamicImage *assembly;
6049 MonoReflectionAssemblyBuilder *assemblyb;
6050 MonoDynamicStream pefile_stream = {0};
6051 MonoDynamicStream *pefile = &pefile_stream;
6053 guint32 *rva, value;
6055 static const unsigned char msheader[] = {
6056 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6057 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6060 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6061 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6062 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6063 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6066 mono_error_init (error);
6068 assemblyb = mb->assemblyb;
6070 mono_image_basic_init (assemblyb);
6071 assembly = mb->dynamic_image;
6073 assembly->pe_kind = assemblyb->pe_kind;
6074 assembly->machine = assemblyb->machine;
6075 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6076 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6078 if (!mono_image_build_metadata (mb, error))
6082 if (mb->is_main && assemblyb->resources) {
6083 int len = mono_array_length (assemblyb->resources);
6084 for (i = 0; i < len; ++i)
6085 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6088 if (mb->resources) {
6089 int len = mono_array_length (mb->resources);
6090 for (i = 0; i < len; ++i)
6091 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6094 if (!build_compressed_metadata (assembly, error))
6098 assembly_add_win32_resources (assembly, assemblyb);
6100 nsections = calc_section_size (assembly);
6102 /* The DOS header and stub */
6103 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6104 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6106 /* the dotnet header */
6107 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6109 /* the section tables */
6110 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6112 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6113 virtual_offset = VIRT_ALIGN;
6116 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6117 if (!assembly->sections [i].size)
6120 file_offset += FILE_ALIGN - 1;
6121 file_offset &= ~(FILE_ALIGN - 1);
6122 virtual_offset += VIRT_ALIGN - 1;
6123 virtual_offset &= ~(VIRT_ALIGN - 1);
6125 assembly->sections [i].offset = file_offset;
6126 assembly->sections [i].rva = virtual_offset;
6128 file_offset += assembly->sections [i].size;
6129 virtual_offset += assembly->sections [i].size;
6130 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6133 file_offset += FILE_ALIGN - 1;
6134 file_offset &= ~(FILE_ALIGN - 1);
6136 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6138 /* back-patch info */
6139 msdos = (MonoMSDOSHeader*)pefile->data;
6140 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6142 header = (MonoDotNetHeader*)(pefile->data + header_start);
6143 header->pesig [0] = 'P';
6144 header->pesig [1] = 'E';
6146 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6147 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6148 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6149 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6150 if (assemblyb->pekind == 1) {
6152 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6155 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6158 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6160 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6161 header->pe.pe_major = 6;
6162 header->pe.pe_minor = 0;
6163 size = assembly->sections [MONO_SECTION_TEXT].size;
6164 size += FILE_ALIGN - 1;
6165 size &= ~(FILE_ALIGN - 1);
6166 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6167 size = assembly->sections [MONO_SECTION_RSRC].size;
6168 size += FILE_ALIGN - 1;
6169 size &= ~(FILE_ALIGN - 1);
6170 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6171 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6172 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6173 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6174 /* pe_rva_entry_point always at the beginning of the text section */
6175 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6177 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6178 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6179 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6180 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6181 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6182 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6183 size = section_start;
6184 size += FILE_ALIGN - 1;
6185 size &= ~(FILE_ALIGN - 1);
6186 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6188 size += VIRT_ALIGN - 1;
6189 size &= ~(VIRT_ALIGN - 1);
6190 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6193 // Translate the PEFileKind value to the value expected by the Windows loader
6199 // PEFileKinds.Dll == 1
6200 // PEFileKinds.ConsoleApplication == 2
6201 // PEFileKinds.WindowApplication == 3
6204 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6205 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6207 if (assemblyb->pekind == 3)
6212 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6214 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6215 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6216 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6217 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6218 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6219 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6221 /* fill data directory entries */
6223 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6224 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6226 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6227 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6229 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6230 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6231 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6232 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6233 /* patch entrypoint name */
6234 if (assemblyb->pekind == 1)
6235 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6237 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6238 /* patch imported function RVA name */
6239 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6240 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6242 /* the import table */
6243 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6244 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6245 /* patch imported dll RVA name and other entries in the dir */
6246 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6247 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6248 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6249 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6250 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6251 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6253 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6254 value = (assembly->text_rva + assembly->imp_names_offset);
6255 *p++ = (value) & 0xff;
6256 *p++ = (value >> 8) & (0xff);
6257 *p++ = (value >> 16) & (0xff);
6258 *p++ = (value >> 24) & (0xff);
6260 /* the CLI header info */
6261 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6262 cli_header->ch_size = GUINT32_FROM_LE (72);
6263 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6264 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6265 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6266 if (assemblyb->entry_point) {
6267 guint32 table_idx = 0;
6268 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6269 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6270 table_idx = methodb->table_idx;
6272 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6274 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6276 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6278 /* The embedded managed resources */
6279 text_offset = assembly->text_rva + assembly->code.index;
6280 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6281 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6282 text_offset += assembly->resources.index;
6283 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6284 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6285 text_offset += assembly->meta_size;
6286 if (assembly->strong_name_size) {
6287 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6288 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6289 text_offset += assembly->strong_name_size;
6292 /* write the section tables and section content */
6293 section = (MonoSectionTable*)(pefile->data + section_start);
6294 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6295 static const char section_names [][7] = {
6296 ".text", ".rsrc", ".reloc"
6298 if (!assembly->sections [i].size)
6300 strcpy (section->st_name, section_names [i]);
6301 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6302 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6303 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6304 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6305 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6306 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6307 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6311 checked_write_file (file, pefile->data, pefile->index);
6313 mono_dynamic_stream_reset (pefile);
6315 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6316 if (!assembly->sections [i].size)
6319 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6320 g_error ("SetFilePointer returned %d\n", GetLastError ());
6323 case MONO_SECTION_TEXT:
6324 /* patch entry point */
6325 p = (guchar*)(assembly->code.data + 2);
6326 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6327 *p++ = (value) & 0xff;
6328 *p++ = (value >> 8) & 0xff;
6329 *p++ = (value >> 16) & 0xff;
6330 *p++ = (value >> 24) & 0xff;
6332 checked_write_file (file, assembly->code.data, assembly->code.index);
6333 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6334 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6335 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6338 g_free (assembly->image.raw_metadata);
6340 case MONO_SECTION_RELOC: {
6344 guint16 type_and_offset;
6348 g_assert (sizeof (reloc) == 12);
6350 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6351 reloc.block_size = GUINT32_FROM_LE (12);
6354 * the entrypoint is always at the start of the text section
6355 * 3 is IMAGE_REL_BASED_HIGHLOW
6356 * 2 is patch_size_rva - text_rva
6358 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6361 checked_write_file (file, &reloc, sizeof (reloc));
6365 case MONO_SECTION_RSRC:
6366 if (assembly->win32_res) {
6368 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6369 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6370 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6374 g_assert_not_reached ();
6378 /* check that the file is properly padded */
6379 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6380 g_error ("SetFilePointer returned %d\n", GetLastError ());
6381 if (! SetEndOfFile (file))
6382 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6384 mono_dynamic_stream_reset (&assembly->code);
6385 mono_dynamic_stream_reset (&assembly->us);
6386 mono_dynamic_stream_reset (&assembly->blob);
6387 mono_dynamic_stream_reset (&assembly->guid);
6388 mono_dynamic_stream_reset (&assembly->sheap);
6390 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6391 g_hash_table_destroy (assembly->blob_cache);
6392 assembly->blob_cache = NULL;
6397 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6400 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6402 g_assert_not_reached ();
6405 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6407 #ifndef DISABLE_REFLECTION_EMIT
6409 MonoReflectionModule *
6410 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6413 MonoReflectionModule *result = NULL;
6416 MonoImageOpenStatus status;
6417 MonoDynamicAssembly *assembly;
6418 guint32 module_count;
6419 MonoImage **new_modules;
6420 gboolean *new_modules_loaded;
6422 name = mono_string_to_utf8 (fileName);
6424 image = mono_image_open (name, &status);
6427 if (status == MONO_IMAGE_ERROR_ERRNO)
6428 exc = mono_get_exception_file_not_found (fileName);
6430 exc = mono_get_exception_bad_image_format (name);
6432 mono_raise_exception (exc);
6437 assembly = ab->dynamic_assembly;
6438 image->assembly = (MonoAssembly*)assembly;
6440 module_count = image->assembly->image->module_count;
6441 new_modules = g_new0 (MonoImage *, module_count + 1);
6442 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6444 if (image->assembly->image->modules)
6445 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6446 if (image->assembly->image->modules_loaded)
6447 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6448 new_modules [module_count] = image;
6449 new_modules_loaded [module_count] = TRUE;
6450 mono_image_addref (image);
6452 g_free (image->assembly->image->modules);
6453 image->assembly->image->modules = new_modules;
6454 image->assembly->image->modules_loaded = new_modules_loaded;
6455 image->assembly->image->module_count ++;
6457 mono_assembly_load_references (image, &status);
6459 mono_image_close (image);
6460 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6463 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6464 mono_error_raise_exception (&error); /* FIXME don't raise here */
6468 #endif /* DISABLE_REFLECTION_EMIT */
6471 * We need to return always the same object for MethodInfo, FieldInfo etc..
6472 * but we need to consider the reflected type.
6473 * type uses a different hash, since it uses custom hash/equal functions.
6478 MonoClass *refclass;
6482 reflected_equal (gconstpointer a, gconstpointer b) {
6483 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6484 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6486 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6490 reflected_hash (gconstpointer a) {
6491 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6492 return mono_aligned_addr_hash (ea->item);
6495 #define CHECK_OBJECT(t,p,k) \
6501 mono_domain_lock (domain); \
6502 if (!domain->refobject_hash) \
6503 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"); \
6504 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6505 mono_domain_unlock (domain); \
6508 mono_domain_unlock (domain); \
6511 #ifdef HAVE_BOEHM_GC
6512 /* ReflectedEntry doesn't need to be GC tracked */
6513 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6514 #define FREE_REFENTRY(entry) g_free ((entry))
6515 #define REFENTRY_REQUIRES_CLEANUP
6517 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6519 #define FREE_REFENTRY(entry)
6522 #define CACHE_OBJECT(t,p,o,k) \
6525 ReflectedEntry pe; \
6527 pe.refclass = (k); \
6528 mono_domain_lock (domain); \
6529 if (!domain->refobject_hash) \
6530 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"); \
6531 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6533 ReflectedEntry *e = ALLOC_REFENTRY; \
6535 e->refclass = (k); \
6536 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6539 mono_domain_unlock (domain); \
6544 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6546 mono_domain_lock (domain);
6547 if (domain->refobject_hash) {
6549 gpointer orig_pe, orig_value;
6552 pe.refclass = klass;
6553 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6554 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6555 FREE_REFENTRY (orig_pe);
6558 mono_domain_unlock (domain);
6561 #ifdef REFENTRY_REQUIRES_CLEANUP
6563 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6565 FREE_REFENTRY (key);
6570 mono_reflection_cleanup_domain (MonoDomain *domain)
6572 if (domain->refobject_hash) {
6573 /*let's avoid scanning the whole hashtable if not needed*/
6574 #ifdef REFENTRY_REQUIRES_CLEANUP
6575 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6577 mono_g_hash_table_destroy (domain->refobject_hash);
6578 domain->refobject_hash = NULL;
6582 #ifndef DISABLE_REFLECTION_EMIT
6584 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6586 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6590 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6592 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6596 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6598 MonoDynamicImage *image = moduleb->dynamic_image;
6599 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6603 MonoImage **new_modules;
6605 char *name, *fqname;
6607 * FIXME: we already created an image in mono_image_basic_init (), but
6608 * we don't know which module it belongs to, since that is only
6609 * determined at assembly save time.
6611 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6612 name = mono_string_to_utf8 (ab->name);
6613 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6614 if (!mono_error_ok (&error)) {
6616 mono_error_raise_exception (&error);
6618 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6620 moduleb->module.image = &image->image;
6621 moduleb->dynamic_image = image;
6622 register_module (mono_object_domain (moduleb), moduleb, image);
6624 /* register the module with the assembly */
6625 ass = ab->dynamic_assembly->assembly.image;
6626 module_count = ass->module_count;
6627 new_modules = g_new0 (MonoImage *, module_count + 1);
6630 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6631 new_modules [module_count] = &image->image;
6632 mono_image_addref (&image->image);
6634 g_free (ass->modules);
6635 ass->modules = new_modules;
6636 ass->module_count ++;
6641 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6643 MonoDynamicImage *image = moduleb->dynamic_image;
6645 g_assert (type->type);
6646 image->wrappers_type = mono_class_from_mono_type (type->type);
6652 * mono_assembly_get_object:
6653 * @domain: an app domain
6654 * @assembly: an assembly
6656 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6658 MonoReflectionAssembly*
6659 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6662 MonoReflectionAssembly *result;
6663 result = mono_assembly_get_object_checked (domain, assembly, &error);
6665 mono_error_set_pending_exception (&error);
6669 * mono_assembly_get_object:
6670 * @domain: an app domain
6671 * @assembly: an assembly
6673 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6675 MonoReflectionAssembly*
6676 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6678 static MonoClass *assembly_type;
6679 MonoReflectionAssembly *res;
6681 mono_error_init (error);
6683 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6684 if (!assembly_type) {
6685 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6687 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6689 assembly_type = klass;
6691 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, error);
6694 res->assembly = assembly;
6696 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6701 MonoReflectionModule*
6702 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6705 MonoReflectionModule *result;
6706 result = mono_module_get_object_checked (domain, image, &error);
6707 mono_error_raise_exception (&error);
6711 MonoReflectionModule*
6712 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6714 static MonoClass *module_type;
6715 MonoReflectionModule *res;
6718 mono_error_init (error);
6719 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6721 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6723 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6725 module_type = klass;
6727 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, error);
6732 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6735 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6737 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6738 basename = g_path_get_basename (image->name);
6739 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6740 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6744 if (image->assembly->image == image) {
6745 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6749 if (image->assembly->image->modules) {
6750 for (i = 0; i < image->assembly->image->module_count; i++) {
6751 if (image->assembly->image->modules [i] == image)
6752 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6754 g_assert (res->token);
6758 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6761 MonoReflectionModule*
6762 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6765 MonoReflectionModule *result;
6766 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6767 mono_error_raise_exception (&error);
6771 MonoReflectionModule*
6772 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6774 static MonoClass *module_type;
6775 MonoReflectionModule *res;
6776 MonoTableInfo *table;
6777 guint32 cols [MONO_FILE_SIZE];
6779 guint32 i, name_idx;
6782 mono_error_init (error);
6785 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6787 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6789 module_type = klass;
6791 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, error);
6795 table = &image->tables [MONO_TABLE_FILE];
6796 g_assert (table_index < table->rows);
6797 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6800 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6803 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6804 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6806 /* Check whenever the row has a corresponding row in the moduleref table */
6807 table = &image->tables [MONO_TABLE_MODULEREF];
6808 for (i = 0; i < table->rows; ++i) {
6809 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6810 val = mono_metadata_string_heap (image, name_idx);
6811 if (strcmp (val, name) == 0)
6812 res->image = image->modules [i];
6815 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6816 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6817 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6818 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6819 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6825 verify_safe_for_managed_space (MonoType *type)
6827 switch (type->type) {
6829 case MONO_TYPE_ARRAY:
6830 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6832 return verify_safe_for_managed_space (type->data.type);
6833 case MONO_TYPE_SZARRAY:
6834 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6835 case MONO_TYPE_GENERICINST: {
6836 MonoGenericInst *inst = type->data.generic_class->inst;
6840 for (i = 0; i < inst->type_argc; ++i)
6841 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6847 case MONO_TYPE_MVAR:
6855 mono_type_normalize (MonoType *type)
6858 MonoGenericClass *gclass;
6859 MonoGenericInst *ginst;
6861 MonoGenericContainer *gcontainer;
6862 MonoType **argv = NULL;
6863 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6865 if (type->type != MONO_TYPE_GENERICINST)
6868 gclass = type->data.generic_class;
6869 ginst = gclass->context.class_inst;
6870 if (!ginst->is_open)
6873 gtd = gclass->container_class;
6874 gcontainer = gtd->generic_container;
6875 argv = g_newa (MonoType*, ginst->type_argc);
6877 for (i = 0; i < ginst->type_argc; ++i) {
6878 MonoType *t = ginst->type_argv [i], *norm;
6879 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6880 is_denorm_gtd = FALSE;
6881 norm = mono_type_normalize (t);
6884 requires_rebind = TRUE;
6888 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6890 if (requires_rebind) {
6891 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6892 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6898 * mono_type_get_object:
6899 * @domain: an app domain
6902 * Return an System.MonoType object representing the type @type.
6905 mono_type_get_object (MonoDomain *domain, MonoType *type)
6908 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6909 mono_error_raise_exception (&error);
6915 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6917 MonoType *norm_type;
6918 MonoReflectionType *res;
6921 mono_error_init (error);
6923 klass = mono_class_from_mono_type (type);
6925 /*we must avoid using @type as it might have come
6926 * from a mono_metadata_type_dup and the caller
6927 * expects that is can be freed.
6928 * Using the right type from
6930 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6932 /* void is very common */
6933 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6934 return (MonoReflectionType*)domain->typeof_void;
6937 * If the vtable of the given class was already created, we can use
6938 * the MonoType from there and avoid all locking and hash table lookups.
6940 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6941 * that the resulting object is different.
6943 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6944 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6945 if (vtable && vtable->type)
6946 return (MonoReflectionType *)vtable->type;
6949 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6950 mono_domain_lock (domain);
6951 if (!domain->type_hash)
6952 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6953 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6954 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6955 mono_domain_unlock (domain);
6956 mono_loader_unlock ();
6960 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6961 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6962 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6963 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6964 * artifact of how generics are encoded and should be transparent to managed code so we
6965 * need to weed out this diference when retrieving managed System.Type objects.
6967 norm_type = mono_type_normalize (type);
6968 if (norm_type != type) {
6969 res = mono_type_get_object_checked (domain, norm_type, error);
6970 if (!mono_error_ok (error))
6972 mono_g_hash_table_insert (domain->type_hash, type, res);
6973 mono_domain_unlock (domain);
6974 mono_loader_unlock ();
6978 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6979 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6982 if (!verify_safe_for_managed_space (type)) {
6983 mono_domain_unlock (domain);
6984 mono_loader_unlock ();
6985 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6989 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6990 gboolean is_type_done = TRUE;
6991 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6992 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6993 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6995 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6996 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6998 if (gparam->owner && gparam->owner->is_method) {
6999 MonoMethod *method = gparam->owner->owner.method;
7000 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7001 is_type_done = FALSE;
7002 } else if (gparam->owner && !gparam->owner->is_method) {
7003 MonoClass *klass = gparam->owner->owner.klass;
7004 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7005 is_type_done = FALSE;
7009 /* g_assert_not_reached (); */
7010 /* should this be considered an error condition? */
7011 if (is_type_done && !type->byref) {
7012 mono_domain_unlock (domain);
7013 mono_loader_unlock ();
7014 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7017 /* This is stored in vtables/JITted code so it has to be pinned */
7018 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7019 if (!mono_error_ok (error))
7023 mono_g_hash_table_insert (domain->type_hash, type, res);
7025 if (type->type == MONO_TYPE_VOID)
7026 domain->typeof_void = (MonoObject*)res;
7028 mono_domain_unlock (domain);
7029 mono_loader_unlock ();
7034 * mono_method_get_object:
7035 * @domain: an app domain
7037 * @refclass: the reflected type (can be NULL)
7039 * Return an System.Reflection.MonoMethod object representing the method @method.
7041 MonoReflectionMethod*
7042 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7045 MonoReflectionMethod *ret = NULL;
7046 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7047 mono_error_raise_exception (&error);
7052 * mono_method_get_object_checked:
7053 * @domain: an app domain
7055 * @refclass: the reflected type (can be NULL)
7056 * @error: set on error.
7058 * Return an System.Reflection.MonoMethod object representing the method @method.
7059 * Returns NULL and sets @error on error.
7061 MonoReflectionMethod*
7062 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7065 * We use the same C representation for methods and constructors, but the type
7066 * name in C# is different.
7068 static MonoClass *System_Reflection_MonoMethod = NULL;
7069 static MonoClass *System_Reflection_MonoCMethod = NULL;
7070 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
7071 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
7072 MonoReflectionType *rt;
7074 MonoReflectionMethod *ret;
7076 mono_error_init (error);
7078 if (method->is_inflated) {
7079 MonoReflectionGenericMethod *gret;
7082 refclass = method->klass;
7083 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7084 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7085 if (!System_Reflection_MonoGenericCMethod) {
7086 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
7087 if (!mono_error_ok (error))
7090 klass = System_Reflection_MonoGenericCMethod;
7092 if (!System_Reflection_MonoGenericMethod) {
7093 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
7094 if (!mono_error_ok (error))
7097 klass = System_Reflection_MonoGenericMethod;
7099 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7100 if (!mono_error_ok (error))
7102 gret->method.method = method;
7104 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7106 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7107 if (!mono_error_ok (error))
7110 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7112 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7116 refclass = method->klass;
7118 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7119 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7120 if (!System_Reflection_MonoCMethod) {
7121 System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7122 if (!mono_error_ok (error))
7125 klass = System_Reflection_MonoCMethod;
7128 if (!System_Reflection_MonoMethod) {
7129 System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7130 if (!mono_error_ok (error))
7133 klass = System_Reflection_MonoMethod;
7135 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7136 if (!mono_error_ok (error))
7138 ret->method = method;
7140 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7141 if (!mono_error_ok (error))
7144 MONO_OBJECT_SETREF (ret, reftype, rt);
7146 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7149 g_assert (!mono_error_ok (error));
7154 * mono_method_clear_object:
7156 * Clear the cached reflection objects for the dynamic method METHOD.
7159 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7162 g_assert (method_is_dynamic (method));
7164 klass = method->klass;
7166 clear_cached_object (domain, method, klass);
7167 klass = klass->parent;
7169 /* Added by mono_param_get_objects () */
7170 clear_cached_object (domain, &(method->signature), NULL);
7171 klass = method->klass;
7173 clear_cached_object (domain, &(method->signature), klass);
7174 klass = klass->parent;
7179 * mono_field_get_object:
7180 * @domain: an app domain
7184 * Return an System.Reflection.MonoField object representing the field @field
7187 MonoReflectionField*
7188 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7191 MonoReflectionField *result;
7192 result = mono_field_get_object_checked (domain, klass, field, &error);
7193 mono_error_raise_exception (&error);
7198 * mono_field_get_object_checked:
7199 * @domain: an app domain
7202 * @error: set on error
7204 * Return an System.Reflection.MonoField object representing the field @field
7205 * in class @klass. On error, returns NULL and sets @error.
7207 MonoReflectionField*
7208 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7210 MonoReflectionType *rt;
7211 MonoReflectionField *res;
7212 static MonoClass *monofield_klass;
7214 mono_error_init (error);
7216 CHECK_OBJECT (MonoReflectionField *, field, klass);
7217 if (!monofield_klass)
7218 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7219 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7224 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7226 if (is_field_on_inst (field)) {
7227 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7229 rt = mono_type_get_object_checked (domain, field->type, error);
7230 if (!mono_error_ok (error))
7233 MONO_OBJECT_SETREF (res, type, rt);
7236 rt = mono_type_get_object_checked (domain, field->type, error);
7237 if (!mono_error_ok (error))
7240 MONO_OBJECT_SETREF (res, type, rt);
7242 res->attrs = mono_field_get_flags (field);
7244 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7248 * mono_property_get_object:
7249 * @domain: an app domain
7251 * @property: a property
7253 * Return an System.Reflection.MonoProperty object representing the property @property
7256 MonoReflectionProperty*
7257 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7260 MonoReflectionProperty *result;
7261 result = mono_property_get_object_checked (domain, klass, property, &error);
7262 mono_error_raise_exception (&error);
7267 * mono_property_get_object:
7268 * @domain: an app domain
7270 * @property: a property
7271 * @error: set on error
7273 * Return an System.Reflection.MonoProperty object representing the property @property
7274 * in class @klass. On error returns NULL and sets @error.
7276 MonoReflectionProperty*
7277 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7279 MonoReflectionProperty *res;
7280 static MonoClass *monoproperty_klass;
7282 mono_error_init (error);
7284 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7285 if (!monoproperty_klass)
7286 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7287 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, error);
7291 res->property = property;
7292 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7296 * mono_event_get_object:
7297 * @domain: an app domain
7301 * Return an System.Reflection.MonoEvent object representing the event @event
7304 MonoReflectionEvent*
7305 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7308 MonoReflectionEvent *result;
7309 result = mono_event_get_object_checked (domain, klass, event, &error);
7310 mono_error_raise_exception (&error);
7315 * mono_event_get_object_checked:
7316 * @domain: an app domain
7319 * @error: set on error
7321 * Return an System.Reflection.MonoEvent object representing the event @event
7322 * in class @klass. On failure sets @error and returns NULL
7324 MonoReflectionEvent*
7325 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7327 MonoReflectionEvent *res;
7328 MonoReflectionMonoEvent *mono_event;
7329 static MonoClass *monoevent_klass;
7331 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7332 if (!monoevent_klass)
7333 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7334 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, error);
7337 mono_event->klass = klass;
7338 mono_event->event = event;
7339 res = (MonoReflectionEvent*)mono_event;
7340 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7344 * mono_get_reflection_missing_object:
7345 * @domain: Domain where the object lives
7347 * Returns the System.Reflection.Missing.Value singleton object
7348 * (of type System.Reflection.Missing).
7350 * Used as the value for ParameterInfo.DefaultValue when Optional
7354 mono_get_reflection_missing_object (MonoDomain *domain)
7357 static MonoClassField *missing_value_field = NULL;
7359 if (!missing_value_field) {
7360 MonoClass *missing_klass;
7361 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7362 mono_class_init (missing_klass);
7363 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7364 g_assert (missing_value_field);
7366 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7372 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7375 *dbnull = mono_get_dbnull_object (domain);
7380 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7382 if (!*reflection_missing)
7383 *reflection_missing = mono_get_reflection_missing_object (domain);
7384 return *reflection_missing;
7388 * mono_param_get_objects:
7389 * @domain: an app domain
7392 * Return an System.Reflection.ParameterInfo array object representing the parameters
7393 * in the method @method.
7396 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7398 static MonoClass *System_Reflection_ParameterInfo;
7399 static MonoClass *System_Reflection_ParameterInfo_array;
7401 MonoArray *res = NULL;
7402 MonoReflectionMethod *member = NULL;
7403 MonoReflectionParameter *param = NULL;
7404 char **names = NULL, **blobs = NULL;
7405 guint32 *types = NULL;
7406 MonoType *type = NULL;
7407 MonoObject *dbnull = NULL;
7408 MonoObject *missing = NULL;
7409 MonoMarshalSpec **mspecs = NULL;
7410 MonoMethodSignature *sig = NULL;
7411 MonoVTable *pinfo_vtable;
7412 MonoReflectionType *rt;
7415 mono_error_init (&error);
7417 if (!System_Reflection_ParameterInfo_array) {
7420 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7422 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7424 mono_memory_barrier ();
7425 System_Reflection_ParameterInfo = klass;
7428 klass = mono_array_class_get (klass, 1);
7429 mono_memory_barrier ();
7430 System_Reflection_ParameterInfo_array = klass;
7433 sig = mono_method_signature_checked (method, &error);
7434 if (!mono_error_ok (&error))
7437 if (!sig->param_count) {
7438 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7445 /* Note: the cache is based on the address of the signature into the method
7446 * since we already cache MethodInfos with the method as keys.
7448 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7450 member = mono_method_get_object_checked (domain, method, refclass, &error);
7453 names = g_new (char *, sig->param_count);
7454 mono_method_get_param_names (method, (const char **) names);
7456 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7457 mono_method_get_marshal_info (method, mspecs);
7459 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7463 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7464 for (i = 0; i < sig->param_count; ++i) {
7465 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7469 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7473 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7475 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7477 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7479 param->PositionImpl = i;
7480 param->AttrsImpl = sig->params [i]->attrs;
7482 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7483 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7484 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7486 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7490 blobs = g_new0 (char *, sig->param_count);
7491 types = g_new0 (guint32, sig->param_count);
7492 get_default_param_value_blobs (method, blobs, types);
7495 /* Build MonoType for the type from the Constant Table */
7497 type = g_new0 (MonoType, 1);
7498 type->type = (MonoTypeEnum)types [i];
7499 type->data.klass = NULL;
7500 if (types [i] == MONO_TYPE_CLASS)
7501 type->data.klass = mono_defaults.object_class;
7502 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7503 /* For enums, types [i] contains the base type */
7505 type->type = MONO_TYPE_VALUETYPE;
7506 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7508 type->data.klass = mono_class_from_mono_type (type);
7510 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7512 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7513 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7514 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7515 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7517 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7522 if (mspecs [i + 1]) {
7523 MonoReflectionMarshalAsAttribute* mobj;
7524 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7527 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7530 mono_array_setref (res, i, param);
7540 for (i = sig->param_count; i >= 0; i--) {
7542 mono_metadata_free_marshal_spec (mspecs [i]);
7547 mono_error_raise_exception (&error); /* FIXME don't raise here */
7549 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7553 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7555 return mono_param_get_objects_internal (domain, method, NULL);
7559 * mono_method_body_get_object:
7560 * @domain: an app domain
7563 * Return an System.Reflection.MethodBody object representing the method @method.
7565 MonoReflectionMethodBody*
7566 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7568 static MonoClass *System_Reflection_MethodBody = NULL;
7569 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7570 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7572 MonoReflectionMethodBody *ret;
7573 MonoMethodHeader *header;
7575 MonoReflectionType *rt;
7576 guint32 method_rva, local_var_sig_token;
7578 unsigned char format, flags;
7581 /* for compatibility with .net */
7582 if (method_is_dynamic (method))
7583 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7585 if (!System_Reflection_MethodBody)
7586 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7587 if (!System_Reflection_LocalVariableInfo)
7588 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7589 if (!System_Reflection_ExceptionHandlingClause)
7590 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7592 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7594 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7595 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7596 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7597 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7598 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7601 image = method->klass->image;
7602 header = mono_method_get_header (method);
7604 if (!image_is_dynamic (image)) {
7605 /* Obtain local vars signature token */
7606 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7607 ptr = mono_image_rva_map (image, method_rva);
7608 flags = *(const unsigned char *) ptr;
7609 format = flags & METHOD_HEADER_FORMAT_MASK;
7611 case METHOD_HEADER_TINY_FORMAT:
7612 local_var_sig_token = 0;
7614 case METHOD_HEADER_FAT_FORMAT:
7618 local_var_sig_token = read32 (ptr);
7621 g_assert_not_reached ();
7624 local_var_sig_token = 0; //FIXME
7626 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7627 mono_error_raise_exception (&error); /* FIXME don't raise here */
7629 ret->init_locals = header->init_locals;
7630 ret->max_stack = header->max_stack;
7631 ret->local_var_sig_token = local_var_sig_token;
7632 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7633 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7636 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7637 for (i = 0; i < header->num_locals; ++i) {
7638 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7639 mono_error_raise_exception (&error); /* FIXME don't raise here */
7641 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7642 mono_error_raise_exception (&error); /* FIXME don't raise here */
7644 MONO_OBJECT_SETREF (info, local_type, rt);
7646 info->is_pinned = header->locals [i]->pinned;
7647 info->local_index = i;
7648 mono_array_setref (ret->locals, i, info);
7652 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7653 for (i = 0; i < header->num_clauses; ++i) {
7654 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7655 mono_error_raise_exception (&error); /* FIXME don't raise here */
7656 MonoExceptionClause *clause = &header->clauses [i];
7658 info->flags = clause->flags;
7659 info->try_offset = clause->try_offset;
7660 info->try_length = clause->try_len;
7661 info->handler_offset = clause->handler_offset;
7662 info->handler_length = clause->handler_len;
7663 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7664 info->filter_offset = clause->data.filter_offset;
7665 else if (clause->data.catch_class) {
7666 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7667 mono_error_raise_exception (&error); /* FIXME don't raise here */
7669 MONO_OBJECT_SETREF (info, catch_type, rt);
7672 mono_array_setref (ret->clauses, i, info);
7675 mono_metadata_free_mh (header);
7676 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7681 * mono_get_dbnull_object:
7682 * @domain: Domain where the object lives
7684 * Returns the System.DBNull.Value singleton object
7686 * Used as the value for ParameterInfo.DefaultValue
7689 mono_get_dbnull_object (MonoDomain *domain)
7692 static MonoClassField *dbnull_value_field = NULL;
7694 if (!dbnull_value_field) {
7695 MonoClass *dbnull_klass;
7696 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7697 mono_class_init (dbnull_klass);
7698 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7699 g_assert (dbnull_value_field);
7701 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7707 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7709 guint32 param_index, i, lastp, crow = 0;
7710 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7713 MonoClass *klass = method->klass;
7714 MonoImage *image = klass->image;
7715 MonoMethodSignature *methodsig = mono_method_signature (method);
7717 MonoTableInfo *constt;
7718 MonoTableInfo *methodt;
7719 MonoTableInfo *paramt;
7721 if (!methodsig->param_count)
7724 mono_class_init (klass);
7726 if (image_is_dynamic (klass->image)) {
7727 MonoReflectionMethodAux *aux;
7728 if (method->is_inflated)
7729 method = ((MonoMethodInflated*)method)->declaring;
7730 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7731 if (aux && aux->param_defaults) {
7732 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7733 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7738 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7739 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7740 constt = &image->tables [MONO_TABLE_CONSTANT];
7742 idx = mono_method_get_index (method) - 1;
7743 g_assert (idx != -1);
7745 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7746 if (idx + 1 < methodt->rows)
7747 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7749 lastp = paramt->rows + 1;
7751 for (i = param_index; i < lastp; ++i) {
7754 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7755 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7757 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7760 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7765 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7766 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7767 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7774 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7780 MonoType *basetype = type;
7785 klass = mono_class_from_mono_type (type);
7786 if (klass->valuetype) {
7787 object = mono_object_new_checked (domain, klass, &error);
7788 mono_error_raise_exception (&error); /* FIXME don't raise here */
7789 retval = ((gchar *) object + sizeof (MonoObject));
7790 if (klass->enumtype)
7791 basetype = mono_class_enum_basetype (klass);
7796 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7803 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7806 gboolean quoted = FALSE;
7808 memset (assembly, 0, sizeof (MonoAssemblyName));
7809 assembly->culture = "";
7810 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7817 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7828 /* Remove trailing whitespace */
7830 while (*s && g_ascii_isspace (*s))
7833 while (g_ascii_isspace (*p))
7836 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7838 assembly->major = strtoul (p, &s, 10);
7839 if (s == p || *s != '.')
7842 assembly->minor = strtoul (p, &s, 10);
7843 if (s == p || *s != '.')
7846 assembly->build = strtoul (p, &s, 10);
7847 if (s == p || *s != '.')
7850 assembly->revision = strtoul (p, &s, 10);
7854 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7856 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7857 assembly->culture = "";
7860 assembly->culture = p;
7861 while (*p && *p != ',') {
7865 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7867 if (strncmp (p, "null", 4) == 0) {
7872 while (*p && *p != ',') {
7875 len = (p - start + 1);
7876 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7877 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7878 g_strlcpy ((char*)assembly->public_key_token, start, len);
7881 while (*p && *p != ',')
7885 while (g_ascii_isspace (*p) || *p == ',') {
7899 * mono_reflection_parse_type:
7902 * Parse a type name as accepted by the GetType () method and output the info
7903 * extracted in the info structure.
7904 * the name param will be mangled, so, make a copy before passing it to this function.
7905 * The fields in info will be valid until the memory pointed to by name is valid.
7907 * See also mono_type_get_name () below.
7909 * Returns: 0 on parse error.
7912 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7913 MonoTypeNameParse *info)
7915 char *start, *p, *w, *last_point, *startn;
7916 int in_modifiers = 0;
7917 int isbyref = 0, rank = 0, isptr = 0;
7919 start = p = w = name;
7921 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7922 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7923 info->name = info->name_space = NULL;
7924 info->nested = NULL;
7925 info->modifiers = NULL;
7926 info->type_arguments = NULL;
7928 /* last_point separates the namespace from the name */
7931 while (*p == ' ') p++, start++, w++, name++;
7936 *p = 0; /* NULL terminate the name */
7938 info->nested = g_list_append (info->nested, startn);
7939 /* we have parsed the nesting namespace + name */
7943 info->name_space = start;
7945 info->name = last_point + 1;
7947 info->name_space = (char *)"";
7975 info->name_space = start;
7977 info->name = last_point + 1;
7979 info->name_space = (char *)"";
7986 if (isbyref) /* only one level allowed by the spec */
7990 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7994 if (isbyref) /* pointer to ref not okay */
7996 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8001 if (isbyref) /* array of ref and generic ref are not okay */
8003 //Decide if it's an array of a generic argument list
8008 if (*p == ',' || *p == '*' || *p == ']') { //array
8016 else if (*p == '*') /* '*' means unknown lower bound */
8017 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8024 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8026 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8029 info->type_arguments = g_ptr_array_new ();
8031 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8032 gboolean fqname = FALSE;
8034 g_ptr_array_add (info->type_arguments, subinfo);
8036 while (*p == ' ') p++;
8042 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8045 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8046 if (fqname && (*p != ']')) {
8054 while (*p && (*p != ']'))
8062 if (g_ascii_isspace (*aname)) {
8069 !assembly_name_to_aname (&subinfo->assembly, aname))
8071 } else if (fqname && (*p == ']')) {
8093 if (g_ascii_isspace (*p)) {
8100 return 0; /* missing assembly name */
8101 if (!assembly_name_to_aname (&info->assembly, p))
8107 if (info->assembly.name)
8110 // *w = 0; /* terminate class name */
8112 if (!info->name || !*info->name)
8116 /* add other consistency checks */
8122 * mono_identifier_unescape_type_name_chars:
8123 * @identifier: the display name of a mono type
8126 * The name in internal form, that is without escaping backslashes.
8128 * The string is modified in place!
8131 mono_identifier_unescape_type_name_chars(char* identifier)
8136 for (w = r = identifier; *r != 0; r++)
8154 mono_identifier_unescape_info (MonoTypeNameParse* info);
8157 unescape_each_type_argument(void* data, void* user_data)
8159 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8160 mono_identifier_unescape_info (info);
8164 unescape_each_nested_name (void* data, void* user_data)
8166 char* nested_name = (char*) data;
8167 mono_identifier_unescape_type_name_chars(nested_name);
8171 * mono_identifier_unescape_info:
8173 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8177 * Destructively updates the info by unescaping the identifiers that
8178 * comprise the type namespace, name, nested types (if any) and
8179 * generic type arguments (if any).
8181 * The resulting info has the names in internal form.
8185 mono_identifier_unescape_info (MonoTypeNameParse *info)
8189 mono_identifier_unescape_type_name_chars(info->name_space);
8190 mono_identifier_unescape_type_name_chars(info->name);
8191 // but don't escape info->assembly
8192 if (info->type_arguments)
8193 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8195 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8199 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8201 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8203 mono_identifier_unescape_info (info);
8209 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8211 gboolean type_resolve = FALSE;
8213 MonoImage *rootimage = image;
8215 if (info->assembly.name) {
8216 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8217 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8219 * This could happen in the AOT compiler case when the search hook is not
8222 assembly = image->assembly;
8224 /* then we must load the assembly ourselve - see #60439 */
8225 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8229 image = assembly->image;
8230 } else if (!image) {
8231 image = mono_defaults.corlib;
8234 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8235 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8236 image = mono_defaults.corlib;
8237 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8244 * mono_reflection_get_type_internal:
8246 * Returns: may return NULL on success, sets error on failure.
8249 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8254 gboolean bounded = FALSE;
8256 mono_error_init (error);
8258 image = mono_defaults.corlib;
8261 rootimage = mono_defaults.corlib;
8264 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8265 g_assert (mono_error_ok (error)); /* FIXME Don't swallow the error */
8267 klass = mono_class_from_name (image, info->name_space, info->name);
8272 for (mod = info->nested; mod; mod = mod->next) {
8273 gpointer iter = NULL;
8277 mono_class_init (parent);
8279 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8281 char *nested_name, *nested_nspace;
8282 gboolean match = TRUE;
8284 lastp = strrchr ((const char *)mod->data, '.');
8286 /* Nested classes can have namespaces */
8289 nested_name = g_strdup (lastp + 1);
8290 nspace_len = lastp - (char*)mod->data;
8291 nested_nspace = (char *)g_malloc (nspace_len + 1);
8292 memcpy (nested_nspace, mod->data, nspace_len);
8293 nested_nspace [nspace_len] = '\0';
8296 nested_name = (char *)mod->data;
8297 nested_nspace = NULL;
8300 if (nested_nspace) {
8302 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8305 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8311 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8314 if (strcmp (klass->name, nested_name) != 0)
8319 g_free (nested_name);
8320 g_free (nested_nspace);
8332 if (info->type_arguments) {
8333 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8334 MonoReflectionType *the_type;
8338 for (i = 0; i < info->type_arguments->len; i++) {
8339 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8341 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8342 if (!type_args [i]) {
8348 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8352 instance = mono_reflection_bind_generic_parameters (
8353 the_type, info->type_arguments->len, type_args);
8359 klass = mono_class_from_mono_type (instance);
8362 for (mod = info->modifiers; mod; mod = mod->next) {
8363 modval = GPOINTER_TO_UINT (mod->data);
8364 if (!modval) { /* byref: must be last modifier */
8365 return &klass->this_arg;
8366 } else if (modval == -1) {
8367 klass = mono_ptr_class_get (&klass->byval_arg);
8368 } else if (modval == -2) {
8370 } else { /* array rank */
8371 klass = mono_bounded_array_class_get (klass, modval, bounded);
8375 return &klass->byval_arg;
8379 * mono_reflection_get_type:
8380 * @image: a metadata context
8381 * @info: type description structure
8382 * @ignorecase: flag for case-insensitive string compares
8383 * @type_resolve: whenever type resolve was already tried
8385 * Build a MonoType from the type description in @info.
8390 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8391 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8395 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8397 MonoReflectionAssemblyBuilder *abuilder;
8401 mono_error_init (error);
8402 g_assert (assembly_is_dynamic (assembly));
8403 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8407 /* Enumerate all modules */
8410 if (abuilder->modules) {
8411 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8412 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8413 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8416 if (!mono_error_ok (error))
8421 if (!type && abuilder->loaded_modules) {
8422 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8423 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8424 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8427 if (!mono_error_ok (error))
8436 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8440 MonoReflectionAssembly *assembly;
8444 if (image && image_is_dynamic (image))
8445 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8447 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8449 if (!mono_error_ok(&error))
8450 mono_error_raise_exception (&error); /* FIXME don't raise here */
8454 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8461 *type_resolve = TRUE;
8464 /* Reconstruct the type name */
8465 fullName = g_string_new ("");
8466 if (info->name_space && (info->name_space [0] != '\0'))
8467 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8469 g_string_printf (fullName, "%s", info->name);
8470 for (mod = info->nested; mod; mod = mod->next)
8471 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8473 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8475 if (assembly_is_dynamic (assembly->assembly))
8476 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8477 info, ignorecase, &error);
8479 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8480 info, ignorecase, &error);
8482 g_string_free (fullName, TRUE);
8483 if (!mono_error_ok (&error))
8484 mono_error_raise_exception (&error); /* FIXME don't raise here */
8489 mono_reflection_free_type_info (MonoTypeNameParse *info)
8491 g_list_free (info->modifiers);
8492 g_list_free (info->nested);
8494 if (info->type_arguments) {
8497 for (i = 0; i < info->type_arguments->len; i++) {
8498 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8500 mono_reflection_free_type_info (subinfo);
8501 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8505 g_ptr_array_free (info->type_arguments, TRUE);
8510 * mono_reflection_type_from_name:
8512 * @image: a metadata context (can be NULL).
8514 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8515 * it defaults to get the type from @image or, if @image is NULL or loading
8516 * from it fails, uses corlib.
8520 mono_reflection_type_from_name (char *name, MonoImage *image)
8522 MonoType *type = NULL;
8523 MonoTypeNameParse info;
8526 /* Make a copy since parse_type modifies its argument */
8527 tmp = g_strdup (name);
8529 /*g_print ("requested type %s\n", str);*/
8530 if (mono_reflection_parse_type (tmp, &info)) {
8531 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8535 mono_reflection_free_type_info (&info);
8540 * mono_reflection_get_token:
8542 * Return the metadata token of OBJ which should be an object
8543 * representing a metadata element.
8546 mono_reflection_get_token (MonoObject *obj)
8551 klass = obj->vtable->klass;
8553 if (strcmp (klass->name, "MethodBuilder") == 0) {
8554 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8556 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8557 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8558 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8560 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8561 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8562 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8564 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8565 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8566 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8567 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8568 } else if (strcmp (klass->name, "MonoType") == 0) {
8569 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8570 MonoClass *mc = mono_class_from_mono_type (type);
8571 if (!mono_class_init (mc))
8572 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8574 token = mc->type_token;
8575 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8576 strcmp (klass->name, "MonoMethod") == 0 ||
8577 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8578 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8579 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8580 if (m->method->is_inflated) {
8581 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8582 return inflated->declaring->token;
8584 token = m->method->token;
8586 } else if (strcmp (klass->name, "MonoField") == 0) {
8587 MonoReflectionField *f = (MonoReflectionField*)obj;
8589 if (is_field_on_inst (f->field)) {
8590 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8592 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8593 int field_index = f->field - dgclass->fields;
8596 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8597 obj = dgclass->field_objects [field_index];
8598 return mono_reflection_get_token (obj);
8601 token = mono_class_get_field_token (f->field);
8602 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8603 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8605 token = mono_class_get_property_token (p->property);
8606 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8607 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8609 token = mono_class_get_event_token (p->event);
8610 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8611 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8612 MonoClass *member_class = mono_object_class (p->MemberImpl);
8613 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8615 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8616 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8617 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8620 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8621 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8623 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8624 MonoException *ex = mono_get_exception_not_implemented (msg);
8626 mono_raise_exception (ex);
8633 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8637 int slen = mono_metadata_decode_value (p, &p);
8639 mono_error_init (error);
8641 n = (char *)g_memdup (p, slen + 1);
8643 t = mono_reflection_type_from_name (n, image);
8645 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8646 /* We don't free n, it's consumed by mono_error */
8647 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8653 return mono_class_from_mono_type (t);
8657 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8659 int slen, type = t->type;
8660 MonoClass *tklass = t->data.klass;
8662 mono_error_init (error);
8668 case MONO_TYPE_BOOLEAN: {
8669 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8674 case MONO_TYPE_CHAR:
8676 case MONO_TYPE_I2: {
8677 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8682 #if SIZEOF_VOID_P == 4
8688 case MONO_TYPE_I4: {
8689 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8694 #if SIZEOF_VOID_P == 8
8695 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8699 case MONO_TYPE_I8: {
8700 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8705 case MONO_TYPE_R8: {
8706 double *val = (double *)g_malloc (sizeof (double));
8711 case MONO_TYPE_VALUETYPE:
8712 if (t->data.klass->enumtype) {
8713 type = mono_class_enum_basetype (t->data.klass)->type;
8716 MonoClass *k = t->data.klass;
8718 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8719 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8725 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8728 case MONO_TYPE_STRING:
8729 if (*p == (char)0xFF) {
8733 slen = mono_metadata_decode_value (p, &p);
8735 return mono_string_new_len (mono_domain_get (), p, slen);
8736 case MONO_TYPE_CLASS: {
8737 MonoReflectionType *rt;
8740 if (*p == (char)0xFF) {
8745 slen = mono_metadata_decode_value (p, &p);
8746 n = (char *)g_memdup (p, slen + 1);
8748 t = mono_reflection_type_from_name (n, image);
8750 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8751 /* We don't free n, it's consumed by mono_error */
8752 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8758 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8759 if (!mono_error_ok (error))
8764 case MONO_TYPE_OBJECT: {
8767 MonoClass *subc = NULL;
8772 } else if (subt == 0x0E) {
8773 type = MONO_TYPE_STRING;
8775 } else if (subt == 0x1D) {
8776 MonoType simple_type = {{0}};
8780 type = MONO_TYPE_SZARRAY;
8781 if (etype == 0x50) {
8782 tklass = mono_defaults.systemtype_class;
8783 } else if (etype == 0x55) {
8784 tklass = load_cattr_enum_type (image, p, &p, error);
8785 if (!mono_error_ok (error))
8789 /* See Partition II, Appendix B3 */
8790 etype = MONO_TYPE_OBJECT;
8791 simple_type.type = (MonoTypeEnum)etype;
8792 tklass = mono_class_from_mono_type (&simple_type);
8795 } else if (subt == 0x55) {
8798 slen = mono_metadata_decode_value (p, &p);
8799 n = (char *)g_memdup (p, slen + 1);
8801 t = mono_reflection_type_from_name (n, image);
8803 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8804 /* We don't free n, it's consumed by mono_error */
8805 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8810 subc = mono_class_from_mono_type (t);
8811 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8812 MonoType simple_type = {{0}};
8813 simple_type.type = (MonoTypeEnum)subt;
8814 subc = mono_class_from_mono_type (&simple_type);
8816 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8818 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8820 if (mono_error_ok (error)) {
8821 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8822 g_assert (!subc->has_references);
8823 if (mono_error_ok (error))
8824 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8830 case MONO_TYPE_SZARRAY: {
8832 guint32 i, alen, basetype;
8835 if (alen == 0xffffffff) {
8839 arr = mono_array_new (mono_domain_get(), tklass, alen);
8840 basetype = tklass->byval_arg.type;
8841 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8842 basetype = mono_class_enum_basetype (tklass)->type;
8847 case MONO_TYPE_BOOLEAN:
8848 for (i = 0; i < alen; i++) {
8849 MonoBoolean val = *p++;
8850 mono_array_set (arr, MonoBoolean, i, val);
8853 case MONO_TYPE_CHAR:
8856 for (i = 0; i < alen; i++) {
8857 guint16 val = read16 (p);
8858 mono_array_set (arr, guint16, i, val);
8865 for (i = 0; i < alen; i++) {
8866 guint32 val = read32 (p);
8867 mono_array_set (arr, guint32, i, val);
8872 for (i = 0; i < alen; i++) {
8875 mono_array_set (arr, double, i, val);
8881 for (i = 0; i < alen; i++) {
8882 guint64 val = read64 (p);
8883 mono_array_set (arr, guint64, i, val);
8887 case MONO_TYPE_CLASS:
8888 case MONO_TYPE_OBJECT:
8889 case MONO_TYPE_STRING:
8890 case MONO_TYPE_SZARRAY:
8891 for (i = 0; i < alen; i++) {
8892 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8893 if (!mono_error_ok (error))
8895 mono_array_setref (arr, i, item);
8899 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8905 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8911 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8913 static MonoClass *klass;
8914 static MonoMethod *ctor;
8917 void *params [2], *unboxed;
8920 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8922 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8924 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8925 mono_error_raise_exception (&error); /* FIXME don't raise here */
8928 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8929 mono_error_raise_exception (&error); /* FIXME don't raise here */
8930 unboxed = mono_object_unbox (retval);
8932 mono_runtime_invoke_checked (ctor, unboxed, params, &error);
8933 mono_error_raise_exception (&error); /* FIXME don't raise here */
8939 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8941 static MonoClass *klass;
8942 static MonoMethod *ctor;
8945 void *unboxed, *params [2];
8948 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8950 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8953 params [1] = typedarg;
8954 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8955 mono_error_raise_exception (&error); /* FIXME don't raise here */
8956 unboxed = mono_object_unbox (retval);
8958 mono_runtime_invoke_checked (ctor, unboxed, params, &error);
8959 mono_error_raise_exception (&error); /* FIXME don't raise here */
8965 type_is_reference (MonoType *type)
8967 switch (type->type) {
8968 case MONO_TYPE_BOOLEAN:
8969 case MONO_TYPE_CHAR:
8982 case MONO_TYPE_VALUETYPE:
8990 free_param_data (MonoMethodSignature *sig, void **params) {
8992 for (i = 0; i < sig->param_count; ++i) {
8993 if (!type_is_reference (sig->params [i]))
8994 g_free (params [i]);
8999 * Find the field index in the metadata FieldDef table.
9002 find_field_index (MonoClass *klass, MonoClassField *field) {
9005 for (i = 0; i < klass->field.count; ++i) {
9006 if (field == &klass->fields [i])
9007 return klass->field.first + 1 + i;
9013 * Find the property index in the metadata Property table.
9016 find_property_index (MonoClass *klass, MonoProperty *property) {
9019 for (i = 0; i < klass->ext->property.count; ++i) {
9020 if (property == &klass->ext->properties [i])
9021 return klass->ext->property.first + 1 + i;
9027 * Find the event index in the metadata Event table.
9030 find_event_index (MonoClass *klass, MonoEvent *event) {
9033 for (i = 0; i < klass->ext->event.count; ++i) {
9034 if (event == &klass->ext->events [i])
9035 return klass->ext->event.first + 1 + i;
9041 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9043 const char *p = (const char*)data;
9045 guint32 i, j, num_named;
9047 void *params_buf [32];
9048 void **params = NULL;
9049 MonoMethodSignature *sig;
9050 MonoObject *exc = NULL;
9052 mono_error_init (error);
9054 mono_class_init (method->klass);
9056 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9057 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9062 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9063 if (!mono_error_ok (error)) return NULL;
9065 mono_runtime_invoke_checked (method, attr, NULL, error);
9066 if (!mono_error_ok (error))
9072 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9075 /*g_print ("got attr %s\n", method->klass->name);*/
9077 sig = mono_method_signature (method);
9078 if (sig->param_count < 32) {
9079 params = params_buf;
9080 memset (params, 0, sizeof (void*) * sig->param_count);
9082 /* Allocate using GC so it gets GC tracking */
9083 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9088 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9089 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9090 if (!mono_error_ok (error))
9095 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9096 if (!mono_error_ok (error)) goto fail;
9098 mono_runtime_try_invoke (method, attr, params, &exc, error);
9099 if (!mono_error_ok (error))
9104 num_named = read16 (named);
9106 for (j = 0; j < num_named; j++) {
9108 char *name, named_type, data_type;
9109 named_type = *named++;
9110 data_type = *named++; /* type of data */
9111 if (data_type == MONO_TYPE_SZARRAY)
9112 data_type = *named++;
9113 if (data_type == MONO_TYPE_ENUM) {
9116 type_len = mono_metadata_decode_blob_size (named, &named);
9117 type_name = (char *)g_malloc (type_len + 1);
9118 memcpy (type_name, named, type_len);
9119 type_name [type_len] = 0;
9121 /* FIXME: lookup the type and check type consistency */
9124 name_len = mono_metadata_decode_blob_size (named, &named);
9125 name = (char *)g_malloc (name_len + 1);
9126 memcpy (name, named, name_len);
9127 name [name_len] = 0;
9129 if (named_type == 0x53) {
9130 MonoClassField *field;
9133 /* how this fail is a blackbox */
9134 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9136 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9141 val = load_cattr_value (image, field->type, named, &named, error);
9142 if (!mono_error_ok (error)) {
9144 if (!type_is_reference (field->type))
9149 mono_field_set_value (attr, field, val);
9150 if (!type_is_reference (field->type))
9152 } else if (named_type == 0x54) {
9155 MonoType *prop_type;
9157 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9160 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9166 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9171 /* can we have more that 1 arg in a custom attr named property? */
9172 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9173 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9175 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9176 if (!mono_error_ok (error)) {
9178 if (!type_is_reference (prop_type))
9179 g_free (pparams [0]);
9184 mono_property_set_value (prop, attr, pparams, NULL);
9185 if (!type_is_reference (prop_type))
9186 g_free (pparams [0]);
9191 free_param_data (method->signature, params);
9192 if (params != params_buf)
9193 mono_gc_free_fixed (params);
9198 free_param_data (method->signature, params);
9199 if (params != params_buf)
9200 mono_gc_free_fixed (params);
9202 mono_raise_exception ((MonoException*)exc);
9207 * mono_reflection_create_custom_attr_data_args:
9209 * Create an array of typed and named arguments from the cattr blob given by DATA.
9210 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9211 * NAMED_ARG_INFO will contain information about the named arguments.
9214 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)
9216 MonoArray *typedargs, *namedargs;
9217 MonoClass *attrklass;
9219 const char *p = (const char*)data;
9221 guint32 i, j, num_named;
9222 CattrNamedArg *arginfo = NULL;
9226 *named_arg_info = NULL;
9228 mono_error_init (error);
9230 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9231 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9235 mono_class_init (method->klass);
9237 domain = mono_domain_get ();
9239 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9242 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9246 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9250 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9251 if (!mono_error_ok (error)) {
9252 if (!type_is_reference (mono_method_signature (method)->params [i]))
9257 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9258 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9259 mono_array_setref (typedargs, i, obj);
9261 if (!type_is_reference (mono_method_signature (method)->params [i]))
9266 num_named = read16 (named);
9267 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9269 attrklass = method->klass;
9271 arginfo = g_new0 (CattrNamedArg, num_named);
9272 *named_arg_info = arginfo;
9274 for (j = 0; j < num_named; j++) {
9276 char *name, named_type, data_type;
9277 named_type = *named++;
9278 data_type = *named++; /* type of data */
9279 if (data_type == MONO_TYPE_SZARRAY)
9280 data_type = *named++;
9281 if (data_type == MONO_TYPE_ENUM) {
9284 type_len = mono_metadata_decode_blob_size (named, &named);
9285 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9288 type_name = (char *)g_malloc (type_len + 1);
9289 memcpy (type_name, named, type_len);
9290 type_name [type_len] = 0;
9292 /* FIXME: lookup the type and check type consistency */
9295 name_len = mono_metadata_decode_blob_size (named, &named);
9296 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9298 name = (char *)g_malloc (name_len + 1);
9299 memcpy (name, named, name_len);
9300 name [name_len] = 0;
9302 if (named_type == 0x53) {
9304 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9312 arginfo [j].type = field->type;
9313 arginfo [j].field = field;
9315 val = load_cattr_value (image, field->type, named, &named, error);
9316 if (!mono_error_ok (error)) {
9317 if (!type_is_reference (field->type))
9323 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9324 mono_array_setref (namedargs, j, obj);
9325 if (!type_is_reference (field->type))
9327 } else if (named_type == 0x54) {
9329 MonoType *prop_type;
9330 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9333 if (!prop || !prop->set) {
9338 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9339 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9341 arginfo [j].type = prop_type;
9342 arginfo [j].prop = prop;
9344 val = load_cattr_value (image, prop_type, named, &named, error);
9345 if (!mono_error_ok (error)) {
9346 if (!type_is_reference (prop_type))
9352 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9353 mono_array_setref (namedargs, j, obj);
9354 if (!type_is_reference (prop_type))
9360 *typed_args = typedargs;
9361 *named_args = namedargs;
9364 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9366 *named_arg_info = NULL;
9370 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9373 MonoArray *typedargs, *namedargs;
9376 CattrNamedArg *arginfo = NULL;
9380 mono_error_init (&error);
9388 image = assembly->assembly->image;
9389 method = ref_method->method;
9390 domain = mono_object_domain (ref_method);
9392 if (!mono_class_init (method->klass))
9393 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9395 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9396 if (!mono_error_ok (&error))
9399 if (mono_loader_get_last_error ()) {
9400 mono_error_set_from_loader_error (&error);
9404 if (!typedargs || !namedargs)
9407 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9408 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9409 MonoObject *typedarg;
9411 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9412 mono_array_setref (typedargs, i, typedarg);
9415 for (i = 0; i < mono_array_length (namedargs); ++i) {
9416 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9417 MonoObject *typedarg, *namedarg, *minfo;
9419 if (arginfo [i].prop) {
9420 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9424 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9425 if (!mono_error_ok (&error))
9429 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9430 namedarg = create_cattr_named_arg (minfo, typedarg);
9432 mono_array_setref (namedargs, i, namedarg);
9435 *ctor_args = typedargs;
9436 *named_args = namedargs;
9439 mono_error_raise_exception (&error);
9444 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9446 static MonoMethod *ctor;
9453 g_assert (image->assembly);
9456 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9458 domain = mono_domain_get ();
9459 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9460 mono_error_raise_exception (&error); /* FIXME don't raise here */
9461 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9462 mono_error_raise_exception (&error); /* FIXME don't raise here */
9463 params [1] = mono_assembly_get_object_checked (domain, image->assembly, &error);
9464 mono_error_raise_exception (&error); /* FIXME don't raise here */
9465 params [2] = (gpointer)&cattr->data;
9466 params [3] = &cattr->data_size;
9468 mono_runtime_invoke_checked (ctor, attr, params, &error);
9469 mono_error_raise_exception (&error); /* FIXME don't raise here */
9475 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9481 mono_error_init (error);
9484 for (i = 0; i < cinfo->num_attrs; ++i) {
9485 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9489 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9491 for (i = 0; i < cinfo->num_attrs; ++i) {
9492 if (!cinfo->attrs [i].ctor) {
9493 /* The cattr type is not finished yet */
9494 /* We should include the type name but cinfo doesn't contain it */
9495 mono_error_set_type_load_name (error, NULL, NULL, "");
9498 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9499 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9500 if (!mono_error_ok (error))
9502 mono_array_setref (result, n, attr);
9510 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9513 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9514 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9520 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9526 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9527 for (i = 0; i < cinfo->num_attrs; ++i) {
9528 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9529 mono_array_setref (result, i, attr);
9535 * mono_custom_attrs_from_index:
9537 * Returns: NULL if no attributes are found or if a loading error occurs.
9540 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9542 guint32 mtoken, i, len;
9543 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9545 MonoCustomAttrInfo *ainfo;
9546 GList *tmp, *list = NULL;
9548 MonoCustomAttrEntry* attr;
9550 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9552 i = mono_metadata_custom_attrs_from_index (image, idx);
9556 while (i < ca->rows) {
9557 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9559 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9562 len = g_list_length (list);
9565 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9566 ainfo->num_attrs = len;
9567 ainfo->image = image;
9568 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9570 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9571 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9572 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9573 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9574 mtoken |= MONO_TOKEN_METHOD_DEF;
9576 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9577 mtoken |= MONO_TOKEN_MEMBER_REF;
9580 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9583 attr = &ainfo->attrs [i - 1];
9584 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9586 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9587 mono_loader_set_error_from_mono_error (&error);
9593 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9594 /*FIXME raising an exception here doesn't make any sense*/
9595 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9600 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9601 attr->data_size = mono_metadata_decode_value (data, &data);
9602 attr->data = (guchar*)data;
9610 mono_custom_attrs_from_method (MonoMethod *method)
9615 * An instantiated method has the same cattrs as the generic method definition.
9617 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9618 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9620 if (method->is_inflated)
9621 method = ((MonoMethodInflated *) method)->declaring;
9623 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9624 return lookup_custom_attr (method->klass->image, method);
9627 /* Synthetic methods */
9630 idx = mono_method_get_index (method);
9631 idx <<= MONO_CUSTOM_ATTR_BITS;
9632 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9633 return mono_custom_attrs_from_index (method->klass->image, idx);
9637 mono_custom_attrs_from_class (MonoClass *klass)
9641 if (klass->generic_class)
9642 klass = klass->generic_class->container_class;
9644 if (image_is_dynamic (klass->image))
9645 return lookup_custom_attr (klass->image, klass);
9647 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9648 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9649 idx <<= MONO_CUSTOM_ATTR_BITS;
9650 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9652 idx = mono_metadata_token_index (klass->type_token);
9653 idx <<= MONO_CUSTOM_ATTR_BITS;
9654 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9656 return mono_custom_attrs_from_index (klass->image, idx);
9660 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9664 if (image_is_dynamic (assembly->image))
9665 return lookup_custom_attr (assembly->image, assembly);
9666 idx = 1; /* there is only one assembly */
9667 idx <<= MONO_CUSTOM_ATTR_BITS;
9668 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9669 return mono_custom_attrs_from_index (assembly->image, idx);
9672 static MonoCustomAttrInfo*
9673 mono_custom_attrs_from_module (MonoImage *image)
9677 if (image_is_dynamic (image))
9678 return lookup_custom_attr (image, image);
9679 idx = 1; /* there is only one module */
9680 idx <<= MONO_CUSTOM_ATTR_BITS;
9681 idx |= MONO_CUSTOM_ATTR_MODULE;
9682 return mono_custom_attrs_from_index (image, idx);
9686 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9690 if (image_is_dynamic (klass->image)) {
9691 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9692 return lookup_custom_attr (klass->image, property);
9694 idx = find_property_index (klass, property);
9695 idx <<= MONO_CUSTOM_ATTR_BITS;
9696 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9697 return mono_custom_attrs_from_index (klass->image, idx);
9701 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9705 if (image_is_dynamic (klass->image)) {
9706 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9707 return lookup_custom_attr (klass->image, event);
9709 idx = find_event_index (klass, event);
9710 idx <<= MONO_CUSTOM_ATTR_BITS;
9711 idx |= MONO_CUSTOM_ATTR_EVENT;
9712 return mono_custom_attrs_from_index (klass->image, idx);
9716 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9719 if (image_is_dynamic (klass->image)) {
9720 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9721 return lookup_custom_attr (klass->image, field);
9723 idx = find_field_index (klass, field);
9724 idx <<= MONO_CUSTOM_ATTR_BITS;
9725 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9726 return mono_custom_attrs_from_index (klass->image, idx);
9730 * mono_custom_attrs_from_param:
9731 * @method: handle to the method that we want to retrieve custom parameter information from
9732 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9734 * The result must be released with mono_custom_attrs_free().
9736 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9739 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9742 guint32 i, idx, method_index;
9743 guint32 param_list, param_last, param_pos, found;
9745 MonoReflectionMethodAux *aux;
9748 * An instantiated method has the same cattrs as the generic method definition.
9750 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9751 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9753 if (method->is_inflated)
9754 method = ((MonoMethodInflated *) method)->declaring;
9756 if (image_is_dynamic (method->klass->image)) {
9757 MonoCustomAttrInfo *res, *ainfo;
9760 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9761 if (!aux || !aux->param_cattr)
9764 /* Need to copy since it will be freed later */
9765 ainfo = aux->param_cattr [param];
9768 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9769 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9770 memcpy (res, ainfo, size);
9774 image = method->klass->image;
9775 method_index = mono_method_get_index (method);
9778 ca = &image->tables [MONO_TABLE_METHOD];
9780 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9781 if (method_index == ca->rows) {
9782 ca = &image->tables [MONO_TABLE_PARAM];
9783 param_last = ca->rows + 1;
9785 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9786 ca = &image->tables [MONO_TABLE_PARAM];
9789 for (i = param_list; i < param_last; ++i) {
9790 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9791 if (param_pos == param) {
9799 idx <<= MONO_CUSTOM_ATTR_BITS;
9800 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9801 return mono_custom_attrs_from_index (image, idx);
9805 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9809 for (i = 0; i < ainfo->num_attrs; ++i) {
9810 klass = ainfo->attrs [i].ctor->klass;
9811 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9818 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9821 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9822 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9827 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9833 mono_error_init (error);
9836 for (i = 0; i < ainfo->num_attrs; ++i) {
9837 klass = ainfo->attrs [i].ctor->klass;
9838 if (mono_class_has_parent (klass, attr_klass)) {
9843 if (attr_index == -1)
9846 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9847 if (!mono_error_ok (error))
9849 return mono_array_get (attrs, MonoObject*, attr_index);
9853 * mono_reflection_get_custom_attrs_info:
9854 * @obj: a reflection object handle
9856 * Return the custom attribute info for attributes defined for the
9857 * reflection handle @obj. The objects.
9859 * FIXME this function leaks like a sieve for SRE objects.
9862 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9865 MonoCustomAttrInfo *cinfo = NULL;
9867 klass = obj->vtable->klass;
9868 if (klass == mono_defaults.monotype_class) {
9869 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9870 klass = mono_class_from_mono_type (type);
9871 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9872 cinfo = mono_custom_attrs_from_class (klass);
9873 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9874 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9875 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9876 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9877 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9878 cinfo = mono_custom_attrs_from_module (module->image);
9879 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9880 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9881 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9882 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9883 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9884 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9885 } else if (strcmp ("MonoField", klass->name) == 0) {
9886 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9887 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9888 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9889 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9890 cinfo = mono_custom_attrs_from_method (rmethod->method);
9891 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9892 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9893 cinfo = mono_custom_attrs_from_method (rmethod->method);
9894 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9895 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9896 MonoClass *member_class = mono_object_class (param->MemberImpl);
9897 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9898 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9899 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9900 } else if (is_sr_mono_property (member_class)) {
9901 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9903 if (!(method = prop->property->get))
9904 method = prop->property->set;
9907 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9909 #ifndef DISABLE_REFLECTION_EMIT
9910 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9911 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9912 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9913 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9914 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9915 MonoMethod *method = NULL;
9916 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9917 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9918 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9919 method = ((MonoReflectionMethod *)c->cb)->method;
9921 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));
9923 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9927 char *type_name = mono_type_get_full_name (member_class);
9928 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9929 MonoException *ex = mono_get_exception_not_supported (msg);
9932 mono_raise_exception (ex);
9934 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9935 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9936 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9937 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9938 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9939 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9940 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9941 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9942 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9943 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9944 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9945 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9946 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9947 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9948 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9949 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9950 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9951 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9952 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9953 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9954 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9955 } else { /* handle other types here... */
9956 g_error ("get custom attrs not yet supported for %s", klass->name);
9963 * mono_reflection_get_custom_attrs_by_type:
9964 * @obj: a reflection object handle
9966 * Return an array with all the custom attributes defined of the
9967 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9968 * of that type are returned. The objects are fully build. Return NULL if a loading error
9972 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9975 MonoCustomAttrInfo *cinfo;
9977 mono_error_init (error);
9979 cinfo = mono_reflection_get_custom_attrs_info (obj);
9981 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9985 mono_custom_attrs_free (cinfo);
9987 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9988 if (mono_loader_get_last_error ())
9990 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9997 * mono_reflection_get_custom_attrs:
9998 * @obj: a reflection object handle
10000 * Return an array with all the custom attributes defined of the
10001 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10005 mono_reflection_get_custom_attrs (MonoObject *obj)
10009 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10013 * mono_reflection_get_custom_attrs_data:
10014 * @obj: a reflection obj handle
10016 * Returns an array of System.Reflection.CustomAttributeData,
10017 * which include information about attributes reflected on
10018 * types loaded using the Reflection Only methods
10021 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10024 MonoCustomAttrInfo *cinfo;
10026 cinfo = mono_reflection_get_custom_attrs_info (obj);
10028 result = mono_custom_attrs_data_construct (cinfo);
10029 if (!cinfo->cached)
10030 mono_custom_attrs_free (cinfo);
10032 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10037 static MonoReflectionType*
10038 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
10040 static MonoMethod *method_get_underlying_system_type = NULL;
10042 MonoReflectionType *rt;
10043 MonoMethod *usertype_method;
10045 if (!method_get_underlying_system_type)
10046 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10048 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10050 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, &error);
10051 mono_error_raise_exception (&error); /* FIXME don't raise here */
10058 is_corlib_type (MonoClass *klass)
10060 return klass->image == mono_defaults.corlib;
10063 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10064 static MonoClass *cached_class; \
10065 if (cached_class) \
10066 return cached_class == _class; \
10067 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10068 cached_class = _class; \
10075 #ifndef DISABLE_REFLECTION_EMIT
10077 is_sre_array (MonoClass *klass)
10079 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10083 is_sre_byref (MonoClass *klass)
10085 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10089 is_sre_pointer (MonoClass *klass)
10091 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10095 is_sre_generic_instance (MonoClass *klass)
10097 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10101 is_sre_type_builder (MonoClass *klass)
10103 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10107 is_sre_method_builder (MonoClass *klass)
10109 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10113 is_sre_ctor_builder (MonoClass *klass)
10115 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10119 is_sre_field_builder (MonoClass *klass)
10121 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10125 is_sre_method_on_tb_inst (MonoClass *klass)
10127 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10131 is_sre_ctor_on_tb_inst (MonoClass *klass)
10133 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10137 mono_reflection_type_get_handle (MonoReflectionType* ref)
10145 if (is_usertype (ref)) {
10146 ref = mono_reflection_type_get_underlying_system_type (ref);
10147 if (ref == NULL || is_usertype (ref))
10153 klass = mono_object_class (ref);
10155 if (is_sre_array (klass)) {
10157 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10158 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10160 if (sre_array->rank == 0) //single dimentional array
10161 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10163 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10164 sre_array->type.type = res;
10166 } else if (is_sre_byref (klass)) {
10168 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10169 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10171 res = &mono_class_from_mono_type (base)->this_arg;
10172 sre_byref->type.type = res;
10174 } else if (is_sre_pointer (klass)) {
10176 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10177 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10179 res = &mono_ptr_class_get (base)->byval_arg;
10180 sre_pointer->type.type = res;
10182 } else if (is_sre_generic_instance (klass)) {
10183 MonoType *res, **types;
10184 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10187 count = mono_array_length (gclass->type_arguments);
10188 types = g_new0 (MonoType*, count);
10189 for (i = 0; i < count; ++i) {
10190 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10191 types [i] = mono_reflection_type_get_handle (t);
10198 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10201 gclass->type.type = res;
10205 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10212 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10214 mono_reflection_type_get_handle (type);
10218 mono_reflection_register_with_runtime (MonoReflectionType *type)
10220 MonoType *res = mono_reflection_type_get_handle (type);
10221 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10225 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10227 klass = mono_class_from_mono_type (res);
10229 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10230 mono_domain_lock (domain);
10232 if (!image_is_dynamic (klass->image)) {
10233 mono_class_setup_supertypes (klass);
10235 if (!domain->type_hash)
10236 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10237 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10238 mono_g_hash_table_insert (domain->type_hash, res, type);
10240 mono_domain_unlock (domain);
10241 mono_loader_unlock ();
10245 * LOCKING: Assumes the loader lock is held.
10247 static MonoMethodSignature*
10248 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10249 MonoMethodSignature *sig;
10252 count = parameters? mono_array_length (parameters): 0;
10254 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10255 sig->param_count = count;
10256 sig->sentinelpos = -1; /* FIXME */
10257 for (i = 0; i < count; ++i)
10258 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10263 * LOCKING: Assumes the loader lock is held.
10265 static MonoMethodSignature*
10266 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10267 MonoMethodSignature *sig;
10269 sig = parameters_to_signature (image, ctor->parameters);
10270 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10271 sig->ret = &mono_defaults.void_class->byval_arg;
10276 * LOCKING: Assumes the loader lock is held.
10278 static MonoMethodSignature*
10279 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10280 MonoMethodSignature *sig;
10282 sig = parameters_to_signature (image, method->parameters);
10283 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10284 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10285 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10289 static MonoMethodSignature*
10290 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10291 MonoMethodSignature *sig;
10293 sig = parameters_to_signature (NULL, method->parameters);
10294 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10295 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10296 sig->generic_param_count = 0;
10301 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10303 MonoClass *klass = mono_object_class (prop);
10304 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10305 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10306 *name = mono_string_to_utf8 (pb->name);
10307 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10309 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10310 *name = g_strdup (p->property->name);
10311 if (p->property->get)
10312 *type = mono_method_signature (p->property->get)->ret;
10314 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10319 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10321 MonoClass *klass = mono_object_class (field);
10322 if (strcmp (klass->name, "FieldBuilder") == 0) {
10323 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10324 *name = mono_string_to_utf8 (fb->name);
10325 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10327 MonoReflectionField *f = (MonoReflectionField *)field;
10328 *name = g_strdup (mono_field_get_name (f->field));
10329 *type = f->field->type;
10333 #else /* DISABLE_REFLECTION_EMIT */
10336 mono_reflection_register_with_runtime (MonoReflectionType *type)
10338 /* This is empty */
10342 is_sre_type_builder (MonoClass *klass)
10348 is_sre_generic_instance (MonoClass *klass)
10354 init_type_builder_generics (MonoObject *type)
10358 #endif /* !DISABLE_REFLECTION_EMIT */
10362 is_sr_mono_field (MonoClass *klass)
10364 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10368 is_sr_mono_property (MonoClass *klass)
10370 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10374 is_sr_mono_method (MonoClass *klass)
10376 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10380 is_sr_mono_cmethod (MonoClass *klass)
10382 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10386 is_sr_mono_generic_method (MonoClass *klass)
10388 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10392 is_sr_mono_generic_cmethod (MonoClass *klass)
10394 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10398 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10400 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10404 is_usertype (MonoReflectionType *ref)
10406 MonoClass *klass = mono_object_class (ref);
10407 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10410 static MonoReflectionType*
10411 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10413 mono_error_init (error);
10414 if (!type || type->type)
10417 if (is_usertype (type)) {
10418 type = mono_reflection_type_get_underlying_system_type (type);
10419 if (is_usertype (type)) {
10420 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10428 * Encode a value in a custom attribute stream of bytes.
10429 * The value to encode is either supplied as an object in argument val
10430 * (valuetypes are boxed), or as a pointer to the data in the
10432 * @type represents the type of the value
10433 * @buffer is the start of the buffer
10434 * @p the current position in the buffer
10435 * @buflen contains the size of the buffer and is used to return the new buffer size
10436 * if this needs to be realloced.
10437 * @retbuffer and @retp return the start and the position of the buffer
10440 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10442 MonoTypeEnum simple_type;
10444 if ((p-buffer) + 10 >= *buflen) {
10447 newbuf = (char *)g_realloc (buffer, *buflen);
10448 p = newbuf + (p-buffer);
10452 argval = ((char*)arg + sizeof (MonoObject));
10453 simple_type = type->type;
10455 switch (simple_type) {
10456 case MONO_TYPE_BOOLEAN:
10461 case MONO_TYPE_CHAR:
10464 swap_with_size (p, argval, 2, 1);
10470 swap_with_size (p, argval, 4, 1);
10474 swap_with_size (p, argval, 8, 1);
10479 swap_with_size (p, argval, 8, 1);
10482 case MONO_TYPE_VALUETYPE:
10483 if (type->data.klass->enumtype) {
10484 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10487 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10490 case MONO_TYPE_STRING: {
10497 str = mono_string_to_utf8 ((MonoString*)arg);
10498 slen = strlen (str);
10499 if ((p-buffer) + 10 + slen >= *buflen) {
10503 newbuf = (char *)g_realloc (buffer, *buflen);
10504 p = newbuf + (p-buffer);
10507 mono_metadata_encode_value (slen, p, &p);
10508 memcpy (p, str, slen);
10513 case MONO_TYPE_CLASS: {
10521 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10522 slen = strlen (str);
10523 if ((p-buffer) + 10 + slen >= *buflen) {
10527 newbuf = (char *)g_realloc (buffer, *buflen);
10528 p = newbuf + (p-buffer);
10531 mono_metadata_encode_value (slen, p, &p);
10532 memcpy (p, str, slen);
10537 case MONO_TYPE_SZARRAY: {
10539 MonoClass *eclass, *arg_eclass;
10542 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10545 len = mono_array_length ((MonoArray*)arg);
10547 *p++ = (len >> 8) & 0xff;
10548 *p++ = (len >> 16) & 0xff;
10549 *p++ = (len >> 24) & 0xff;
10551 *retbuffer = buffer;
10552 eclass = type->data.klass;
10553 arg_eclass = mono_object_class (arg)->element_class;
10556 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10557 eclass = mono_defaults.object_class;
10559 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10560 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10561 int elsize = mono_class_array_element_size (arg_eclass);
10562 for (i = 0; i < len; ++i) {
10563 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10566 } else if (eclass->valuetype && arg_eclass->valuetype) {
10567 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10568 int elsize = mono_class_array_element_size (eclass);
10569 for (i = 0; i < len; ++i) {
10570 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10574 for (i = 0; i < len; ++i) {
10575 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10580 case MONO_TYPE_OBJECT: {
10586 * The parameter type is 'object' but the type of the actual
10587 * argument is not. So we have to add type information to the blob
10588 * too. This is completely undocumented in the spec.
10592 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10597 klass = mono_object_class (arg);
10599 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10602 } else if (klass->enumtype) {
10604 } else if (klass == mono_defaults.string_class) {
10605 simple_type = MONO_TYPE_STRING;
10608 } else if (klass->rank == 1) {
10610 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10611 /* See Partition II, Appendix B3 */
10614 *p++ = klass->element_class->byval_arg.type;
10615 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10617 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10618 *p++ = simple_type = klass->byval_arg.type;
10621 g_error ("unhandled type in custom attr");
10623 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10624 slen = strlen (str);
10625 if ((p-buffer) + 10 + slen >= *buflen) {
10629 newbuf = (char *)g_realloc (buffer, *buflen);
10630 p = newbuf + (p-buffer);
10633 mono_metadata_encode_value (slen, p, &p);
10634 memcpy (p, str, slen);
10637 simple_type = mono_class_enum_basetype (klass)->type;
10641 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10644 *retbuffer = buffer;
10648 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10650 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10651 char *str = type_get_qualified_name (type, NULL);
10652 int slen = strlen (str);
10656 * This seems to be optional...
10659 mono_metadata_encode_value (slen, p, &p);
10660 memcpy (p, str, slen);
10663 } else if (type->type == MONO_TYPE_OBJECT) {
10665 } else if (type->type == MONO_TYPE_CLASS) {
10666 /* it should be a type: encode_cattr_value () has the check */
10669 mono_metadata_encode_value (type->type, p, &p);
10670 if (type->type == MONO_TYPE_SZARRAY)
10671 /* See the examples in Partition VI, Annex B */
10672 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10678 #ifndef DISABLE_REFLECTION_EMIT
10680 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10683 /* Preallocate a large enough buffer */
10684 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10685 char *str = type_get_qualified_name (type, NULL);
10686 len = strlen (str);
10688 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10689 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10690 len = strlen (str);
10695 len += strlen (name);
10697 if ((p-buffer) + 20 + len >= *buflen) {
10701 newbuf = (char *)g_realloc (buffer, *buflen);
10702 p = newbuf + (p-buffer);
10706 encode_field_or_prop_type (type, p, &p);
10708 len = strlen (name);
10709 mono_metadata_encode_value (len, p, &p);
10710 memcpy (p, name, len);
10712 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10714 *retbuffer = buffer;
10718 * mono_reflection_get_custom_attrs_blob:
10719 * @ctor: custom attribute constructor
10720 * @ctorArgs: arguments o the constructor
10726 * Creates the blob of data that needs to be saved in the metadata and that represents
10727 * the custom attributed described by @ctor, @ctorArgs etc.
10728 * Returns: a Byte array representing the blob of data.
10731 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10734 MonoMethodSignature *sig;
10739 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10740 /* sig is freed later so allocate it in the heap */
10741 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10743 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10746 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10748 p = buffer = (char *)g_malloc (buflen);
10749 /* write the prolog */
10752 for (i = 0; i < sig->param_count; ++i) {
10753 arg = mono_array_get (ctorArgs, MonoObject*, i);
10754 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10758 i += mono_array_length (properties);
10760 i += mono_array_length (fields);
10762 *p++ = (i >> 8) & 0xff;
10765 for (i = 0; i < mono_array_length (properties); ++i) {
10769 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10770 get_prop_name_and_type (prop, &pname, &ptype);
10771 *p++ = 0x54; /* PROPERTY signature */
10772 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10779 for (i = 0; i < mono_array_length (fields); ++i) {
10783 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10784 get_field_name_and_type (field, &fname, &ftype);
10785 *p++ = 0x53; /* FIELD signature */
10786 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10791 g_assert (p - buffer <= buflen);
10792 buflen = p - buffer;
10793 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10794 p = mono_array_addr (result, char, 0);
10795 memcpy (p, buffer, buflen);
10797 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10803 * mono_reflection_setup_internal_class:
10804 * @tb: a TypeBuilder object
10806 * Creates a MonoClass that represents the TypeBuilder.
10807 * This is a trick that lets us simplify a lot of reflection code
10808 * (and will allow us to support Build and Run assemblies easier).
10811 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10814 MonoClass *klass, *parent;
10816 RESOLVE_TYPE (tb->parent, &error);
10817 mono_error_raise_exception (&error); /* FIXME don't raise here */
10819 mono_loader_lock ();
10822 /* check so we can compile corlib correctly */
10823 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10824 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10825 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10827 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10833 /* the type has already being created: it means we just have to change the parent */
10834 if (tb->type.type) {
10835 klass = mono_class_from_mono_type (tb->type.type);
10836 klass->parent = NULL;
10837 /* fool mono_class_setup_parent */
10838 klass->supertypes = NULL;
10839 mono_class_setup_parent (klass, parent);
10840 mono_class_setup_mono_type (klass);
10841 mono_loader_unlock ();
10845 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10847 klass->image = &tb->module->dynamic_image->image;
10849 klass->inited = 1; /* we lie to the runtime */
10850 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10851 if (!mono_error_ok (&error))
10853 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10854 if (!mono_error_ok (&error))
10856 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10857 klass->flags = tb->attrs;
10859 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10861 klass->element_class = klass;
10863 if (mono_class_get_ref_info (klass) == NULL) {
10865 mono_class_set_ref_info (klass, tb);
10867 /* Put into cache so mono_class_get_checked () will find it.
10868 Skip nested types as those should not be available on the global scope. */
10869 if (!tb->nesting_type)
10870 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10873 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10874 by performing a mono_class_get which does the full resolution.
10876 Working around this semantics would require us to write a lot of code for no clear advantage.
10878 mono_image_append_class_to_reflection_info_set (klass);
10880 g_assert (mono_class_get_ref_info (klass) == tb);
10883 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10885 if (parent != NULL) {
10886 mono_class_setup_parent (klass, parent);
10887 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10888 const char *old_n = klass->name;
10889 /* trick to get relative numbering right when compiling corlib */
10890 klass->name = "BuildingObject";
10891 mono_class_setup_parent (klass, mono_defaults.object_class);
10892 klass->name = old_n;
10895 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10896 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10897 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10898 klass->instance_size = sizeof (MonoObject);
10899 klass->size_inited = 1;
10900 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10903 mono_class_setup_mono_type (klass);
10905 mono_class_setup_supertypes (klass);
10908 * FIXME: handle interfaces.
10911 tb->type.type = &klass->byval_arg;
10913 if (tb->nesting_type) {
10914 g_assert (tb->nesting_type->type);
10915 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10918 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10920 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10922 mono_loader_unlock ();
10926 mono_loader_unlock ();
10927 mono_error_raise_exception (&error);
10931 * mono_reflection_setup_generic_class:
10932 * @tb: a TypeBuilder object
10934 * Setup the generic class before adding the first generic parameter.
10937 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10942 * mono_reflection_create_generic_class:
10943 * @tb: a TypeBuilder object
10945 * Creates the generic class after all generic parameters have been added.
10948 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10953 klass = mono_class_from_mono_type (tb->type.type);
10955 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10957 if (klass->generic_container || (count == 0))
10960 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10962 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10964 klass->generic_container->owner.klass = klass;
10965 klass->generic_container->type_argc = count;
10966 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10968 klass->is_generic = 1;
10970 for (i = 0; i < count; i++) {
10971 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10972 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10973 klass->generic_container->type_params [i] = *param;
10974 /*Make sure we are a diferent type instance */
10975 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10976 klass->generic_container->type_params [i].info.pklass = NULL;
10977 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10979 g_assert (klass->generic_container->type_params [i].param.owner);
10982 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10986 * mono_reflection_create_internal_class:
10987 * @tb: a TypeBuilder object
10989 * Actually create the MonoClass that is associated with the TypeBuilder.
10992 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10996 klass = mono_class_from_mono_type (tb->type.type);
10998 mono_loader_lock ();
10999 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11000 MonoReflectionFieldBuilder *fb;
11002 MonoType *enum_basetype;
11004 g_assert (tb->fields != NULL);
11005 g_assert (mono_array_length (tb->fields) >= 1);
11007 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11009 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11010 mono_loader_unlock ();
11014 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11015 klass->element_class = mono_class_from_mono_type (enum_basetype);
11016 if (!klass->element_class)
11017 klass->element_class = mono_class_from_mono_type (enum_basetype);
11020 * get the element_class from the current corlib.
11022 ec = default_class_from_mono_type (enum_basetype);
11023 klass->instance_size = ec->instance_size;
11024 klass->size_inited = 1;
11026 * this is almost safe to do with enums and it's needed to be able
11027 * to create objects of the enum type (for use in SetConstant).
11029 /* FIXME: Does this mean enums can't have method overrides ? */
11030 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11032 mono_loader_unlock ();
11035 static MonoMarshalSpec*
11036 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11037 MonoReflectionMarshal *minfo)
11039 MonoMarshalSpec *res;
11041 res = image_g_new0 (image, MonoMarshalSpec, 1);
11042 res->native = (MonoMarshalNative)minfo->type;
11044 switch (minfo->type) {
11045 case MONO_NATIVE_LPARRAY:
11046 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11047 if (minfo->has_size) {
11048 res->data.array_data.param_num = minfo->param_num;
11049 res->data.array_data.num_elem = minfo->count;
11050 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11053 res->data.array_data.param_num = -1;
11054 res->data.array_data.num_elem = -1;
11055 res->data.array_data.elem_mult = -1;
11059 case MONO_NATIVE_BYVALTSTR:
11060 case MONO_NATIVE_BYVALARRAY:
11061 res->data.array_data.num_elem = minfo->count;
11064 case MONO_NATIVE_CUSTOM:
11065 if (minfo->marshaltyperef)
11066 res->data.custom_data.custom_name =
11067 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11068 if (minfo->mcookie)
11069 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11078 #endif /* !DISABLE_REFLECTION_EMIT */
11080 MonoReflectionMarshalAsAttribute*
11081 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11082 MonoMarshalSpec *spec, MonoError *error)
11084 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
11085 MonoReflectionType *rt;
11086 MonoReflectionMarshalAsAttribute *minfo;
11089 mono_error_init (error);
11091 if (!System_Reflection_Emit_MarshalAsAttribute) {
11092 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
11093 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
11094 g_assert (System_Reflection_Emit_MarshalAsAttribute);
11097 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, error);
11100 minfo->utype = spec->native;
11102 switch (minfo->utype) {
11103 case MONO_NATIVE_LPARRAY:
11104 minfo->array_subtype = spec->data.array_data.elem_type;
11105 minfo->size_const = spec->data.array_data.num_elem;
11106 if (spec->data.array_data.param_num != -1)
11107 minfo->size_param_index = spec->data.array_data.param_num;
11110 case MONO_NATIVE_BYVALTSTR:
11111 case MONO_NATIVE_BYVALARRAY:
11112 minfo->size_const = spec->data.array_data.num_elem;
11115 case MONO_NATIVE_CUSTOM:
11116 if (spec->data.custom_data.custom_name) {
11117 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11119 rt = mono_type_get_object_checked (domain, mtype, error);
11123 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11126 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11128 if (spec->data.custom_data.cookie)
11129 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11139 #ifndef DISABLE_REFLECTION_EMIT
11141 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11142 ReflectionMethodBuilder *rmb,
11143 MonoMethodSignature *sig)
11147 MonoMethodWrapper *wrapperm;
11148 MonoMarshalSpec **specs;
11149 MonoReflectionMethodAux *method_aux;
11154 mono_error_init (&error);
11156 * Methods created using a MethodBuilder should have their memory allocated
11157 * inside the image mempool, while dynamic methods should have their memory
11160 dynamic = rmb->refs != NULL;
11161 image = dynamic ? NULL : klass->image;
11164 g_assert (!klass->generic_class);
11166 mono_loader_lock ();
11168 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11169 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11170 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11172 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11174 wrapperm = (MonoMethodWrapper*)m;
11176 m->dynamic = dynamic;
11178 m->flags = rmb->attrs;
11179 m->iflags = rmb->iattrs;
11180 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11182 m->signature = sig;
11183 m->sre_method = TRUE;
11184 m->skip_visibility = rmb->skip_visibility;
11185 if (rmb->table_idx)
11186 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11188 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11189 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11190 m->string_ctor = 1;
11192 m->signature->pinvoke = 1;
11193 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11194 m->signature->pinvoke = 1;
11196 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11198 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11199 g_assert (mono_error_ok (&error));
11200 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11201 g_assert (mono_error_ok (&error));
11203 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11205 if (image_is_dynamic (klass->image))
11206 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11208 mono_loader_unlock ();
11211 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11212 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11213 MonoMethodHeader *header;
11215 gint32 max_stack, i;
11216 gint32 num_locals = 0;
11217 gint32 num_clauses = 0;
11221 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11222 code_size = rmb->ilgen->code_len;
11223 max_stack = rmb->ilgen->max_stack;
11224 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11225 if (rmb->ilgen->ex_handlers)
11226 num_clauses = method_count_clauses (rmb->ilgen);
11229 code = mono_array_addr (rmb->code, guint8, 0);
11230 code_size = mono_array_length (rmb->code);
11231 /* we probably need to run a verifier on the code... */
11241 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11242 header->code_size = code_size;
11243 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11244 memcpy ((char*)header->code, code, code_size);
11245 header->max_stack = max_stack;
11246 header->init_locals = rmb->init_locals;
11247 header->num_locals = num_locals;
11249 for (i = 0; i < num_locals; ++i) {
11250 MonoReflectionLocalBuilder *lb =
11251 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11253 header->locals [i] = image_g_new0 (image, MonoType, 1);
11254 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11257 header->num_clauses = num_clauses;
11259 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11260 rmb->ilgen, num_clauses);
11263 wrapperm->header = header;
11266 if (rmb->generic_params) {
11267 int count = mono_array_length (rmb->generic_params);
11268 MonoGenericContainer *container = rmb->generic_container;
11270 g_assert (container);
11272 container->type_argc = count;
11273 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11274 container->owner.method = m;
11275 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11277 m->is_generic = TRUE;
11278 mono_method_set_generic_container (m, container);
11280 for (i = 0; i < count; i++) {
11281 MonoReflectionGenericParam *gp =
11282 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11283 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11284 container->type_params [i] = *param;
11288 * The method signature might have pointers to generic parameters that belong to other methods.
11289 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11290 * generic parameters.
11292 for (i = 0; i < m->signature->param_count; ++i) {
11293 MonoType *t = m->signature->params [i];
11294 if (t->type == MONO_TYPE_MVAR) {
11295 MonoGenericParam *gparam = t->data.generic_param;
11296 if (gparam->num < count) {
11297 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11298 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11304 if (klass->generic_container) {
11305 container->parent = klass->generic_container;
11306 container->context.class_inst = klass->generic_container->context.class_inst;
11308 container->context.method_inst = mono_get_shared_generic_inst (container);
11312 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11316 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11318 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11319 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11320 for (i = 0; i < rmb->nrefs; ++i)
11321 data [i + 1] = rmb->refs [i];
11326 /* Parameter info */
11329 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11330 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11331 for (i = 0; i <= m->signature->param_count; ++i) {
11332 MonoReflectionParamBuilder *pb;
11333 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11334 if ((i > 0) && (pb->attrs)) {
11335 /* Make a copy since it might point to a shared type structure */
11336 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11337 m->signature->params [i - 1]->attrs = pb->attrs;
11340 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11341 MonoDynamicImage *assembly;
11343 MonoTypeEnum def_type;
11347 if (!method_aux->param_defaults) {
11348 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11349 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11351 assembly = (MonoDynamicImage*)klass->image;
11352 idx = encode_constant (assembly, pb->def_value, &def_type);
11353 /* Copy the data from the blob since it might get realloc-ed */
11354 p = assembly->blob.data + idx;
11355 len = mono_metadata_decode_blob_size (p, &p2);
11357 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11358 method_aux->param_default_types [i] = def_type;
11359 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11363 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11364 g_assert (mono_error_ok (&error));
11367 if (!method_aux->param_cattr)
11368 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11369 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11375 /* Parameter marshalling */
11378 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11379 MonoReflectionParamBuilder *pb;
11380 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11381 if (pb->marshal_info) {
11383 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11384 specs [pb->position] =
11385 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11389 if (specs != NULL) {
11391 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11392 method_aux->param_marshall = specs;
11395 if (image_is_dynamic (klass->image) && method_aux)
11396 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11398 mono_loader_unlock ();
11404 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11406 ReflectionMethodBuilder rmb;
11407 MonoMethodSignature *sig;
11409 mono_loader_lock ();
11410 sig = ctor_builder_to_signature (klass->image, mb);
11411 mono_loader_unlock ();
11413 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11416 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11417 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11419 /* If we are in a generic class, we might be called multiple times from inflate_method */
11420 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11421 /* ilgen is no longer needed */
11425 return mb->mhandle;
11429 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11431 ReflectionMethodBuilder rmb;
11432 MonoMethodSignature *sig;
11434 mono_error_init (error);
11436 mono_loader_lock ();
11437 sig = method_builder_to_signature (klass->image, mb);
11438 mono_loader_unlock ();
11440 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11443 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11444 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11446 /* If we are in a generic class, we might be called multiple times from inflate_method */
11447 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11448 /* ilgen is no longer needed */
11451 return mb->mhandle;
11454 static MonoClassField*
11455 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11457 MonoClassField *field;
11461 field = g_new0 (MonoClassField, 1);
11463 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11464 g_assert (mono_error_ok (&error));
11465 if (fb->attrs || fb->modreq || fb->modopt) {
11466 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11467 field->type->attrs = fb->attrs;
11469 g_assert (image_is_dynamic (klass->image));
11470 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11471 g_free (field->type);
11472 field->type = mono_metadata_type_dup (klass->image, custom);
11475 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11477 if (fb->offset != -1)
11478 field->offset = fb->offset;
11479 field->parent = klass;
11480 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11482 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11489 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11492 MonoReflectionTypeBuilder *tb = NULL;
11493 gboolean is_dynamic = FALSE;
11494 MonoClass *geninst;
11496 mono_loader_lock ();
11498 if (is_sre_type_builder (mono_object_class (type))) {
11499 tb = (MonoReflectionTypeBuilder *) type;
11502 } else if (is_sre_generic_instance (mono_object_class (type))) {
11503 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11504 MonoReflectionType *gtd = rgi->generic_type;
11506 if (is_sre_type_builder (mono_object_class (gtd))) {
11507 tb = (MonoReflectionTypeBuilder *)gtd;
11512 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11513 if (tb && tb->generic_container)
11514 mono_reflection_create_generic_class (tb);
11516 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11517 if (!klass->generic_container) {
11518 mono_loader_unlock ();
11522 if (klass->wastypebuilder) {
11523 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11528 mono_loader_unlock ();
11530 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11532 return &geninst->byval_arg;
11536 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11538 MonoGenericClass *gclass;
11539 MonoGenericInst *inst;
11541 g_assert (klass->generic_container);
11543 inst = mono_metadata_get_generic_inst (type_argc, types);
11544 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11546 return mono_generic_class_get_class (gclass);
11549 MonoReflectionMethod*
11550 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11554 MonoMethod *method, *inflated;
11555 MonoMethodInflated *imethod;
11556 MonoGenericContext tmp_context;
11557 MonoGenericInst *ginst;
11558 MonoType **type_argv;
11561 /*FIXME but this no longer should happen*/
11562 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11563 #ifndef DISABLE_REFLECTION_EMIT
11564 MonoReflectionMethodBuilder *mb = NULL;
11565 MonoReflectionTypeBuilder *tb;
11568 mb = (MonoReflectionMethodBuilder *) rmethod;
11569 tb = (MonoReflectionTypeBuilder *) mb->type;
11570 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11572 method = methodbuilder_to_mono_method (klass, mb, &error);
11574 mono_error_raise_exception (&error); /* FIXME don't raise here */
11576 g_assert_not_reached ();
11580 method = rmethod->method;
11583 klass = method->klass;
11585 if (method->is_inflated)
11586 method = ((MonoMethodInflated *) method)->declaring;
11588 count = mono_method_signature (method)->generic_param_count;
11589 if (count != mono_array_length (types))
11592 type_argv = g_new0 (MonoType *, count);
11593 for (i = 0; i < count; i++) {
11594 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11595 type_argv [i] = mono_reflection_type_get_handle (garg);
11597 ginst = mono_metadata_get_generic_inst (count, type_argv);
11598 g_free (type_argv);
11600 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11601 tmp_context.method_inst = ginst;
11603 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11604 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11605 imethod = (MonoMethodInflated *) inflated;
11607 /*FIXME but I think this is no longer necessary*/
11608 if (image_is_dynamic (method->klass->image)) {
11609 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11611 * This table maps metadata structures representing inflated methods/fields
11612 * to the reflection objects representing their generic definitions.
11614 mono_image_lock ((MonoImage*)image);
11615 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11616 mono_image_unlock ((MonoImage*)image);
11619 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11620 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11622 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11623 mono_error_raise_exception (&error); /* FIXME don't raise here */
11627 #ifndef DISABLE_REFLECTION_EMIT
11629 static MonoMethod *
11630 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11632 MonoMethodInflated *imethod;
11633 MonoGenericContext *context;
11637 * With generic code sharing the klass might not be inflated.
11638 * This can happen because classes inflated with their own
11639 * type arguments are "normalized" to the uninflated class.
11641 if (!klass->generic_class)
11644 context = mono_class_get_context (klass);
11646 if (klass->method.count && klass->methods) {
11647 /* Find the already created inflated method */
11648 for (i = 0; i < klass->method.count; ++i) {
11649 g_assert (klass->methods [i]->is_inflated);
11650 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11653 g_assert (i < klass->method.count);
11654 imethod = (MonoMethodInflated*)klass->methods [i];
11657 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11658 mono_error_assert_ok (&error);
11661 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11662 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11664 mono_image_lock ((MonoImage*)image);
11665 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11666 mono_image_unlock ((MonoImage*)image);
11668 return (MonoMethod *) imethod;
11671 static MonoMethod *
11672 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11674 MonoMethod *method;
11677 mono_error_init (error);
11679 MonoClass *type_class = mono_object_class (type);
11681 if (is_sre_generic_instance (type_class)) {
11682 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11683 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11684 } else if (is_sre_type_builder (type_class)) {
11685 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11686 } else if (type->type) {
11687 gklass = mono_class_from_mono_type (type->type);
11688 gklass = mono_class_get_generic_type_definition (gklass);
11690 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11693 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11694 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11695 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11697 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11701 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11702 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11705 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11706 method = ((MonoReflectionMethod *) obj)->method;
11708 method = NULL; /* prevent compiler warning */
11709 g_error ("can't handle type %s", obj->vtable->klass->name);
11712 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11715 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11717 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11719 MonoGenericClass *gclass;
11720 MonoDynamicGenericClass *dgclass;
11721 MonoClass *klass, *gklass;
11725 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11726 klass = mono_class_from_mono_type (gtype);
11727 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11728 gclass = gtype->data.generic_class;
11730 if (!gclass->is_dynamic)
11733 dgclass = (MonoDynamicGenericClass *) gclass;
11735 if (dgclass->initialized)
11738 gklass = gclass->container_class;
11739 mono_class_init (gklass);
11741 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11743 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11744 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11745 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11747 for (i = 0; i < dgclass->count_fields; i++) {
11748 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11749 MonoClassField *field, *inflated_field = NULL;
11751 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11752 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11753 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11754 field = ((MonoReflectionField *) obj)->field;
11756 field = NULL; /* prevent compiler warning */
11757 g_assert_not_reached ();
11760 dgclass->fields [i] = *field;
11761 dgclass->fields [i].parent = klass;
11762 dgclass->fields [i].type = mono_class_inflate_generic_type (
11763 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11764 dgclass->field_generic_types [i] = field->type;
11765 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11766 dgclass->field_objects [i] = obj;
11768 if (inflated_field) {
11769 g_free (inflated_field);
11771 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11775 dgclass->initialized = TRUE;
11779 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11781 MonoDynamicGenericClass *dgclass;
11784 g_assert (gclass->is_dynamic);
11786 dgclass = (MonoDynamicGenericClass *)gclass;
11788 for (i = 0; i < dgclass->count_fields; ++i) {
11789 MonoClassField *field = dgclass->fields + i;
11790 mono_metadata_free_type (field->type);
11791 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11796 fix_partial_generic_class (MonoClass *klass)
11798 MonoClass *gklass = klass->generic_class->container_class;
11799 MonoDynamicGenericClass *dgclass;
11802 if (klass->wastypebuilder)
11805 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11806 if (klass->parent != gklass->parent) {
11808 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11809 if (mono_error_ok (&error)) {
11810 MonoClass *parent = mono_class_from_mono_type (parent_type);
11811 mono_metadata_free_type (parent_type);
11812 if (parent != klass->parent) {
11813 /*fool mono_class_setup_parent*/
11814 klass->supertypes = NULL;
11815 mono_class_setup_parent (klass, parent);
11818 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11819 mono_error_cleanup (&error);
11820 if (gklass->wastypebuilder)
11821 klass->wastypebuilder = TRUE;
11826 if (!dgclass->initialized)
11829 if (klass->method.count != gklass->method.count) {
11830 klass->method.count = gklass->method.count;
11831 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11833 for (i = 0; i < klass->method.count; i++) {
11835 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11836 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11837 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11841 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11842 klass->interface_count = gklass->interface_count;
11843 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11844 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11846 for (i = 0; i < gklass->interface_count; ++i) {
11848 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11849 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11850 mono_metadata_free_type (iface_type);
11852 ensure_runtime_vtable (klass->interfaces [i], &error);
11853 mono_error_raise_exception (&error); /* FIXME don't raise here */
11855 klass->interfaces_inited = 1;
11858 if (klass->field.count != gklass->field.count) {
11859 klass->field.count = gklass->field.count;
11860 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11862 for (i = 0; i < klass->field.count; i++) {
11863 klass->fields [i] = gklass->fields [i];
11864 klass->fields [i].parent = klass;
11865 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11869 /*We can only finish with this klass once it's parent has as well*/
11870 if (gklass->wastypebuilder)
11871 klass->wastypebuilder = TRUE;
11876 * ensure_generic_class_runtime_vtable:
11877 * @klass a generic class
11878 * @error set on error
11880 * Ensures that the generic container of @klass has a vtable and
11881 * returns TRUE on success. On error returns FALSE and sets @error.
11884 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
11886 MonoClass *gklass = klass->generic_class->container_class;
11888 mono_error_init (error);
11890 if (!ensure_runtime_vtable (gklass, error))
11893 fix_partial_generic_class (klass);
11899 * ensure_runtime_vtable:
11901 * @error set on error
11903 * Ensures that @klass has a vtable and returns TRUE on success. On
11904 * error returns FALSE and sets @error.
11907 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
11909 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11912 mono_error_init (error);
11914 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11917 if (!ensure_runtime_vtable (klass->parent, error))
11921 num = tb->ctors? mono_array_length (tb->ctors): 0;
11922 num += tb->num_methods;
11923 klass->method.count = num;
11924 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11925 num = tb->ctors? mono_array_length (tb->ctors): 0;
11926 for (i = 0; i < num; ++i) {
11927 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
11930 klass->methods [i] = ctor;
11932 num = tb->num_methods;
11934 for (i = 0; i < num; ++i) {
11935 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
11938 klass->methods [j++] = meth;
11941 if (tb->interfaces) {
11942 klass->interface_count = mono_array_length (tb->interfaces);
11943 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11944 for (i = 0; i < klass->interface_count; ++i) {
11945 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11946 klass->interfaces [i] = mono_class_from_mono_type (iface);
11947 if (!ensure_runtime_vtable (klass->interfaces [i], error))
11950 klass->interfaces_inited = 1;
11952 } else if (klass->generic_class){
11953 if (!ensure_generic_class_runtime_vtable (klass, error))
11957 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11959 for (i = 0; i < klass->method.count; ++i) {
11960 MonoMethod *im = klass->methods [i];
11961 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11962 im->slot = slot_num++;
11965 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11966 mono_class_setup_interface_offsets (klass);
11967 mono_class_setup_interface_id (klass);
11971 * The generic vtable is needed even if image->run is not set since some
11972 * runtime code like ves_icall_Type_GetMethodsByName depends on
11973 * method->slot being defined.
11977 * tb->methods could not be freed since it is used for determining
11978 * overrides during dynamic vtable construction.
11985 mono_reflection_method_get_handle (MonoObject *method)
11987 MonoClass *klass = mono_object_class (method);
11988 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11989 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11990 return sr_method->method;
11992 if (is_sre_method_builder (klass)) {
11993 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11994 return mb->mhandle;
11996 if (is_sre_method_on_tb_inst (klass)) {
11997 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11998 MonoMethod *result;
11999 /*FIXME move this to a proper method and unify with resolve_object*/
12000 if (m->method_args) {
12001 result = mono_reflection_method_on_tb_inst_get_handle (m);
12003 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12004 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12005 MonoMethod *mono_method;
12007 if (is_sre_method_builder (mono_object_class (m->mb)))
12008 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12009 else if (is_sr_mono_method (mono_object_class (m->mb)))
12010 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12012 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)));
12014 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12019 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12024 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12026 MonoReflectionTypeBuilder *tb;
12028 MonoReflectionMethod *m;
12031 *num_overrides = 0;
12033 g_assert (image_is_dynamic (klass->image));
12035 if (!mono_class_get_ref_info (klass))
12038 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12040 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12044 for (i = 0; i < tb->num_methods; ++i) {
12045 MonoReflectionMethodBuilder *mb =
12046 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12047 if (mb->override_methods)
12048 onum += mono_array_length (mb->override_methods);
12053 *overrides = g_new0 (MonoMethod*, onum * 2);
12056 for (i = 0; i < tb->num_methods; ++i) {
12057 MonoReflectionMethodBuilder *mb =
12058 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12059 if (mb->override_methods) {
12060 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12061 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12063 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12064 (*overrides) [onum * 2 + 1] = mb->mhandle;
12066 g_assert (mb->mhandle);
12074 *num_overrides = onum;
12078 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12080 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12081 MonoReflectionFieldBuilder *fb;
12082 MonoClassField *field;
12083 MonoImage *image = klass->image;
12084 const char *p, *p2;
12086 guint32 len, idx, real_size = 0;
12088 klass->field.count = tb->num_fields;
12089 klass->field.first = 0;
12091 mono_error_init (error);
12093 if (tb->class_size) {
12094 if ((tb->packing_size & 0xffffff00) != 0) {
12095 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12096 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12099 klass->packing_size = tb->packing_size;
12100 real_size = klass->instance_size + tb->class_size;
12103 if (!klass->field.count) {
12104 klass->instance_size = MAX (klass->instance_size, real_size);
12108 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12109 mono_class_alloc_ext (klass);
12110 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12112 This is, guess what, a hack.
12113 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12114 On the static path no field class is resolved, only types are built. This is the right thing to do
12116 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12118 klass->size_inited = 1;
12120 for (i = 0; i < klass->field.count; ++i) {
12121 MonoArray *rva_data;
12122 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12123 field = &klass->fields [i];
12124 field->name = mono_string_to_utf8_image (image, fb->name, error);
12125 if (!mono_error_ok (error))
12128 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12129 field->type->attrs = fb->attrs;
12131 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12134 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12135 char *base = mono_array_addr (rva_data, char, 0);
12136 size_t size = mono_array_length (rva_data);
12137 char *data = (char *)mono_image_alloc (klass->image, size);
12138 memcpy (data, base, size);
12139 klass->ext->field_def_values [i].data = data;
12141 if (fb->offset != -1)
12142 field->offset = fb->offset;
12143 field->parent = klass;
12144 fb->handle = field;
12145 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12147 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12148 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12150 if (fb->def_value) {
12151 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12152 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12153 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12154 /* Copy the data from the blob since it might get realloc-ed */
12155 p = assembly->blob.data + idx;
12156 len = mono_metadata_decode_blob_size (p, &p2);
12158 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12159 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12163 klass->instance_size = MAX (klass->instance_size, real_size);
12164 mono_class_layout_fields (klass);
12168 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12170 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12171 MonoReflectionPropertyBuilder *pb;
12172 MonoImage *image = klass->image;
12173 MonoProperty *properties;
12176 mono_error_init (error);
12179 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12181 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12182 klass->ext->property.first = 0;
12184 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12185 klass->ext->properties = properties;
12186 for (i = 0; i < klass->ext->property.count; ++i) {
12187 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12188 properties [i].parent = klass;
12189 properties [i].attrs = pb->attrs;
12190 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12191 if (!mono_error_ok (error))
12193 if (pb->get_method)
12194 properties [i].get = pb->get_method->mhandle;
12195 if (pb->set_method)
12196 properties [i].set = pb->set_method->mhandle;
12198 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12199 if (pb->def_value) {
12201 const char *p, *p2;
12202 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12203 if (!klass->ext->prop_def_values)
12204 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12205 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12206 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12207 /* Copy the data from the blob since it might get realloc-ed */
12208 p = assembly->blob.data + idx;
12209 len = mono_metadata_decode_blob_size (p, &p2);
12211 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12212 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12217 MonoReflectionEvent *
12218 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12221 MonoEvent *event = g_new0 (MonoEvent, 1);
12224 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12226 event->parent = klass;
12227 event->attrs = eb->attrs;
12228 event->name = mono_string_to_utf8 (eb->name);
12229 if (eb->add_method)
12230 event->add = eb->add_method->mhandle;
12231 if (eb->remove_method)
12232 event->remove = eb->remove_method->mhandle;
12233 if (eb->raise_method)
12234 event->raise = eb->raise_method->mhandle;
12236 #ifndef MONO_SMALL_CONFIG
12237 if (eb->other_methods) {
12239 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12240 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12241 MonoReflectionMethodBuilder *mb =
12242 mono_array_get (eb->other_methods,
12243 MonoReflectionMethodBuilder*, j);
12244 event->other [j] = mb->mhandle;
12249 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12250 mono_error_raise_exception (&error); /* FIXME don't raise here */
12255 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12257 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12258 MonoReflectionEventBuilder *eb;
12259 MonoImage *image = klass->image;
12263 mono_error_init (error);
12266 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12268 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12269 klass->ext->event.first = 0;
12271 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12272 klass->ext->events = events;
12273 for (i = 0; i < klass->ext->event.count; ++i) {
12274 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12275 events [i].parent = klass;
12276 events [i].attrs = eb->attrs;
12277 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12278 if (!mono_error_ok (error))
12280 if (eb->add_method)
12281 events [i].add = eb->add_method->mhandle;
12282 if (eb->remove_method)
12283 events [i].remove = eb->remove_method->mhandle;
12284 if (eb->raise_method)
12285 events [i].raise = eb->raise_method->mhandle;
12287 #ifndef MONO_SMALL_CONFIG
12288 if (eb->other_methods) {
12290 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12291 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12292 MonoReflectionMethodBuilder *mb =
12293 mono_array_get (eb->other_methods,
12294 MonoReflectionMethodBuilder*, j);
12295 events [i].other [j] = mb->mhandle;
12299 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12304 remove_instantiations_of_and_ensure_contents (gpointer key,
12306 gpointer user_data)
12308 MonoType *type = (MonoType*)key;
12309 MonoClass *klass = (MonoClass*)user_data;
12311 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12312 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12319 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12321 mono_error_init (error);
12327 for (i = 0; i < mono_array_length (arr); ++i) {
12328 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12329 if (!mono_error_ok (error))
12334 MonoReflectionType*
12335 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12339 MonoDomain* domain;
12340 MonoReflectionType* res;
12343 domain = mono_object_domain (tb);
12344 klass = mono_class_from_mono_type (tb->type.type);
12347 * Check for user defined Type subclasses.
12349 RESOLVE_TYPE (tb->parent, &error);
12350 mono_error_raise_exception (&error); /* FIXME don't raise here */
12351 check_array_for_usertypes (tb->interfaces, &error);
12352 mono_error_raise_exception (&error); /*FIXME don't raise here */
12354 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12355 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12357 RESOLVE_TYPE (fb->type, &error);
12358 mono_error_raise_exception (&error); /* FIXME don't raise here */
12359 check_array_for_usertypes (fb->modreq, &error);
12360 mono_error_raise_exception (&error); /*FIXME don't raise here */
12361 check_array_for_usertypes (fb->modopt, &error);
12362 mono_error_raise_exception (&error); /*FIXME don't raise here */
12363 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12364 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12365 mono_error_raise_exception (&error); /* FIXME don't raise here */
12371 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12372 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12374 RESOLVE_TYPE (mb->rtype, &error);
12375 mono_error_raise_exception (&error); /* FIXME don't raise here */
12376 check_array_for_usertypes (mb->return_modreq, &error);
12377 mono_error_raise_exception (&error); /*FIXME don't raise here */
12378 check_array_for_usertypes (mb->return_modopt, &error);
12379 mono_error_raise_exception (&error); /*FIXME don't raise here */
12380 check_array_for_usertypes (mb->parameters, &error);
12381 mono_error_raise_exception (&error); /*FIXME don't raise here */
12382 if (mb->param_modreq)
12383 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12384 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12385 mono_error_raise_exception (&error); /*FIXME don't raise here */
12387 if (mb->param_modopt)
12388 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12389 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12390 mono_error_raise_exception (&error); /*FIXME don't raise here */
12396 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12397 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12399 check_array_for_usertypes (mb->parameters, &error);
12400 mono_error_raise_exception (&error); /*FIXME don't raise here */
12401 if (mb->param_modreq)
12402 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12403 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12404 mono_error_raise_exception (&error); /*FIXME don't raise here */
12406 if (mb->param_modopt)
12407 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12408 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12409 mono_error_raise_exception (&error); /*FIXME don't raise here */
12415 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12418 * we need to lock the domain because the lock will be taken inside
12419 * So, we need to keep the locking order correct.
12421 mono_loader_lock ();
12422 mono_domain_lock (domain);
12423 if (klass->wastypebuilder) {
12424 mono_domain_unlock (domain);
12425 mono_loader_unlock ();
12427 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12428 mono_error_raise_exception (&error); /* FIXME don't raise here */
12433 * Fields to set in klass:
12434 * the various flags: delegate/unicode/contextbound etc.
12436 klass->flags = tb->attrs;
12437 klass->has_cctor = 1;
12438 klass->has_finalize = 1;
12439 klass->has_finalize_inited = 1;
12441 mono_class_setup_parent (klass, klass->parent);
12442 /* fool mono_class_setup_supertypes */
12443 klass->supertypes = NULL;
12444 mono_class_setup_supertypes (klass);
12445 mono_class_setup_mono_type (klass);
12448 if (!((MonoDynamicImage*)klass->image)->run) {
12449 if (klass->generic_container) {
12450 /* FIXME: The code below can't handle generic classes */
12451 klass->wastypebuilder = TRUE;
12452 mono_loader_unlock ();
12453 mono_domain_unlock (domain);
12455 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12456 mono_error_raise_exception (&error); /* FIXME don't raise here */
12463 /* enums are done right away */
12464 if (!klass->enumtype)
12465 if (!ensure_runtime_vtable (klass, &error))
12468 if (tb->subtypes) {
12469 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12470 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12471 mono_class_alloc_ext (klass);
12472 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)));
12476 klass->nested_classes_inited = TRUE;
12478 /* fields and object layout */
12479 if (klass->parent) {
12480 if (!klass->parent->size_inited)
12481 mono_class_init (klass->parent);
12482 klass->instance_size = klass->parent->instance_size;
12483 klass->sizes.class_size = 0;
12484 klass->min_align = klass->parent->min_align;
12485 /* if the type has no fields we won't call the field_setup
12486 * routine which sets up klass->has_references.
12488 klass->has_references |= klass->parent->has_references;
12490 klass->instance_size = sizeof (MonoObject);
12491 klass->min_align = 1;
12494 /* FIXME: handle packing_size and instance_size */
12495 typebuilder_setup_fields (klass, &error);
12496 if (!mono_error_ok (&error))
12498 typebuilder_setup_properties (klass, &error);
12499 if (!mono_error_ok (&error))
12502 typebuilder_setup_events (klass, &error);
12503 if (!mono_error_ok (&error))
12506 klass->wastypebuilder = TRUE;
12509 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12510 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12511 * we want to return normal System.MonoType objects, so clear these out from the cache.
12513 * Together with this we must ensure the contents of all instances to match the created type.
12515 if (domain->type_hash && klass->generic_container)
12516 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12518 mono_domain_unlock (domain);
12519 mono_loader_unlock ();
12521 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12522 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12523 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12526 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12527 mono_error_raise_exception (&error); /* FIXME don't raise here */
12529 g_assert (res != (MonoReflectionType*)tb);
12534 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12535 klass->wastypebuilder = TRUE;
12536 mono_domain_unlock (domain);
12537 mono_loader_unlock ();
12538 mono_error_raise_exception (&error);
12543 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12545 MonoGenericParamFull *param;
12550 image = &gparam->tbuilder->module->dynamic_image->image;
12552 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12554 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12555 g_assert (mono_error_ok (&error));
12556 param->param.num = gparam->index;
12558 if (gparam->mbuilder) {
12559 if (!gparam->mbuilder->generic_container) {
12560 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12561 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12562 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12563 gparam->mbuilder->generic_container->is_method = TRUE;
12565 * Cannot set owner.method, since the MonoMethod is not created yet.
12566 * Set the image field instead, so type_in_image () works.
12568 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12569 gparam->mbuilder->generic_container->owner.image = klass->image;
12571 param->param.owner = gparam->mbuilder->generic_container;
12572 } else if (gparam->tbuilder) {
12573 if (!gparam->tbuilder->generic_container) {
12574 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12575 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12576 gparam->tbuilder->generic_container->owner.klass = klass;
12578 param->param.owner = gparam->tbuilder->generic_container;
12581 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12583 gparam->type.type = &pklass->byval_arg;
12585 mono_class_set_ref_info (pklass, gparam);
12586 mono_image_append_class_to_reflection_info_set (pklass);
12590 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12593 MonoReflectionModuleBuilder *module = sig->module;
12594 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12595 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12600 check_array_for_usertypes (sig->arguments, &error);
12601 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12603 sigbuffer_init (&buf, 32);
12605 sigbuffer_add_value (&buf, 0x07);
12606 sigbuffer_add_value (&buf, na);
12607 if (assembly != NULL){
12608 for (i = 0; i < na; ++i) {
12609 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12610 encode_reflection_type (assembly, type, &buf);
12614 buflen = buf.p - buf.buf;
12615 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12616 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12617 sigbuffer_free (&buf);
12623 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12626 MonoDynamicImage *assembly = sig->module->dynamic_image;
12627 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12632 check_array_for_usertypes (sig->arguments, &error);
12633 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12635 sigbuffer_init (&buf, 32);
12637 sigbuffer_add_value (&buf, 0x06);
12638 for (i = 0; i < na; ++i) {
12639 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12640 encode_reflection_type (assembly, type, &buf);
12643 buflen = buf.p - buf.buf;
12644 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12645 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12646 sigbuffer_free (&buf);
12652 MonoMethod *handle;
12653 MonoDomain *domain;
12654 } DynamicMethodReleaseData;
12657 * The runtime automatically clean up those after finalization.
12659 static MonoReferenceQueue *dynamic_method_queue;
12662 free_dynamic_method (void *dynamic_method)
12664 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12665 MonoDomain *domain = data->domain;
12666 MonoMethod *method = data->handle;
12669 mono_domain_lock (domain);
12670 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12671 g_hash_table_remove (domain->method_to_dyn_method, method);
12672 mono_domain_unlock (domain);
12673 g_assert (dis_link);
12674 mono_gchandle_free (dis_link);
12676 mono_runtime_free_method (domain, method);
12681 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12683 MonoReferenceQueue *queue;
12684 MonoMethod *handle;
12685 DynamicMethodReleaseData *release_data;
12686 ReflectionMethodBuilder rmb;
12687 MonoMethodSignature *sig;
12689 MonoDomain *domain;
12693 if (mono_runtime_is_shutting_down ())
12694 mono_raise_exception (mono_get_exception_invalid_operation (""));
12696 if (!(queue = dynamic_method_queue)) {
12697 mono_loader_lock ();
12698 if (!(queue = dynamic_method_queue))
12699 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12700 mono_loader_unlock ();
12703 sig = dynamic_method_to_signature (mb);
12705 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12708 * Resolve references.
12711 * Every second entry in the refs array is reserved for storing handle_class,
12712 * which is needed by the ldtoken implementation in the JIT.
12714 rmb.nrefs = mb->nrefs;
12715 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12716 for (i = 0; i < mb->nrefs; i += 2) {
12717 MonoClass *handle_class;
12719 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12721 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12722 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12724 * The referenced DynamicMethod should already be created by the managed
12725 * code, except in the case of circular references. In that case, we store
12726 * method in the refs array, and fix it up later when the referenced
12727 * DynamicMethod is created.
12729 if (method->mhandle) {
12730 ref = method->mhandle;
12732 /* FIXME: GC object stored in unmanaged memory */
12735 /* FIXME: GC object stored in unmanaged memory */
12736 method->referenced_by = g_slist_append (method->referenced_by, mb);
12738 handle_class = mono_defaults.methodhandle_class;
12740 MonoException *ex = NULL;
12741 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12743 ex = mono_get_exception_type_load (NULL, NULL);
12744 else if (mono_security_core_clr_enabled ())
12745 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12749 mono_raise_exception (ex);
12754 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12755 rmb.refs [i + 1] = handle_class;
12758 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12760 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12761 release_data = g_new (DynamicMethodReleaseData, 1);
12762 release_data->handle = handle;
12763 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12764 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12765 g_free (release_data);
12767 /* Fix up refs entries pointing at us */
12768 for (l = mb->referenced_by; l; l = l->next) {
12769 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12770 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12773 g_assert (method->mhandle);
12775 data = (gpointer*)wrapper->method_data;
12776 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12777 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12778 data [i + 1] = mb->mhandle;
12781 g_slist_free (mb->referenced_by);
12785 /* ilgen is no longer needed */
12788 domain = mono_domain_get ();
12789 mono_domain_lock (domain);
12790 if (!domain->method_to_dyn_method)
12791 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12792 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12793 mono_domain_unlock (domain);
12796 #endif /* DISABLE_REFLECTION_EMIT */
12800 * mono_reflection_is_valid_dynamic_token:
12802 * Returns TRUE if token is valid.
12806 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12808 return lookup_dyn_token (image, token) != NULL;
12811 MonoMethodSignature *
12812 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12814 MonoMethodSignature *sig;
12815 g_assert (image_is_dynamic (image));
12817 mono_error_init (error);
12819 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12823 return mono_method_signature_checked (method, error);
12826 #ifndef DISABLE_REFLECTION_EMIT
12829 * mono_reflection_lookup_dynamic_token:
12831 * Finish the Builder object pointed to by TOKEN and return the corresponding
12832 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12833 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12836 * LOCKING: Take the loader lock
12839 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12841 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12845 obj = lookup_dyn_token (assembly, token);
12848 g_error ("Could not find required dynamic token 0x%08x", token);
12854 handle_class = &klass;
12855 return resolve_object (image, obj, handle_class, context);
12859 * ensure_complete_type:
12861 * Ensure that KLASS is completed if it is a dynamic type, or references
12865 ensure_complete_type (MonoClass *klass)
12867 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12870 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12872 // Asserting here could break a lot of code
12873 //g_assert (klass->wastypebuilder);
12876 if (klass->generic_class) {
12877 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12880 for (i = 0; i < inst->type_argc; ++i) {
12881 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12887 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12889 gpointer result = NULL;
12891 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12892 result = mono_string_intern ((MonoString*)obj);
12893 *handle_class = mono_defaults.string_class;
12895 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12896 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12897 MonoClass *mc = mono_class_from_mono_type (type);
12898 if (!mono_class_init (mc))
12899 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12902 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12903 result = mono_class_from_mono_type (inflated);
12904 mono_metadata_free_type (inflated);
12906 result = mono_class_from_mono_type (type);
12908 *handle_class = mono_defaults.typehandle_class;
12910 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12911 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12912 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12913 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12914 result = ((MonoReflectionMethod*)obj)->method;
12917 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12918 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12920 *handle_class = mono_defaults.methodhandle_class;
12922 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12923 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12924 result = mb->mhandle;
12926 /* Type is not yet created */
12927 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12929 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12932 * Hopefully this has been filled in by calling CreateType() on the
12936 * TODO: This won't work if the application finishes another
12937 * TypeBuilder instance instead of this one.
12939 result = mb->mhandle;
12943 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12944 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12946 *handle_class = mono_defaults.methodhandle_class;
12947 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12948 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12950 result = cb->mhandle;
12952 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12954 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12955 result = cb->mhandle;
12959 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12960 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12962 *handle_class = mono_defaults.methodhandle_class;
12963 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12964 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12966 ensure_complete_type (field->parent);
12968 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12969 MonoClass *klass = mono_class_from_mono_type (inflated);
12970 MonoClassField *inflated_field;
12971 gpointer iter = NULL;
12972 mono_metadata_free_type (inflated);
12973 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12974 if (!strcmp (field->name, inflated_field->name))
12977 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12978 result = inflated_field;
12982 *handle_class = mono_defaults.fieldhandle_class;
12984 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12985 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12986 result = fb->handle;
12989 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12991 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12992 result = fb->handle;
12995 if (fb->handle && fb->handle->parent->generic_container) {
12996 MonoClass *klass = fb->handle->parent;
12997 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12998 MonoClass *inflated = mono_class_from_mono_type (type);
13000 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13002 mono_metadata_free_type (type);
13004 *handle_class = mono_defaults.fieldhandle_class;
13005 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13006 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13007 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
13010 klass = type->data.klass;
13011 if (klass->wastypebuilder) {
13012 /* Already created */
13016 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
13017 result = type->data.klass;
13020 *handle_class = mono_defaults.typehandle_class;
13021 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13022 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13023 MonoMethodSignature *sig;
13026 if (helper->arguments)
13027 nargs = mono_array_length (helper->arguments);
13031 sig = mono_metadata_signature_alloc (image, nargs);
13032 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13033 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13035 if (helper->unmanaged_call_conv) { /* unmanaged */
13036 sig->call_convention = helper->unmanaged_call_conv - 1;
13037 sig->pinvoke = TRUE;
13038 } else if (helper->call_conv & 0x02) {
13039 sig->call_convention = MONO_CALL_VARARG;
13041 sig->call_convention = MONO_CALL_DEFAULT;
13044 sig->param_count = nargs;
13045 /* TODO: Copy type ? */
13046 sig->ret = helper->return_type->type;
13047 for (i = 0; i < nargs; ++i)
13048 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13051 *handle_class = NULL;
13052 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13053 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13054 /* Already created by the managed code */
13055 g_assert (method->mhandle);
13056 result = method->mhandle;
13057 *handle_class = mono_defaults.methodhandle_class;
13058 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13059 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13060 type = mono_class_inflate_generic_type (type, context);
13061 result = mono_class_from_mono_type (type);
13062 *handle_class = mono_defaults.typehandle_class;
13064 mono_metadata_free_type (type);
13065 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13066 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13067 type = mono_class_inflate_generic_type (type, context);
13068 result = mono_class_from_mono_type (type);
13069 *handle_class = mono_defaults.typehandle_class;
13071 mono_metadata_free_type (type);
13072 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13073 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13074 MonoClass *inflated;
13076 MonoClassField *field;
13078 if (is_sre_field_builder (mono_object_class (f->fb)))
13079 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13080 else if (is_sr_mono_field (mono_object_class (f->fb)))
13081 field = ((MonoReflectionField*)f->fb)->field;
13083 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)));
13085 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13086 inflated = mono_class_from_mono_type (type);
13088 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13089 ensure_complete_type (field->parent);
13091 mono_metadata_free_type (type);
13092 *handle_class = mono_defaults.fieldhandle_class;
13093 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13094 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13095 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13096 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13097 MonoMethod *method;
13099 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13100 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13101 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13102 method = ((MonoReflectionMethod *)c->cb)->method;
13104 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)));
13106 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13107 *handle_class = mono_defaults.methodhandle_class;
13108 mono_metadata_free_type (type);
13109 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13110 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13111 if (m->method_args) {
13112 result = mono_reflection_method_on_tb_inst_get_handle (m);
13115 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13116 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13119 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13120 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13121 MonoMethod *method;
13123 if (is_sre_method_builder (mono_object_class (m->mb)))
13124 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13125 else if (is_sr_mono_method (mono_object_class (m->mb)))
13126 method = ((MonoReflectionMethod *)m->mb)->method;
13128 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)));
13130 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13131 mono_metadata_free_type (type);
13133 *handle_class = mono_defaults.methodhandle_class;
13134 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13135 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13138 MonoMethod *method;
13142 mtype = mono_reflection_type_get_handle (m->parent);
13143 klass = mono_class_from_mono_type (mtype);
13145 /* Find the method */
13147 name = mono_string_to_utf8 (m->name);
13149 while ((method = mono_class_get_methods (klass, &iter))) {
13150 if (!strcmp (method->name, name))
13157 // FIXME: Check parameters/return value etc. match
13160 *handle_class = mono_defaults.methodhandle_class;
13161 } else if (is_sre_array (mono_object_get_class(obj)) ||
13162 is_sre_byref (mono_object_get_class(obj)) ||
13163 is_sre_pointer (mono_object_get_class(obj))) {
13164 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13165 MonoType *type = mono_reflection_type_get_handle (ref_type);
13168 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13169 result = mono_class_from_mono_type (inflated);
13170 mono_metadata_free_type (inflated);
13172 result = mono_class_from_mono_type (type);
13174 *handle_class = mono_defaults.typehandle_class;
13176 g_print ("%s\n", obj->vtable->klass->name);
13177 g_assert_not_reached ();
13182 #else /* DISABLE_REFLECTION_EMIT */
13185 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13187 g_assert_not_reached ();
13192 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13194 g_assert_not_reached ();
13198 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13200 g_assert_not_reached ();
13204 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13206 g_assert_not_reached ();
13210 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13212 g_assert_not_reached ();
13216 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13218 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13222 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13224 g_assert_not_reached ();
13228 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13230 g_assert_not_reached ();
13233 MonoReflectionModule *
13234 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13236 g_assert_not_reached ();
13241 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13243 g_assert_not_reached ();
13248 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13250 g_assert_not_reached ();
13255 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13256 gboolean create_open_instance, gboolean register_token, MonoError *error)
13258 g_assert_not_reached ();
13263 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13268 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13270 g_assert_not_reached ();
13274 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13277 *num_overrides = 0;
13280 MonoReflectionEvent *
13281 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13283 g_assert_not_reached ();
13287 MonoReflectionType*
13288 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13290 g_assert_not_reached ();
13295 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13297 g_assert_not_reached ();
13301 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13303 g_assert_not_reached ();
13308 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13310 g_assert_not_reached ();
13315 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13320 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13326 mono_reflection_type_get_handle (MonoReflectionType* ref)
13334 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13336 g_assert_not_reached ();
13339 #endif /* DISABLE_REFLECTION_EMIT */
13341 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13342 const static guint32 declsec_flags_map[] = {
13343 0x00000000, /* empty */
13344 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13345 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13346 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13347 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13348 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13349 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13350 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13351 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13352 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13353 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13354 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13355 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13356 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13357 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13358 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13359 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13360 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13361 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13365 * Returns flags that includes all available security action associated to the handle.
13366 * @token: metadata token (either for a class or a method)
13367 * @image: image where resides the metadata.
13370 mono_declsec_get_flags (MonoImage *image, guint32 token)
13372 int index = mono_metadata_declsec_from_index (image, token);
13373 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13374 guint32 result = 0;
13378 /* HasSecurity can be present for other, not specially encoded, attributes,
13379 e.g. SuppressUnmanagedCodeSecurityAttribute */
13383 for (i = index; i < t->rows; i++) {
13384 guint32 cols [MONO_DECL_SECURITY_SIZE];
13386 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13387 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13390 action = cols [MONO_DECL_SECURITY_ACTION];
13391 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13392 result |= declsec_flags_map [action];
13394 g_assert_not_reached ();
13401 * Get the security actions (in the form of flags) associated with the specified method.
13403 * @method: The method for which we want the declarative security flags.
13404 * Return the declarative security flags for the method (only).
13406 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13407 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13410 mono_declsec_flags_from_method (MonoMethod *method)
13412 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13413 /* FIXME: No cache (for the moment) */
13414 guint32 idx = mono_method_get_index (method);
13415 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13416 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13417 return mono_declsec_get_flags (method->klass->image, idx);
13423 * Get the security actions (in the form of flags) associated with the specified class.
13425 * @klass: The class for which we want the declarative security flags.
13426 * Return the declarative security flags for the class.
13428 * Note: We cache the flags inside the MonoClass structure as this will get
13429 * called very often (at least for each method).
13432 mono_declsec_flags_from_class (MonoClass *klass)
13434 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13435 if (!klass->ext || !klass->ext->declsec_flags) {
13438 idx = mono_metadata_token_index (klass->type_token);
13439 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13440 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13441 mono_loader_lock ();
13442 mono_class_alloc_ext (klass);
13443 mono_loader_unlock ();
13444 /* we cache the flags on classes */
13445 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13447 return klass->ext->declsec_flags;
13453 * Get the security actions (in the form of flags) associated with the specified assembly.
13455 * @assembly: The assembly for which we want the declarative security flags.
13456 * Return the declarative security flags for the assembly.
13459 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13461 guint32 idx = 1; /* there is only one assembly */
13462 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13463 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13464 return mono_declsec_get_flags (assembly->image, idx);
13469 * Fill actions for the specific index (which may either be an encoded class token or
13470 * an encoded method token) from the metadata image.
13471 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13474 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13475 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13477 MonoBoolean result = FALSE;
13479 guint32 cols [MONO_DECL_SECURITY_SIZE];
13480 int index = mono_metadata_declsec_from_index (image, token);
13483 t = &image->tables [MONO_TABLE_DECLSECURITY];
13484 for (i = index; i < t->rows; i++) {
13485 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13487 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13490 /* if present only replace (class) permissions with method permissions */
13491 /* if empty accept either class or method permissions */
13492 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13493 if (!actions->demand.blob) {
13494 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13495 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13496 actions->demand.blob = (char*) (blob + 2);
13497 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13500 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13501 if (!actions->noncasdemand.blob) {
13502 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13503 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13504 actions->noncasdemand.blob = (char*) (blob + 2);
13505 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13508 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13509 if (!actions->demandchoice.blob) {
13510 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13511 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13512 actions->demandchoice.blob = (char*) (blob + 2);
13513 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13523 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13524 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13526 guint32 idx = mono_metadata_token_index (klass->type_token);
13527 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13528 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13529 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13533 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13534 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13536 guint32 idx = mono_method_get_index (method);
13537 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13538 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13539 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13543 * Collect all actions (that requires to generate code in mini) assigned for
13544 * the specified method.
13545 * Note: Don't use the content of actions if the function return FALSE.
13548 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13550 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13551 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13552 MonoBoolean result = FALSE;
13555 /* quick exit if no declarative security is present in the metadata */
13556 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13559 /* we want the original as the wrapper is "free" of the security informations */
13560 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13561 method = mono_marshal_method_from_wrapper (method);
13566 /* First we look for method-level attributes */
13567 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13568 mono_class_init (method->klass);
13569 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13571 result = mono_declsec_get_method_demands_params (method, demands,
13572 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13575 /* Here we use (or create) the class declarative cache to look for demands */
13576 flags = mono_declsec_flags_from_class (method->klass);
13577 if (flags & mask) {
13579 mono_class_init (method->klass);
13580 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13582 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13583 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13586 /* The boolean return value is used as a shortcut in case nothing needs to
13587 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13593 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13595 * Note: Don't use the content of actions if the function return FALSE.
13598 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13600 MonoBoolean result = FALSE;
13603 /* quick exit if no declarative security is present in the metadata */
13604 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13607 /* we want the original as the wrapper is "free" of the security informations */
13608 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13609 method = mono_marshal_method_from_wrapper (method);
13614 /* results are independant - zeroize both */
13615 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13616 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13618 /* First we look for method-level attributes */
13619 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13620 mono_class_init (method->klass);
13622 result = mono_declsec_get_method_demands_params (method, cmethod,
13623 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13626 /* Here we use (or create) the class declarative cache to look for demands */
13627 flags = mono_declsec_flags_from_class (method->klass);
13628 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13629 mono_class_init (method->klass);
13631 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13632 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13639 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13641 * @klass The inherited class - this is the class that provides the security check (attributes)
13643 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13645 * Note: Don't use the content of actions if the function return FALSE.
13648 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13650 MonoBoolean result = FALSE;
13653 /* quick exit if no declarative security is present in the metadata */
13654 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13657 /* Here we use (or create) the class declarative cache to look for demands */
13658 flags = mono_declsec_flags_from_class (klass);
13659 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13660 mono_class_init (klass);
13661 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13663 result |= mono_declsec_get_class_demands_params (klass, demands,
13664 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13671 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13673 * Note: Don't use the content of actions if the function return FALSE.
13676 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13678 /* quick exit if no declarative security is present in the metadata */
13679 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13682 /* we want the original as the wrapper is "free" of the security informations */
13683 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13684 method = mono_marshal_method_from_wrapper (method);
13689 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13690 mono_class_init (method->klass);
13691 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13693 return mono_declsec_get_method_demands_params (method, demands,
13694 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13701 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13703 guint32 cols [MONO_DECL_SECURITY_SIZE];
13707 int index = mono_metadata_declsec_from_index (image, token);
13711 t = &image->tables [MONO_TABLE_DECLSECURITY];
13712 for (i = index; i < t->rows; i++) {
13713 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13715 /* shortcut - index are ordered */
13716 if (token != cols [MONO_DECL_SECURITY_PARENT])
13719 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13720 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13721 entry->blob = (char*) (metadata + 2);
13722 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13731 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13733 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13734 guint32 idx = mono_method_get_index (method);
13735 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13736 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13737 return get_declsec_action (method->klass->image, idx, action, entry);
13743 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13746 guint32 flags = mono_declsec_flags_from_class (klass);
13747 if (declsec_flags_map [action] & flags) {
13748 guint32 idx = mono_metadata_token_index (klass->type_token);
13749 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13750 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13751 return get_declsec_action (klass->image, idx, action, entry);
13757 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13759 guint32 idx = 1; /* there is only one assembly */
13760 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13761 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13763 return get_declsec_action (assembly->image, idx, action, entry);
13767 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13770 MonoObject *res, *exc;
13772 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13773 static MonoMethod *method = NULL;
13775 if (!System_Reflection_Emit_TypeBuilder) {
13776 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13777 g_assert (System_Reflection_Emit_TypeBuilder);
13779 if (method == NULL) {
13780 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13785 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13786 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13788 g_assert (mono_class_get_ref_info (klass));
13789 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13791 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13792 mono_error_raise_exception (&error); /* FIXME don't raise here */
13794 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13796 if (exc || !mono_error_ok (&error)) {
13797 mono_error_cleanup (&error);
13800 return *(MonoBoolean*)mono_object_unbox (res);
13804 * mono_reflection_type_get_type:
13805 * @reftype: the System.Type object
13807 * Returns the MonoType* associated with the C# System.Type object @reftype.
13810 mono_reflection_type_get_type (MonoReflectionType *reftype)
13812 g_assert (reftype);
13814 return mono_reflection_type_get_handle (reftype);
13818 * mono_reflection_assembly_get_assembly:
13819 * @refassembly: the System.Reflection.Assembly object
13821 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13824 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13826 g_assert (refassembly);
13828 return refassembly->assembly;