2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static 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);
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)
1823 MONO_REQ_GC_UNSAFE_MODE;
1827 MonoDynamicTable *table;
1829 ReflectionMethodBuilder rmb;
1832 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
1833 mono_error_raise_exception (&error); /* FIXME don't raise here */
1835 mono_image_basic_method (&rmb, assembly, &error);
1836 mono_error_raise_exception (&error); /* FIXME don't raise here */
1837 mb->table_idx = *rmb.table_idx;
1839 if (mb->dll) { /* It's a P/Invoke method */
1841 /* map CharSet values to on-disk values */
1842 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1843 int extra_flags = mb->extra_flags;
1844 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1849 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1850 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1852 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1854 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1855 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1856 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1857 table = &assembly->tables [MONO_TABLE_MODULEREF];
1859 alloc_table (table, table->rows);
1860 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1861 values [MONO_IMPLMAP_SCOPE] = table->rows;
1865 if (mb->generic_params) {
1866 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1867 table->rows += mono_array_length (mb->generic_params);
1868 alloc_table (table, table->rows);
1869 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1870 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1872 mono_image_get_generic_param_info (
1873 (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)
2481 MONO_REQ_GC_UNSAFE_MODE;
2485 MonoDynamicTable *table;
2486 MonoGenericParam *param;
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);
2508 mono_error_raise_exception (&error); /* FIXME don't raise here */
2512 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2514 MONO_REQ_GC_UNSAFE_MODE;
2516 MonoDynamicTable *table;
2519 guint32 cols [MONO_ASSEMBLY_SIZE];
2523 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2526 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2527 table = &assembly->tables [MONO_TABLE_MODULEREF];
2528 token = table->next_idx ++;
2530 alloc_table (table, table->rows);
2531 values = table->values + token * MONO_MODULEREF_SIZE;
2532 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2534 token <<= MONO_RESOLUTION_SCOPE_BITS;
2535 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2536 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2541 if (assembly_is_dynamic (image->assembly))
2543 memset (cols, 0, sizeof (cols));
2545 /* image->assembly->image is the manifest module */
2546 image = image->assembly->image;
2547 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2550 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2551 token = table->next_idx ++;
2553 alloc_table (table, table->rows);
2554 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2555 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2556 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2557 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2558 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2559 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2560 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2561 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2562 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2564 if (strcmp ("", image->assembly->aname.culture)) {
2565 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2566 image->assembly->aname.culture);
2569 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2570 guchar pubtoken [9];
2572 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2573 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2575 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2577 token <<= MONO_RESOLUTION_SCOPE_BITS;
2578 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2579 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2584 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2586 MONO_REQ_GC_NEUTRAL_MODE;
2588 MonoDynamicTable *table;
2593 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2596 sigbuffer_init (&buf, 32);
2597 switch (type->type) {
2598 case MONO_TYPE_FNPTR:
2600 case MONO_TYPE_SZARRAY:
2601 case MONO_TYPE_ARRAY:
2603 case MONO_TYPE_MVAR:
2604 case MONO_TYPE_GENERICINST:
2605 encode_type (assembly, type, &buf);
2607 case MONO_TYPE_CLASS:
2608 case MONO_TYPE_VALUETYPE: {
2609 MonoClass *k = mono_class_from_mono_type (type);
2610 if (!k || !k->generic_container) {
2611 sigbuffer_free (&buf);
2614 encode_type (assembly, type, &buf);
2618 sigbuffer_free (&buf);
2622 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2623 if (assembly->save) {
2624 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2625 alloc_table (table, table->rows + 1);
2626 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2627 values [MONO_TYPESPEC_SIGNATURE] = token;
2629 sigbuffer_free (&buf);
2631 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2632 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2638 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2640 MONO_REQ_GC_UNSAFE_MODE;
2642 MonoDynamicTable *table;
2644 guint32 token, scope, enclosing;
2647 /* if the type requires a typespec, we must try that first*/
2648 if (try_typespec && (token = create_typespec (assembly, type)))
2650 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2653 klass = mono_class_from_mono_type (type);
2655 klass = mono_class_from_mono_type (type);
2658 * If it's in the same module and not a generic type parameter:
2660 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2661 (type->type != MONO_TYPE_MVAR)) {
2662 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2663 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2664 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2668 if (klass->nested_in) {
2669 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2670 /* get the typeref idx of the enclosing type */
2671 enclosing >>= MONO_TYPEDEFORREF_BITS;
2672 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2674 scope = resolution_scope_from_image (assembly, klass->image);
2676 table = &assembly->tables [MONO_TABLE_TYPEREF];
2677 if (assembly->save) {
2678 alloc_table (table, table->rows + 1);
2679 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2680 values [MONO_TYPEREF_SCOPE] = scope;
2681 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2682 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2684 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2685 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2687 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2692 * Despite the name, we handle also TypeSpec (with the above helper).
2695 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2697 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2700 #ifndef DISABLE_REFLECTION_EMIT
2702 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2704 MONO_REQ_GC_NEUTRAL_MODE;
2706 MonoDynamicTable *table;
2708 guint32 token, pclass;
2710 switch (parent & MONO_TYPEDEFORREF_MASK) {
2711 case MONO_TYPEDEFORREF_TYPEREF:
2712 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2714 case MONO_TYPEDEFORREF_TYPESPEC:
2715 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2717 case MONO_TYPEDEFORREF_TYPEDEF:
2718 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2721 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2724 /* extract the index */
2725 parent >>= MONO_TYPEDEFORREF_BITS;
2727 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2729 if (assembly->save) {
2730 alloc_table (table, table->rows + 1);
2731 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2732 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2733 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2734 values [MONO_MEMBERREF_SIGNATURE] = sig;
2737 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2744 * Insert a memberef row into the metadata: the token that point to the memberref
2745 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2746 * mono_image_get_fieldref_token()).
2747 * The sig param is an index to an already built signature.
2750 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2752 MONO_REQ_GC_NEUTRAL_MODE;
2754 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2755 return mono_image_add_memberef_row (assembly, parent, name, sig);
2760 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2762 MONO_REQ_GC_NEUTRAL_MODE;
2765 MonoMethodSignature *sig;
2767 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2769 if (create_typespec) {
2770 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2775 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2776 if (token && !create_typespec)
2779 g_assert (!method->is_inflated);
2782 * A methodref signature can't contain an unmanaged calling convention.
2784 sig = mono_metadata_signature_dup (mono_method_signature (method));
2785 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2786 sig->call_convention = MONO_CALL_DEFAULT;
2787 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2788 method->name, method_encode_signature (assembly, sig));
2790 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2793 if (create_typespec) {
2794 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2795 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2796 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2798 if (assembly->save) {
2801 alloc_table (table, table->rows + 1);
2802 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2803 values [MONO_METHODSPEC_METHOD] = token;
2804 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2807 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2809 /*methodspec and memberef tokens are diferent, */
2810 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2817 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2820 guint32 token, parent, sig;
2821 ReflectionMethodBuilder rmb;
2823 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2825 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2829 name = mono_string_to_utf8 (method->name);
2830 if (!reflection_methodbuilder_from_method_builder (&rmb, method, &error))
2831 mono_error_raise_exception (&error); /* FIXME don't raise here */
2834 * A methodref signature can't contain an unmanaged calling convention.
2835 * Since some flags are encoded as part of call_conv, we need to check against it.
2837 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2838 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2840 sig = method_builder_encode_signature (assembly, &rmb);
2842 if (tb->generic_params)
2843 parent = create_generic_typespec (assembly, tb);
2845 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2847 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2850 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2855 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2856 const gchar *name, guint32 sig)
2858 MonoDynamicTable *table;
2862 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2864 if (assembly->save) {
2865 alloc_table (table, table->rows + 1);
2866 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2867 values [MONO_MEMBERREF_CLASS] = original;
2868 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2869 values [MONO_MEMBERREF_SIGNATURE] = sig;
2872 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2879 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2883 guint32 nparams = mono_array_length (mb->generic_params);
2886 if (!assembly->save)
2889 sigbuffer_init (&buf, 32);
2891 sigbuffer_add_value (&buf, 0xa);
2892 sigbuffer_add_value (&buf, nparams);
2894 for (i = 0; i < nparams; i++) {
2895 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2896 sigbuffer_add_value (&buf, i);
2899 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2900 sigbuffer_free (&buf);
2905 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2907 MonoDynamicTable *table;
2909 guint32 token, mtoken = 0;
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);
2918 switch (mono_metadata_token_table (mtoken)) {
2919 case MONO_TABLE_MEMBERREF:
2920 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922 case MONO_TABLE_METHOD:
2923 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2926 g_assert_not_reached ();
2929 if (assembly->save) {
2930 alloc_table (table, table->rows + 1);
2931 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2932 values [MONO_METHODSPEC_METHOD] = mtoken;
2933 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2936 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2939 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2944 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2948 if (mb->generic_params && create_methodspec)
2949 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2951 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2955 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2956 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2961 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2964 guint32 token, parent, sig;
2965 ReflectionMethodBuilder rmb;
2967 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2969 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2973 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, &error))
2974 mono_error_raise_exception (&error); /* FIXME don't raise here */
2976 if (tb->generic_params)
2977 parent = create_generic_typespec (assembly, tb);
2979 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2981 name = mono_string_to_utf8 (rmb.name);
2982 sig = method_builder_encode_signature (assembly, &rmb);
2984 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2987 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2993 is_field_on_inst (MonoClassField *field)
2995 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2999 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3002 get_field_on_inst_generic_type (MonoClassField *field)
3004 MonoClass *klass, *gtd;
3005 MonoDynamicGenericClass *dgclass;
3008 g_assert (is_field_on_inst (field));
3010 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3012 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3013 field_index = field - dgclass->fields;
3014 return dgclass->field_generic_types [field_index];
3017 klass = field->parent;
3018 gtd = klass->generic_class->container_class;
3020 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3021 field_index = field - klass->fields;
3022 return gtd->fields [field_index].type;
3025 g_assert_not_reached ();
3029 #ifndef DISABLE_REFLECTION_EMIT
3031 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3037 g_assert (field->parent);
3039 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3043 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3044 int index = field - field->parent->fields;
3045 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3047 if (is_field_on_inst (field))
3048 type = get_field_on_inst_generic_type (field);
3050 type = mono_field_get_type (field);
3052 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3053 mono_field_get_name (field),
3054 fieldref_encode_signature (assembly, field->parent->image, type));
3055 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3060 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3064 MonoGenericClass *gclass;
3068 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3071 if (is_sre_field_builder (mono_object_class (f->fb))) {
3072 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3073 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3074 klass = mono_class_from_mono_type (type);
3075 gclass = type->data.generic_class;
3076 g_assert (gclass->is_dynamic);
3078 name = mono_string_to_utf8 (fb->name);
3079 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3080 field_encode_signature (assembly, fb));
3082 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3084 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3086 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3087 klass = mono_class_from_mono_type (type);
3089 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3090 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3092 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3093 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3096 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3101 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3106 MonoGenericClass *gclass;
3109 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3111 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3115 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3116 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3117 ReflectionMethodBuilder rmb;
3120 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3121 klass = mono_class_from_mono_type (type);
3123 gclass = type->data.generic_class;
3124 g_assert (gclass->is_dynamic);
3126 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, &error))
3127 mono_error_raise_exception (&error); /* FIXME don't raise here */
3129 name = mono_string_to_utf8 (rmb.name);
3131 sig = method_builder_encode_signature (assembly, &rmb);
3133 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3135 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3136 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3138 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3139 klass = mono_class_from_mono_type (type);
3141 sig = method_encode_signature (assembly, mono_method_signature (mm));
3142 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3144 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3145 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3149 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3154 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3158 MonoGenericContext tmp_context;
3159 MonoType **type_argv;
3160 MonoGenericInst *ginst;
3161 MonoMethod *method, *inflated;
3164 init_type_builder_generics ((MonoObject*)m->inst);
3166 method = inflate_method (m->inst, (MonoObject*)m->mb);
3168 klass = method->klass;
3170 if (m->method_args == NULL)
3173 if (method->is_inflated)
3174 method = ((MonoMethodInflated *) method)->declaring;
3176 count = mono_array_length (m->method_args);
3178 type_argv = g_new0 (MonoType *, count);
3179 for (i = 0; i < count; i++) {
3180 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3181 type_argv [i] = mono_reflection_type_get_handle (garg);
3183 ginst = mono_metadata_get_generic_inst (count, type_argv);
3186 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3187 tmp_context.method_inst = ginst;
3189 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3190 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3195 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3199 guint32 sig, token = 0;
3203 if (m->method_args) {
3204 MonoMethod *inflated;
3206 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3207 if (create_methodspec)
3208 token = mono_image_get_methodspec_token (assembly, inflated);
3210 token = mono_image_get_inflated_method_token (assembly, inflated);
3214 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3218 if (is_sre_method_builder (mono_object_class (m->mb))) {
3219 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3220 MonoGenericClass *gclass;
3221 ReflectionMethodBuilder rmb;
3224 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3225 klass = mono_class_from_mono_type (type);
3226 gclass = type->data.generic_class;
3227 g_assert (gclass->is_dynamic);
3229 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
3230 mono_error_raise_exception (&error); /* FIXME don't raise here */
3232 name = mono_string_to_utf8 (rmb.name);
3234 sig = method_builder_encode_signature (assembly, &rmb);
3236 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3238 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3239 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3241 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3242 klass = mono_class_from_mono_type (type);
3244 sig = method_encode_signature (assembly, mono_method_signature (mm));
3245 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3247 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3248 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3251 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3256 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3260 guint32 nparams = context->method_inst->type_argc;
3263 if (!assembly->save)
3266 sigbuffer_init (&buf, 32);
3268 * FIXME: vararg, explicit_this, differenc call_conv values...
3270 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3271 sigbuffer_add_value (&buf, nparams);
3273 for (i = 0; i < nparams; i++)
3274 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3276 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3277 sigbuffer_free (&buf);
3282 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3284 MonoDynamicTable *table;
3286 guint32 token, mtoken = 0, sig;
3287 MonoMethodInflated *imethod;
3288 MonoMethod *declaring;
3290 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3292 g_assert (method->is_inflated);
3293 imethod = (MonoMethodInflated *) method;
3294 declaring = imethod->declaring;
3296 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3297 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3299 if (!mono_method_signature (declaring)->generic_param_count)
3302 switch (mono_metadata_token_table (mtoken)) {
3303 case MONO_TABLE_MEMBERREF:
3304 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3306 case MONO_TABLE_METHOD:
3307 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3310 g_assert_not_reached ();
3313 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3315 if (assembly->save) {
3316 alloc_table (table, table->rows + 1);
3317 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3318 values [MONO_METHODSPEC_METHOD] = mtoken;
3319 values [MONO_METHODSPEC_SIGNATURE] = sig;
3322 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3329 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3331 MonoMethodInflated *imethod;
3334 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3338 g_assert (method->is_inflated);
3339 imethod = (MonoMethodInflated *) method;
3341 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3342 token = method_encode_methodspec (assembly, method);
3344 guint32 sig = method_encode_signature (
3345 assembly, mono_method_signature (imethod->declaring));
3346 token = mono_image_get_memberref_token (
3347 assembly, &method->klass->byval_arg, method->name, sig);
3350 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3355 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3357 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3360 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3361 token = mono_image_get_memberref_token (
3362 assembly, &m->klass->byval_arg, m->name, sig);
3368 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3370 MonoDynamicTable *table;
3379 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3380 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3381 * Because of this, we must not insert it into the `typeref' hash table.
3383 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3384 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3388 sigbuffer_init (&buf, 32);
3390 g_assert (tb->generic_params);
3391 klass = mono_class_from_mono_type (type);
3393 if (tb->generic_container)
3394 mono_reflection_create_generic_class (tb);
3396 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3397 g_assert (klass->generic_container);
3398 sigbuffer_add_value (&buf, klass->byval_arg.type);
3399 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3401 count = mono_array_length (tb->generic_params);
3402 sigbuffer_add_value (&buf, count);
3403 for (i = 0; i < count; i++) {
3404 MonoReflectionGenericParam *gparam;
3406 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3408 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3411 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3413 if (assembly->save) {
3414 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3415 alloc_table (table, table->rows + 1);
3416 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3417 values [MONO_TYPESPEC_SIGNATURE] = token;
3419 sigbuffer_free (&buf);
3421 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3422 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3428 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3431 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3433 int i, count, len, pos;
3438 count += mono_array_length (modreq);
3440 count += mono_array_length (modopt);
3443 return mono_metadata_type_dup (NULL, type);
3445 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3446 t = (MonoType *)g_malloc (len);
3447 memcpy (t, type, MONO_SIZEOF_TYPE);
3449 t->num_mods = count;
3452 for (i = 0; i < mono_array_length (modreq); ++i) {
3453 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3454 t->modifiers [pos].required = 1;
3455 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3460 for (i = 0; i < mono_array_length (modopt); ++i) {
3461 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3462 t->modifiers [pos].required = 0;
3463 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3472 init_type_builder_generics (MonoObject *type)
3474 MonoReflectionTypeBuilder *tb;
3476 if (!is_sre_type_builder(mono_object_class (type)))
3478 tb = (MonoReflectionTypeBuilder *)type;
3480 if (tb && tb->generic_container)
3481 mono_reflection_create_generic_class (tb);
3485 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3487 MonoDynamicTable *table;
3488 MonoType *custom = NULL, *type;
3490 guint32 token, pclass, parent, sig;
3493 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3497 /* FIXME: is this call necessary? */
3498 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3499 name = mono_string_to_utf8 (fb->name);
3501 /*FIXME this is one more layer of ugliness due how types are created.*/
3502 init_type_builder_generics (fb->type);
3504 /* fb->type does not include the custom modifiers */
3505 /* FIXME: We should do this in one place when a fieldbuilder is created */
3506 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3507 if (fb->modreq || fb->modopt)
3508 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3510 sig = fieldref_encode_signature (assembly, NULL, type);
3513 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3514 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3516 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3517 parent >>= MONO_TYPEDEFORREF_BITS;
3519 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3521 if (assembly->save) {
3522 alloc_table (table, table->rows + 1);
3523 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3524 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3525 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3526 values [MONO_MEMBERREF_SIGNATURE] = sig;
3529 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3531 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3537 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3543 if (!assembly->save)
3546 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3547 g_assert (helper->type == 2);
3549 if (helper->arguments)
3550 nargs = mono_array_length (helper->arguments);
3554 sigbuffer_init (&buf, 32);
3556 /* Encode calling convention */
3557 /* Change Any to Standard */
3558 if ((helper->call_conv & 0x03) == 0x03)
3559 helper->call_conv = 0x01;
3560 /* explicit_this implies has_this */
3561 if (helper->call_conv & 0x40)
3562 helper->call_conv &= 0x20;
3564 if (helper->call_conv == 0) { /* Unmanaged */
3565 idx = helper->unmanaged_call_conv - 1;
3568 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3569 if (helper->call_conv & 0x02) /* varargs */
3573 sigbuffer_add_byte (&buf, idx);
3574 sigbuffer_add_value (&buf, nargs);
3575 encode_reflection_type (assembly, helper->return_type, &buf);
3576 for (i = 0; i < nargs; ++i) {
3577 MonoArray *modreqs = NULL;
3578 MonoArray *modopts = NULL;
3579 MonoReflectionType *pt;
3581 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3582 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3583 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3584 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3586 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3587 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3588 encode_reflection_type (assembly, pt, &buf);
3590 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3591 sigbuffer_free (&buf);
3597 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3600 MonoDynamicTable *table;
3603 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3604 idx = table->next_idx ++;
3606 alloc_table (table, table->rows);
3607 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3609 values [MONO_STAND_ALONE_SIGNATURE] =
3610 mono_reflection_encode_sighelper (assembly, helper);
3616 reflection_cc_to_file (int call_conv) {
3617 switch (call_conv & 0x3) {
3619 case 1: return MONO_CALL_DEFAULT;
3620 case 2: return MONO_CALL_VARARG;
3622 g_assert_not_reached ();
3626 #endif /* !DISABLE_REFLECTION_EMIT */
3630 MonoMethodSignature *sig;
3635 #ifndef DISABLE_REFLECTION_EMIT
3637 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3642 MonoMethodSignature *sig;
3646 name = mono_string_to_utf8 (m->name);
3647 nparams = mono_array_length (m->parameters);
3648 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3650 sig->sentinelpos = -1;
3651 sig->call_convention = reflection_cc_to_file (m->call_conv);
3652 sig->param_count = nparams;
3653 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3654 mtype = mono_reflection_type_get_handle (m->parent);
3655 for (i = 0; i < nparams; ++i)
3656 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3658 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3659 am = (ArrayMethod *)tmp->data;
3660 if (strcmp (name, am->name) == 0 &&
3661 mono_metadata_type_equal (am->parent, mtype) &&
3662 mono_metadata_signature_equal (am->sig, sig)) {
3665 m->table_idx = am->token & 0xffffff;
3669 am = g_new0 (ArrayMethod, 1);
3673 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3674 method_encode_signature (assembly, sig));
3675 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3676 m->table_idx = am->token & 0xffffff;
3681 * Insert into the metadata tables all the info about the TypeBuilder tb.
3682 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3685 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3688 MonoDynamicTable *table;
3690 int i, is_object = 0, is_system = 0;
3693 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3694 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3695 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3696 n = mono_string_to_utf8 (tb->name);
3697 if (strcmp (n, "Object") == 0)
3699 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3701 n = mono_string_to_utf8 (tb->nspace);
3702 if (strcmp (n, "System") == 0)
3704 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3706 if (tb->parent && !(is_system && is_object) &&
3707 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3708 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3710 values [MONO_TYPEDEF_EXTENDS] = 0;
3712 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3713 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3716 * if we have explicitlayout or sequentiallayouts, output data in the
3717 * ClassLayout table.
3719 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3720 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3721 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3723 alloc_table (table, table->rows);
3724 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3725 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3726 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3727 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3730 /* handle interfaces */
3731 if (tb->interfaces) {
3732 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3734 table->rows += mono_array_length (tb->interfaces);
3735 alloc_table (table, table->rows);
3736 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3737 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3738 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3739 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3740 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3741 values += MONO_INTERFACEIMPL_SIZE;
3747 table = &assembly->tables [MONO_TABLE_FIELD];
3748 table->rows += tb->num_fields;
3749 alloc_table (table, table->rows);
3750 for (i = 0; i < tb->num_fields; ++i)
3751 mono_image_get_field_info (
3752 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3755 /* handle constructors */
3757 table = &assembly->tables [MONO_TABLE_METHOD];
3758 table->rows += mono_array_length (tb->ctors);
3759 alloc_table (table, table->rows);
3760 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3761 mono_image_get_ctor_info (domain,
3762 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3764 mono_error_raise_exception (&error); /* FIXME don't raise here */
3768 /* handle methods */
3770 table = &assembly->tables [MONO_TABLE_METHOD];
3771 table->rows += tb->num_methods;
3772 alloc_table (table, table->rows);
3773 for (i = 0; i < tb->num_methods; ++i)
3774 mono_image_get_method_info (
3775 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3778 /* Do the same with properties etc.. */
3779 if (tb->events && mono_array_length (tb->events)) {
3780 table = &assembly->tables [MONO_TABLE_EVENT];
3781 table->rows += mono_array_length (tb->events);
3782 alloc_table (table, table->rows);
3783 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3785 alloc_table (table, table->rows);
3786 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3787 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3788 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3789 for (i = 0; i < mono_array_length (tb->events); ++i)
3790 mono_image_get_event_info (
3791 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3793 if (tb->properties && mono_array_length (tb->properties)) {
3794 table = &assembly->tables [MONO_TABLE_PROPERTY];
3795 table->rows += mono_array_length (tb->properties);
3796 alloc_table (table, table->rows);
3797 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3799 alloc_table (table, table->rows);
3800 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3801 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3802 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3803 for (i = 0; i < mono_array_length (tb->properties); ++i)
3804 mono_image_get_property_info (
3805 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3808 /* handle generic parameters */
3809 if (tb->generic_params) {
3810 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3811 table->rows += mono_array_length (tb->generic_params);
3812 alloc_table (table, table->rows);
3813 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3814 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3816 mono_image_get_generic_param_info (
3817 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3821 mono_image_add_decl_security (assembly,
3822 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3825 MonoDynamicTable *ntable;
3827 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3828 ntable->rows += mono_array_length (tb->subtypes);
3829 alloc_table (ntable, ntable->rows);
3830 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3832 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3833 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3835 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3836 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3837 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3838 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3839 mono_string_to_utf8 (tb->name), tb->table_idx,
3840 ntable->next_idx, ntable->rows);*/
3841 values += MONO_NESTED_CLASS_SIZE;
3849 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3853 mono_ptr_array_append (*types, type);
3855 if (!type->subtypes)
3858 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3859 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3860 collect_types (types, subtype);
3865 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3867 if ((*type1)->table_idx < (*type2)->table_idx)
3870 if ((*type1)->table_idx > (*type2)->table_idx)
3877 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3880 mono_error_init (error);
3883 for (i = 0; i < mono_array_length (pinfo); ++i) {
3884 MonoReflectionParamBuilder *pb;
3885 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3888 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3896 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3899 mono_error_init (error);
3901 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3904 for (i = 0; i < tb->num_fields; ++i) {
3905 MonoReflectionFieldBuilder* fb;
3906 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3907 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3912 for (i = 0; i < mono_array_length (tb->events); ++i) {
3913 MonoReflectionEventBuilder* eb;
3914 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3915 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3919 if (tb->properties) {
3920 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3921 MonoReflectionPropertyBuilder* pb;
3922 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3923 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3928 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3929 MonoReflectionCtorBuilder* cb;
3930 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3931 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3932 !params_add_cattrs (assembly, cb->pinfo, error))
3938 for (i = 0; i < tb->num_methods; ++i) {
3939 MonoReflectionMethodBuilder* mb;
3940 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3941 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3942 !params_add_cattrs (assembly, mb->pinfo, error))
3948 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3949 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3958 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3962 mono_error_init (error);
3964 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3967 if (moduleb->global_methods) {
3968 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3969 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3970 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3971 !params_add_cattrs (assembly, mb->pinfo, error))
3976 if (moduleb->global_fields) {
3977 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3978 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3979 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3984 if (moduleb->types) {
3985 for (i = 0; i < moduleb->num_types; ++i) {
3986 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
3995 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3997 MonoDynamicTable *table;
4001 char *b = blob_size;
4004 table = &assembly->tables [MONO_TABLE_FILE];
4006 alloc_table (table, table->rows);
4007 values = table->values + table->next_idx * MONO_FILE_SIZE;
4008 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4009 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4010 if (image_is_dynamic (module->image)) {
4011 /* This depends on the fact that the main module is emitted last */
4012 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4013 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4016 path = g_strdup (module->image->name);
4018 mono_sha1_get_digest_from_file (path, hash);
4021 mono_metadata_encode_value (20, b, &b);
4022 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4023 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4028 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4030 MonoDynamicTable *table;
4033 table = &assembly->tables [MONO_TABLE_MODULE];
4034 mb->table_idx = table->next_idx ++;
4035 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4036 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4039 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4040 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4041 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4042 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4046 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4047 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4049 MonoDynamicTable *table;
4053 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4054 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4057 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4059 alloc_table (table, table->rows);
4060 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4062 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4063 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4064 if (klass->nested_in)
4065 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4067 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4068 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4069 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4071 res = table->next_idx;
4075 /* Emit nested types */
4076 if (klass->ext && klass->ext->nested_classes) {
4079 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4080 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4087 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4088 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4093 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4095 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4097 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4098 parent_index, assembly);
4102 * We need to do this ourselves since klass->nested_classes is not set up.
4105 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4106 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4111 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4112 guint32 module_index, MonoDynamicImage *assembly)
4114 MonoImage *image = module->image;
4118 t = &image->tables [MONO_TABLE_TYPEDEF];
4120 for (i = 0; i < t->rows; ++i) {
4122 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4123 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4125 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4126 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4131 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4133 MonoDynamicTable *table;
4135 guint32 scope, scope_idx, impl, current_idx;
4136 gboolean forwarder = TRUE;
4137 gpointer iter = NULL;
4140 if (klass->nested_in) {
4141 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4144 scope = resolution_scope_from_image (assembly, klass->image);
4145 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4146 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4147 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4150 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4153 alloc_table (table, table->rows);
4154 current_idx = table->next_idx;
4155 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4157 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4158 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4159 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4160 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4161 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4165 while ((nested = mono_class_get_nested_types (klass, &iter)))
4166 add_exported_type (assemblyb, assembly, nested, current_idx);
4170 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4175 if (!assemblyb->type_forwarders)
4178 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4179 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4184 type = mono_reflection_type_get_handle (t);
4187 klass = mono_class_from_mono_type (type);
4189 add_exported_type (assemblyb, assembly, klass, 0);
4193 #define align_pointer(base,p)\
4195 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4197 (p) += 4 - (__diff & 3);\
4201 compare_constants (const void *a, const void *b)
4203 const guint32 *a_values = (const guint32 *)a;
4204 const guint32 *b_values = (const guint32 *)b;
4205 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4209 compare_semantics (const void *a, const void *b)
4211 const guint32 *a_values = (const guint32 *)a;
4212 const guint32 *b_values = (const guint32 *)b;
4213 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4216 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4220 compare_custom_attrs (const void *a, const void *b)
4222 const guint32 *a_values = (const guint32 *)a;
4223 const guint32 *b_values = (const guint32 *)b;
4225 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4229 compare_field_marshal (const void *a, const void *b)
4231 const guint32 *a_values = (const guint32 *)a;
4232 const guint32 *b_values = (const guint32 *)b;
4234 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4238 compare_nested (const void *a, const void *b)
4240 const guint32 *a_values = (const guint32 *)a;
4241 const guint32 *b_values = (const guint32 *)b;
4243 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4247 compare_genericparam (const void *a, const void *b)
4249 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4250 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4252 if ((*b_entry)->owner == (*a_entry)->owner)
4254 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4255 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4257 return (*a_entry)->owner - (*b_entry)->owner;
4261 compare_declsecurity_attrs (const void *a, const void *b)
4263 const guint32 *a_values = (const guint32 *)a;
4264 const guint32 *b_values = (const guint32 *)b;
4266 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4270 compare_interface_impl (const void *a, const void *b)
4272 const guint32 *a_values = (const guint32 *)a;
4273 const guint32 *b_values = (const guint32 *)b;
4275 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4279 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4283 pad_heap (MonoDynamicStream *sh)
4285 if (sh->index & 3) {
4286 int sz = 4 - (sh->index & 3);
4287 memset (sh->data + sh->index, 0, sz);
4294 MonoDynamicStream *stream;
4298 * build_compressed_metadata() fills in the blob of data that represents the
4299 * raw metadata as it will be saved in the PE file. The five streams are output
4300 * and the metadata tables are comnpressed from the guint32 array representation,
4301 * to the compressed on-disk format.
4304 build_compressed_metadata (MonoDynamicImage *assembly)
4306 MonoDynamicTable *table;
4308 guint64 valid_mask = 0;
4309 guint64 sorted_mask;
4310 guint32 heapt_size = 0;
4311 guint32 meta_size = 256; /* allow for header and other stuff */
4312 guint32 table_offset;
4313 guint32 ntables = 0;
4319 struct StreamDesc stream_desc [5];
4321 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4322 for (i = 0; i < assembly->gen_params->len; i++){
4323 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4324 write_generic_param_entry (assembly, entry);
4327 stream_desc [0].name = "#~";
4328 stream_desc [0].stream = &assembly->tstream;
4329 stream_desc [1].name = "#Strings";
4330 stream_desc [1].stream = &assembly->sheap;
4331 stream_desc [2].name = "#US";
4332 stream_desc [2].stream = &assembly->us;
4333 stream_desc [3].name = "#Blob";
4334 stream_desc [3].stream = &assembly->blob;
4335 stream_desc [4].name = "#GUID";
4336 stream_desc [4].stream = &assembly->guid;
4338 /* tables that are sorted */
4339 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4340 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4341 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4342 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4343 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4344 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4345 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4347 /* Compute table sizes */
4348 /* the MonoImage has already been created in mono_image_basic_init() */
4349 meta = &assembly->image;
4351 /* sizes should be multiple of 4 */
4352 pad_heap (&assembly->blob);
4353 pad_heap (&assembly->guid);
4354 pad_heap (&assembly->sheap);
4355 pad_heap (&assembly->us);
4357 /* Setup the info used by compute_sizes () */
4358 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4359 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4360 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4362 meta_size += assembly->blob.index;
4363 meta_size += assembly->guid.index;
4364 meta_size += assembly->sheap.index;
4365 meta_size += assembly->us.index;
4367 for (i=0; i < MONO_TABLE_NUM; ++i)
4368 meta->tables [i].rows = assembly->tables [i].rows;
4370 for (i = 0; i < MONO_TABLE_NUM; i++){
4371 if (meta->tables [i].rows == 0)
4373 valid_mask |= (guint64)1 << i;
4375 meta->tables [i].row_size = mono_metadata_compute_size (
4376 meta, i, &meta->tables [i].size_bitfield);
4377 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4379 heapt_size += 24; /* #~ header size */
4380 heapt_size += ntables * 4;
4381 /* make multiple of 4 */
4384 meta_size += heapt_size;
4385 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4386 p = (unsigned char*)meta->raw_metadata;
4387 /* the metadata signature */
4388 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4389 /* version numbers and 4 bytes reserved */
4390 int16val = (guint16*)p;
4391 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4392 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4394 /* version string */
4395 int32val = (guint32*)p;
4396 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4398 memcpy (p, meta->version, strlen (meta->version));
4399 p += GUINT32_FROM_LE (*int32val);
4400 align_pointer (meta->raw_metadata, p);
4401 int16val = (guint16*)p;
4402 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4403 *int16val = GUINT16_TO_LE (5); /* number of streams */
4407 * write the stream info.
4409 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4410 table_offset += 3; table_offset &= ~3;
4412 assembly->tstream.index = heapt_size;
4413 for (i = 0; i < 5; ++i) {
4414 int32val = (guint32*)p;
4415 stream_desc [i].stream->offset = table_offset;
4416 *int32val++ = GUINT32_TO_LE (table_offset);
4417 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4418 table_offset += GUINT32_FROM_LE (*int32val);
4419 table_offset += 3; table_offset &= ~3;
4421 strcpy ((char*)p, stream_desc [i].name);
4422 p += strlen (stream_desc [i].name) + 1;
4423 align_pointer (meta->raw_metadata, p);
4426 * now copy the data, the table stream header and contents goes first.
4428 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4429 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4430 int32val = (guint32*)p;
4431 *int32val = GUINT32_TO_LE (0); /* reserved */
4434 *p++ = 2; /* version */
4437 if (meta->idx_string_wide)
4439 if (meta->idx_guid_wide)
4441 if (meta->idx_blob_wide)
4444 *p++ = 1; /* reserved */
4445 int64val = (guint64*)p;
4446 *int64val++ = GUINT64_TO_LE (valid_mask);
4447 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4449 int32val = (guint32*)p;
4450 for (i = 0; i < MONO_TABLE_NUM; i++){
4451 if (meta->tables [i].rows == 0)
4453 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4455 p = (unsigned char*)int32val;
4457 /* sort the tables that still need sorting */
4458 table = &assembly->tables [MONO_TABLE_CONSTANT];
4460 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4461 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4463 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4464 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4466 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4467 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4469 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4470 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4472 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4473 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4474 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4476 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4477 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4479 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4481 /* compress the tables */
4482 for (i = 0; i < MONO_TABLE_NUM; i++){
4485 guint32 bitfield = meta->tables [i].size_bitfield;
4486 if (!meta->tables [i].rows)
4488 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4489 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4490 meta->tables [i].base = (char*)p;
4491 for (row = 1; row <= meta->tables [i].rows; ++row) {
4492 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4493 for (col = 0; col < assembly->tables [i].columns; ++col) {
4494 switch (mono_metadata_table_size (bitfield, col)) {
4496 *p++ = values [col];
4499 *p++ = values [col] & 0xff;
4500 *p++ = (values [col] >> 8) & 0xff;
4503 *p++ = values [col] & 0xff;
4504 *p++ = (values [col] >> 8) & 0xff;
4505 *p++ = (values [col] >> 16) & 0xff;
4506 *p++ = (values [col] >> 24) & 0xff;
4509 g_assert_not_reached ();
4513 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4516 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4517 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4518 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4519 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4520 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4522 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4526 * Some tables in metadata need to be sorted according to some criteria, but
4527 * when methods and fields are first created with reflection, they may be assigned a token
4528 * that doesn't correspond to the final token they will get assigned after the sorting.
4529 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4530 * with the reflection objects that represent them. Once all the tables are set up, the
4531 * reflection objects will contains the correct table index. fixup_method() will fixup the
4532 * tokens for the method with ILGenerator @ilgen.
4535 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4537 guint32 code_idx = GPOINTER_TO_UINT (value);
4538 MonoReflectionILTokenInfo *iltoken;
4539 MonoReflectionFieldBuilder *field;
4540 MonoReflectionCtorBuilder *ctor;
4541 MonoReflectionMethodBuilder *method;
4542 MonoReflectionTypeBuilder *tb;
4543 MonoReflectionArrayMethod *am;
4545 unsigned char *target;
4547 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4548 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4549 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4550 switch (target [3]) {
4551 case MONO_TABLE_FIELD:
4552 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4553 field = (MonoReflectionFieldBuilder *)iltoken->member;
4554 idx = field->table_idx;
4555 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4556 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4557 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4559 g_assert_not_reached ();
4562 case MONO_TABLE_METHOD:
4563 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4564 method = (MonoReflectionMethodBuilder *)iltoken->member;
4565 idx = method->table_idx;
4566 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4567 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4568 idx = ctor->table_idx;
4569 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4570 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4571 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4572 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574 g_assert_not_reached ();
4577 case MONO_TABLE_TYPEDEF:
4578 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4579 g_assert_not_reached ();
4580 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4581 idx = tb->table_idx;
4583 case MONO_TABLE_MEMBERREF:
4584 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4585 am = (MonoReflectionArrayMethod*)iltoken->member;
4586 idx = am->table_idx;
4587 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4588 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4589 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4590 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4591 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4592 g_assert (m->klass->generic_class || m->klass->generic_container);
4594 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4596 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4597 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4598 g_assert (is_field_on_inst (f));
4600 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4601 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4603 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4605 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4607 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4610 g_assert_not_reached ();
4613 case MONO_TABLE_METHODSPEC:
4614 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4615 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616 g_assert (mono_method_signature (m)->generic_param_count);
4618 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4620 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4623 g_assert_not_reached ();
4627 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4629 target [0] = idx & 0xff;
4630 target [1] = (idx >> 8) & 0xff;
4631 target [2] = (idx >> 16) & 0xff;
4638 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4639 * value is not known when the table is emitted.
4642 fixup_cattrs (MonoDynamicImage *assembly)
4644 MonoDynamicTable *table;
4646 guint32 type, i, idx, token;
4649 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4651 for (i = 0; i < table->rows; ++i) {
4652 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4654 type = values [MONO_CUSTOM_ATTR_TYPE];
4655 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4656 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4657 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4658 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4661 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4662 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4663 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4664 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4665 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4666 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4667 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4668 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4675 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4677 MonoDynamicTable *table;
4680 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4682 alloc_table (table, table->rows);
4683 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4684 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4685 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4686 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4687 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4692 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4694 MonoDynamicTable *table;
4698 char *b = blob_size;
4700 guint32 idx, offset;
4702 if (rsrc->filename) {
4703 name = mono_string_to_utf8 (rsrc->filename);
4704 sname = g_path_get_basename (name);
4706 table = &assembly->tables [MONO_TABLE_FILE];
4708 alloc_table (table, table->rows);
4709 values = table->values + table->next_idx * MONO_FILE_SIZE;
4710 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4711 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4714 mono_sha1_get_digest_from_file (name, hash);
4715 mono_metadata_encode_value (20, b, &b);
4716 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4717 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4719 idx = table->next_idx++;
4721 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4727 data = mono_array_addr (rsrc->data, char, 0);
4728 len = mono_array_length (rsrc->data);
4734 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4735 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4736 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4737 mono_image_add_stream_data (&assembly->resources, data, len);
4741 * The entry should be emitted into the MANIFESTRESOURCE table of
4742 * the main module, but that needs to reference the FILE table
4743 * which isn't emitted yet.
4750 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4754 set_version_from_string (MonoString *version, guint32 *values)
4756 gchar *ver, *p, *str;
4759 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4760 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4761 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4762 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4765 ver = str = mono_string_to_utf8 (version);
4766 for (i = 0; i < 4; ++i) {
4767 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4773 /* handle Revision and Build */
4783 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4787 char *b = blob_size;
4792 len = mono_array_length (pkey);
4793 mono_metadata_encode_value (len, b, &b);
4794 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4795 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4797 assembly->public_key = (guint8 *)g_malloc (len);
4798 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4799 assembly->public_key_len = len;
4801 /* Special case: check for ECMA key (16 bytes) */
4802 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4803 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4804 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4805 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4806 /* minimum key size (in 2.0) is 384 bits */
4807 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4809 /* FIXME - verifier */
4810 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4811 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4813 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4819 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4821 MonoDynamicTable *table;
4822 MonoDynamicImage *assembly;
4823 MonoReflectionAssemblyBuilder *assemblyb;
4827 guint32 module_index;
4829 assemblyb = moduleb->assemblyb;
4830 assembly = moduleb->dynamic_image;
4831 domain = mono_object_domain (assemblyb);
4833 /* Emit ASSEMBLY table */
4834 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4835 alloc_table (table, 1);
4836 values = table->values + MONO_ASSEMBLY_SIZE;
4837 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4838 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4839 if (assemblyb->culture) {
4840 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4842 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4844 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4845 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4846 set_version_from_string (assemblyb->version, values);
4848 /* Emit FILE + EXPORTED_TYPE table */
4850 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4852 MonoReflectionModuleBuilder *file_module =
4853 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4854 if (file_module != moduleb) {
4855 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4857 if (file_module->types) {
4858 for (j = 0; j < file_module->num_types; ++j) {
4859 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4860 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4865 if (assemblyb->loaded_modules) {
4866 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4867 MonoReflectionModule *file_module =
4868 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4869 mono_image_fill_file_table (domain, file_module, assembly);
4871 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4874 if (assemblyb->type_forwarders)
4875 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4877 /* Emit MANIFESTRESOURCE table */
4879 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4881 MonoReflectionModuleBuilder *file_module =
4882 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4883 /* The table for the main module is emitted later */
4884 if (file_module != moduleb) {
4886 if (file_module->resources) {
4887 int len = mono_array_length (file_module->resources);
4888 for (j = 0; j < len; ++j) {
4889 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4890 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4897 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4900 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4901 * for the modulebuilder @moduleb.
4902 * At the end of the process, method and field tokens are fixed up and the
4903 * on-disk compressed metadata representation is created.
4904 * Return TRUE on success, or FALSE on failure and sets @error
4907 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4909 MonoDynamicTable *table;
4910 MonoDynamicImage *assembly;
4911 MonoReflectionAssemblyBuilder *assemblyb;
4917 mono_error_init (error);
4919 assemblyb = moduleb->assemblyb;
4920 assembly = moduleb->dynamic_image;
4921 domain = mono_object_domain (assemblyb);
4923 if (assembly->text_rva)
4926 assembly->text_rva = START_TEXT_RVA;
4928 if (moduleb->is_main) {
4929 mono_image_emit_manifest (moduleb);
4932 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4933 table->rows = 1; /* .<Module> */
4935 alloc_table (table, table->rows);
4937 * Set the first entry.
4939 values = table->values + table->columns;
4940 values [MONO_TYPEDEF_FLAGS] = 0;
4941 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4942 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4943 values [MONO_TYPEDEF_EXTENDS] = 0;
4944 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4945 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4948 * handle global methods
4949 * FIXME: test what to do when global methods are defined in multiple modules.
4951 if (moduleb->global_methods) {
4952 table = &assembly->tables [MONO_TABLE_METHOD];
4953 table->rows += mono_array_length (moduleb->global_methods);
4954 alloc_table (table, table->rows);
4955 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4956 mono_image_get_method_info (
4957 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4959 if (moduleb->global_fields) {
4960 table = &assembly->tables [MONO_TABLE_FIELD];
4961 table->rows += mono_array_length (moduleb->global_fields);
4962 alloc_table (table, table->rows);
4963 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4964 mono_image_get_field_info (
4965 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4968 table = &assembly->tables [MONO_TABLE_MODULE];
4969 alloc_table (table, 1);
4970 mono_image_fill_module_table (domain, moduleb, assembly);
4972 /* Collect all types into a list sorted by their table_idx */
4973 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4976 for (i = 0; i < moduleb->num_types; ++i) {
4977 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4978 collect_types (&types, type);
4981 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4982 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4983 table->rows += mono_ptr_array_size (types);
4984 alloc_table (table, table->rows);
4987 * Emit type names + namespaces at one place inside the string heap,
4988 * so load_class_names () needs to touch fewer pages.
4990 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4991 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4992 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4994 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4995 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4996 string_heap_insert_mstring (&assembly->sheap, tb->name);
4999 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5000 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5001 mono_image_get_type_info (domain, type, assembly);
5005 * table->rows is already set above and in mono_image_fill_module_table.
5007 /* add all the custom attributes at the end, once all the indexes are stable */
5008 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5011 /* CAS assembly permissions */
5012 if (assemblyb->permissions_minimum)
5013 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5014 if (assemblyb->permissions_optional)
5015 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5016 if (assemblyb->permissions_refused)
5017 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5019 if (!module_add_cattrs (assembly, moduleb, error))
5023 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5025 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5026 * the final tokens and don't need another fixup pass. */
5028 if (moduleb->global_methods) {
5029 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5030 MonoReflectionMethodBuilder *mb = mono_array_get (
5031 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5032 if (!mono_image_add_methodimpl (assembly, mb, error))
5037 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5038 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5039 if (type->methods) {
5040 for (j = 0; j < type->num_methods; ++j) {
5041 MonoReflectionMethodBuilder *mb = mono_array_get (
5042 type->methods, MonoReflectionMethodBuilder*, j);
5044 if (!mono_image_add_methodimpl (assembly, mb, error))
5050 fixup_cattrs (assembly);
5053 mono_ptr_array_destroy (types);
5056 return mono_error_ok (error);
5059 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5062 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5064 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5067 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5071 guint32 import_lookup_table;
5075 guint32 import_address_table_rva;
5083 #ifndef DISABLE_REFLECTION_EMIT
5086 * mono_image_insert_string:
5087 * @module: module builder object
5090 * Insert @str into the user string stream of @module.
5093 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5095 MonoDynamicImage *assembly;
5100 if (!module->dynamic_image)
5101 mono_image_module_basic_init (module);
5103 assembly = module->dynamic_image;
5105 if (assembly->save) {
5106 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5107 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5108 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5110 char *swapped = g_malloc (2 * mono_string_length (str));
5111 const char *p = (const char*)mono_string_chars (str);
5113 swap_with_size (swapped, p, 2, mono_string_length (str));
5114 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5118 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5120 mono_image_add_stream_data (&assembly->us, "", 1);
5122 idx = assembly->us.index ++;
5125 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5127 return MONO_TOKEN_STRING | idx;
5131 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5135 MonoMethodSignature *sig;
5137 mono_error_init (error);
5139 klass = obj->vtable->klass;
5140 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5141 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5142 MonoMethodSignature *old;
5143 guint32 sig_token, parent;
5146 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5148 nargs = mono_array_length (opt_param_types);
5149 old = mono_method_signature (method);
5150 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5152 sig->hasthis = old->hasthis;
5153 sig->explicit_this = old->explicit_this;
5154 sig->call_convention = old->call_convention;
5155 sig->generic_param_count = old->generic_param_count;
5156 sig->param_count = old->param_count + nargs;
5157 sig->sentinelpos = old->param_count;
5158 sig->ret = old->ret;
5160 for (i = 0; i < old->param_count; i++)
5161 sig->params [i] = old->params [i];
5163 for (i = 0; i < nargs; i++) {
5164 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5165 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5168 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5169 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5170 parent >>= MONO_TYPEDEFORREF_BITS;
5172 parent <<= MONO_MEMBERREF_PARENT_BITS;
5173 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5175 sig_token = method_encode_signature (assembly, sig);
5176 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5177 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5178 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5179 ReflectionMethodBuilder rmb;
5180 guint32 parent, sig_token;
5181 int nopt_args, nparams, ngparams, i;
5183 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5186 rmb.opt_types = opt_param_types;
5187 nopt_args = mono_array_length (opt_param_types);
5189 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5190 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5191 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5193 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5194 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5195 sig->call_convention = rmb.call_conv;
5196 sig->generic_param_count = ngparams;
5197 sig->param_count = nparams + nopt_args;
5198 sig->sentinelpos = nparams;
5199 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5201 for (i = 0; i < nparams; i++) {
5202 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5203 sig->params [i] = mono_reflection_type_get_handle (rt);
5206 for (i = 0; i < nopt_args; i++) {
5207 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5208 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5211 sig_token = method_builder_encode_signature (assembly, &rmb);
5213 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5214 if (!mono_error_ok (error))
5216 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5218 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5219 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5221 char *name = mono_string_to_utf8 (rmb.name);
5222 token = mono_image_get_varargs_method_token (
5223 assembly, parent, name, sig_token);
5226 g_error ("requested method token for %s\n", klass->name);
5229 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5230 register_dyn_token (assembly, token, obj);
5233 g_assert (!mono_error_ok (error));
5238 * mono_image_create_token:
5239 * @assembly: a dynamic assembly
5241 * @register_token: Whenever to register the token in the assembly->tokens hash.
5243 * Get a token to insert in the IL code stream for the given MemberInfo.
5244 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5245 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5249 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5250 gboolean create_open_instance, gboolean register_token,
5256 mono_error_init (error);
5258 klass = obj->vtable->klass;
5260 /* Check for user defined reflection objects */
5261 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5262 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5263 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5267 if (strcmp (klass->name, "MethodBuilder") == 0) {
5268 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5269 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5271 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5272 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5274 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5275 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5276 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5277 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5278 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5280 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5281 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5283 token = mono_image_get_ctorbuilder_token (assembly, mb);
5284 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5285 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5286 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5287 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5288 if (tb->generic_params) {
5289 token = mono_image_get_generic_field_token (assembly, fb);
5291 if (tb->module->dynamic_image == assembly) {
5292 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5294 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5297 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5298 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5299 if (create_open_instance && tb->generic_params) {
5301 init_type_builder_generics (obj);
5302 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5303 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5304 token = mono_metadata_token_from_dor (token);
5305 } else if (tb->module->dynamic_image == assembly) {
5306 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5309 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5310 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5312 } else if (strcmp (klass->name, "MonoType") == 0) {
5313 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5314 MonoClass *mc = mono_class_from_mono_type (type);
5315 token = mono_metadata_token_from_dor (
5316 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5317 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5318 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5319 token = mono_metadata_token_from_dor (
5320 mono_image_typedef_or_ref (assembly, type));
5321 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5322 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5323 token = mono_metadata_token_from_dor (
5324 mono_image_typedef_or_ref (assembly, type));
5325 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5326 strcmp (klass->name, "MonoMethod") == 0 ||
5327 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5328 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5329 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5330 if (m->method->is_inflated) {
5331 if (create_open_instance)
5332 token = mono_image_get_methodspec_token (assembly, m->method);
5334 token = mono_image_get_inflated_method_token (assembly, m->method);
5335 } else if ((m->method->klass->image == &assembly->image) &&
5336 !m->method->klass->generic_class) {
5337 static guint32 method_table_idx = 0xffffff;
5338 if (m->method->klass->wastypebuilder) {
5339 /* we use the same token as the one that was assigned
5340 * to the Methodbuilder.
5341 * FIXME: do the equivalent for Fields.
5343 token = m->method->token;
5346 * Each token should have a unique index, but the indexes are
5347 * assigned by managed code, so we don't know about them. An
5348 * easy solution is to count backwards...
5350 method_table_idx --;
5351 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5354 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5356 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5357 } else if (strcmp (klass->name, "MonoField") == 0) {
5358 MonoReflectionField *f = (MonoReflectionField *)obj;
5359 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5360 static guint32 field_table_idx = 0xffffff;
5362 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5364 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5366 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5367 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5368 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5369 token = mono_image_get_array_token (assembly, m);
5370 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5371 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5372 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5373 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5374 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5375 token = mono_metadata_token_from_dor (
5376 mono_image_typedef_or_ref (assembly, type));
5377 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5378 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5379 token = mono_image_get_field_on_inst_token (assembly, f);
5380 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5381 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5382 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5383 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5384 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5385 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5386 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5387 MonoReflectionType *type = (MonoReflectionType *)obj;
5388 token = mono_metadata_token_from_dor (
5389 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5391 g_error ("requested token for %s\n", klass->name);
5395 mono_image_register_token (assembly, token, obj);
5401 * mono_image_register_token:
5403 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5404 * the Module.ResolveXXXToken () methods to work.
5407 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5411 dynamic_image_lock (assembly);
5412 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5414 /* There could be multiple MethodInfo objects with the same token */
5415 //g_assert (prev == obj);
5417 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5419 dynamic_image_unlock (assembly);
5422 static MonoDynamicImage*
5423 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5425 static const guchar entrycode [16] = {0xff, 0x25, 0};
5426 MonoDynamicImage *image;
5429 const char *version;
5431 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5432 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5434 version = mono_get_runtime_info ()->runtime_version;
5437 /* The MonoGHashTable's need GC tracking */
5438 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5440 image = g_new0 (MonoDynamicImage, 1);
5443 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5445 /*g_print ("created image %p\n", image);*/
5446 /* keep in sync with image.c */
5447 image->image.name = assembly_name;
5448 image->image.assembly_name = image->image.name; /* they may be different */
5449 image->image.module_name = module_name;
5450 image->image.version = g_strdup (version);
5451 image->image.md_version_major = 1;
5452 image->image.md_version_minor = 1;
5453 image->image.dynamic = TRUE;
5455 image->image.references = g_new0 (MonoAssembly*, 1);
5456 image->image.references [0] = NULL;
5458 mono_image_init (&image->image);
5460 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");
5461 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5462 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5463 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5464 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5465 image->handleref = g_hash_table_new (NULL, NULL);
5466 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");
5467 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5468 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");
5469 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");
5470 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5471 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5472 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5473 image->gen_params = g_ptr_array_new ();
5474 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5476 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5477 string_heap_init (&image->sheap);
5478 mono_image_add_stream_data (&image->us, "", 1);
5479 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5480 /* import tables... */
5481 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5482 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5483 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5484 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5485 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5486 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5487 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5488 stream_data_align (&image->code);
5490 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5492 for (i=0; i < MONO_TABLE_NUM; ++i) {
5493 image->tables [i].next_idx = 1;
5494 image->tables [i].columns = table_sizes [i];
5497 image->image.assembly = (MonoAssembly*)assembly;
5498 image->run = assembly->run;
5499 image->save = assembly->save;
5500 image->pe_kind = 0x1; /* ILOnly */
5501 image->machine = 0x14c; /* I386 */
5503 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5505 dynamic_images_lock ();
5507 if (!dynamic_images)
5508 dynamic_images = g_ptr_array_new ();
5510 g_ptr_array_add (dynamic_images, image);
5512 dynamic_images_unlock ();
5519 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5525 release_hashtable (MonoGHashTable **hash)
5528 mono_g_hash_table_destroy (*hash);
5534 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5536 release_hashtable (&image->token_fixups);
5537 release_hashtable (&image->handleref_managed);
5538 release_hashtable (&image->tokens);
5539 release_hashtable (&image->remapped_tokens);
5540 release_hashtable (&image->generic_def_objects);
5541 release_hashtable (&image->methodspec);
5544 // Free dynamic image pass one: Free resources but not image itself
5546 mono_dynamic_image_free (MonoDynamicImage *image)
5548 MonoDynamicImage *di = image;
5553 mono_g_hash_table_destroy (di->methodspec);
5555 g_hash_table_destroy (di->typespec);
5557 g_hash_table_destroy (di->typeref);
5559 g_hash_table_destroy (di->handleref);
5560 if (di->handleref_managed)
5561 mono_g_hash_table_destroy (di->handleref_managed);
5563 mono_g_hash_table_destroy (di->tokens);
5564 if (di->remapped_tokens)
5565 mono_g_hash_table_destroy (di->remapped_tokens);
5566 if (di->generic_def_objects)
5567 mono_g_hash_table_destroy (di->generic_def_objects);
5568 if (di->blob_cache) {
5569 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5570 g_hash_table_destroy (di->blob_cache);
5572 if (di->standalonesig_cache)
5573 g_hash_table_destroy (di->standalonesig_cache);
5574 for (list = di->array_methods; list; list = list->next) {
5575 ArrayMethod *am = (ArrayMethod *)list->data;
5580 g_list_free (di->array_methods);
5581 if (di->gen_params) {
5582 for (i = 0; i < di->gen_params->len; i++) {
5583 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5584 mono_gc_deregister_root ((char*) &entry->gparam);
5587 g_ptr_array_free (di->gen_params, TRUE);
5589 if (di->token_fixups)
5590 mono_g_hash_table_destroy (di->token_fixups);
5591 if (di->method_to_table_idx)
5592 g_hash_table_destroy (di->method_to_table_idx);
5593 if (di->field_to_table_idx)
5594 g_hash_table_destroy (di->field_to_table_idx);
5595 if (di->method_aux_hash)
5596 g_hash_table_destroy (di->method_aux_hash);
5597 if (di->vararg_aux_hash)
5598 g_hash_table_destroy (di->vararg_aux_hash);
5599 g_free (di->strong_name);
5600 g_free (di->win32_res);
5602 g_free (di->public_key);
5604 /*g_print ("string heap destroy for image %p\n", di);*/
5605 mono_dynamic_stream_reset (&di->sheap);
5606 mono_dynamic_stream_reset (&di->code);
5607 mono_dynamic_stream_reset (&di->resources);
5608 mono_dynamic_stream_reset (&di->us);
5609 mono_dynamic_stream_reset (&di->blob);
5610 mono_dynamic_stream_reset (&di->tstream);
5611 mono_dynamic_stream_reset (&di->guid);
5612 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5613 g_free (di->tables [i].values);
5616 dynamic_images_lock ();
5619 g_ptr_array_remove (dynamic_images, di);
5621 dynamic_images_unlock ();
5624 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5626 mono_dynamic_image_free_image (MonoDynamicImage *image)
5628 /* See create_dynamic_mono_image () */
5630 /* Allocated using GC_MALLOC */
5636 #ifndef DISABLE_REFLECTION_EMIT
5639 * mono_image_basic_init:
5640 * @assembly: an assembly builder object
5642 * Create the MonoImage that represents the assembly builder and setup some
5643 * of the helper hash table and the basic metadata streams.
5646 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5648 MonoDynamicAssembly *assembly;
5649 MonoDynamicImage *image;
5650 MonoDomain *domain = mono_object_domain (assemblyb);
5652 if (assemblyb->dynamic_assembly)
5656 /* assembly->assembly.image might be GC allocated */
5657 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5659 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5662 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5664 assembly->assembly.ref_count = 1;
5665 assembly->assembly.dynamic = TRUE;
5666 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5667 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5668 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5669 if (assemblyb->culture)
5670 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5672 assembly->assembly.aname.culture = g_strdup ("");
5674 if (assemblyb->version) {
5675 char *vstr = mono_string_to_utf8 (assemblyb->version);
5676 char **version = g_strsplit (vstr, ".", 4);
5677 char **parts = version;
5678 assembly->assembly.aname.major = atoi (*parts++);
5679 assembly->assembly.aname.minor = atoi (*parts++);
5680 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5681 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5683 g_strfreev (version);
5686 assembly->assembly.aname.major = 0;
5687 assembly->assembly.aname.minor = 0;
5688 assembly->assembly.aname.build = 0;
5689 assembly->assembly.aname.revision = 0;
5692 assembly->run = assemblyb->access != 2;
5693 assembly->save = assemblyb->access != 1;
5694 assembly->domain = domain;
5696 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5697 image->initial_image = TRUE;
5698 assembly->assembly.aname.name = image->image.name;
5699 assembly->assembly.image = &image->image;
5700 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5701 /* -1 to correct for the trailing NULL byte */
5702 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5703 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5705 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5708 mono_domain_assemblies_lock (domain);
5709 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5710 mono_domain_assemblies_unlock (domain);
5712 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5714 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5716 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5719 #endif /* !DISABLE_REFLECTION_EMIT */
5721 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5724 calc_section_size (MonoDynamicImage *assembly)
5728 /* alignment constraints */
5729 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5730 g_assert ((assembly->code.index % 4) == 0);
5731 assembly->meta_size += 3;
5732 assembly->meta_size &= ~3;
5733 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5734 g_assert ((assembly->resources.index % 4) == 0);
5736 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5737 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5740 if (assembly->win32_res) {
5741 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5743 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5744 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5748 assembly->sections [MONO_SECTION_RELOC].size = 12;
5749 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5759 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5763 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5765 ResTreeNode *t1 = (ResTreeNode*)a;
5766 ResTreeNode *t2 = (ResTreeNode*)b;
5768 return t1->id - t2->id;
5772 * resource_tree_create:
5774 * Organize the resources into a resource tree.
5776 static ResTreeNode *
5777 resource_tree_create (MonoArray *win32_resources)
5779 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5783 tree = g_new0 (ResTreeNode, 1);
5785 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5786 MonoReflectionWin32Resource *win32_res =
5787 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5791 /* FIXME: BUG: this stores managed references in unmanaged memory */
5792 lang_node = g_new0 (ResTreeNode, 1);
5793 lang_node->id = win32_res->lang_id;
5794 lang_node->win32_res = win32_res;
5796 /* Create type node if neccesary */
5798 for (l = tree->children; l; l = l->next)
5799 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5800 type_node = (ResTreeNode*)l->data;
5805 type_node = g_new0 (ResTreeNode, 1);
5806 type_node->id = win32_res->res_type;
5809 * The resource types have to be sorted otherwise
5810 * Windows Explorer can't display the version information.
5812 tree->children = g_slist_insert_sorted (tree->children,
5813 type_node, resource_tree_compare_by_id);
5816 /* Create res node if neccesary */
5818 for (l = type_node->children; l; l = l->next)
5819 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5820 res_node = (ResTreeNode*)l->data;
5825 res_node = g_new0 (ResTreeNode, 1);
5826 res_node->id = win32_res->res_id;
5827 type_node->children = g_slist_append (type_node->children, res_node);
5830 res_node->children = g_slist_append (res_node->children, lang_node);
5837 * resource_tree_encode:
5839 * Encode the resource tree into the format used in the PE file.
5842 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5845 MonoPEResourceDir dir;
5846 MonoPEResourceDirEntry dir_entry;
5847 MonoPEResourceDataEntry data_entry;
5849 guint32 res_id_entries;
5852 * For the format of the resource directory, see the article
5853 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5857 memset (&dir, 0, sizeof (dir));
5858 memset (&dir_entry, 0, sizeof (dir_entry));
5859 memset (&data_entry, 0, sizeof (data_entry));
5861 g_assert (sizeof (dir) == 16);
5862 g_assert (sizeof (dir_entry) == 8);
5863 g_assert (sizeof (data_entry) == 16);
5865 node->offset = p - begin;
5867 /* IMAGE_RESOURCE_DIRECTORY */
5868 res_id_entries = g_slist_length (node->children);
5869 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5871 memcpy (p, &dir, sizeof (dir));
5874 /* Reserve space for entries */
5876 p += sizeof (dir_entry) * res_id_entries;
5878 /* Write children */
5879 for (l = node->children; l; l = l->next) {
5880 ResTreeNode *child = (ResTreeNode*)l->data;
5882 if (child->win32_res) {
5885 child->offset = p - begin;
5887 /* IMAGE_RESOURCE_DATA_ENTRY */
5888 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5889 size = mono_array_length (child->win32_res->res_data);
5890 data_entry.rde_size = GUINT32_TO_LE (size);
5892 memcpy (p, &data_entry, sizeof (data_entry));
5893 p += sizeof (data_entry);
5895 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5898 resource_tree_encode (child, begin, p, &p);
5902 /* IMAGE_RESOURCE_ENTRY */
5903 for (l = node->children; l; l = l->next) {
5904 ResTreeNode *child = (ResTreeNode*)l->data;
5906 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5907 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5909 memcpy (entries, &dir_entry, sizeof (dir_entry));
5910 entries += sizeof (dir_entry);
5917 resource_tree_free (ResTreeNode * node)
5920 for (list = node->children; list; list = list->next)
5921 resource_tree_free ((ResTreeNode*)list->data);
5922 g_slist_free(node->children);
5927 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5932 MonoReflectionWin32Resource *win32_res;
5935 if (!assemblyb->win32_resources)
5939 * Resources are stored in a three level tree inside the PE file.
5940 * - level one contains a node for each type of resource
5941 * - level two contains a node for each resource
5942 * - level three contains a node for each instance of a resource for a
5943 * specific language.
5946 tree = resource_tree_create (assemblyb->win32_resources);
5948 /* Estimate the size of the encoded tree */
5950 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5951 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5952 size += mono_array_length (win32_res->res_data);
5954 /* Directory structure */
5955 size += mono_array_length (assemblyb->win32_resources) * 256;
5956 p = buf = (char *)g_malloc (size);
5958 resource_tree_encode (tree, p, p, &p);
5960 g_assert (p - buf <= size);
5962 assembly->win32_res = (char *)g_malloc (p - buf);
5963 assembly->win32_res_size = p - buf;
5964 memcpy (assembly->win32_res, buf, p - buf);
5967 resource_tree_free (tree);
5971 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5973 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5976 p += sizeof (MonoPEResourceDir);
5977 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5978 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5979 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5980 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5981 fixup_resource_directory (res_section, child, rva);
5983 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5984 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5987 p += sizeof (MonoPEResourceDirEntry);
5992 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5995 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5996 g_error ("WriteFile returned %d\n", GetLastError ());
6000 * mono_image_create_pefile:
6001 * @mb: a module builder object
6003 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6004 * assembly->pefile where it can be easily retrieved later in chunks.
6007 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6010 MonoMSDOSHeader *msdos;
6011 MonoDotNetHeader *header;
6012 MonoSectionTable *section;
6013 MonoCLIHeader *cli_header;
6014 guint32 size, image_size, virtual_base, text_offset;
6015 guint32 header_start, section_start, file_offset, virtual_offset;
6016 MonoDynamicImage *assembly;
6017 MonoReflectionAssemblyBuilder *assemblyb;
6018 MonoDynamicStream pefile_stream = {0};
6019 MonoDynamicStream *pefile = &pefile_stream;
6021 guint32 *rva, value;
6023 static const unsigned char msheader[] = {
6024 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6025 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6026 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6028 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6029 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6030 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6031 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6034 assemblyb = mb->assemblyb;
6036 mono_image_basic_init (assemblyb);
6037 assembly = mb->dynamic_image;
6039 assembly->pe_kind = assemblyb->pe_kind;
6040 assembly->machine = assemblyb->machine;
6041 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6042 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6044 if (!mono_image_build_metadata (mb, &error))
6045 mono_error_raise_exception (&error); /* FIXME don't raise here */
6048 if (mb->is_main && assemblyb->resources) {
6049 int len = mono_array_length (assemblyb->resources);
6050 for (i = 0; i < len; ++i)
6051 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6054 if (mb->resources) {
6055 int len = mono_array_length (mb->resources);
6056 for (i = 0; i < len; ++i)
6057 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6060 build_compressed_metadata (assembly);
6063 assembly_add_win32_resources (assembly, assemblyb);
6065 nsections = calc_section_size (assembly);
6067 /* The DOS header and stub */
6068 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6069 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6071 /* the dotnet header */
6072 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6074 /* the section tables */
6075 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6077 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6078 virtual_offset = VIRT_ALIGN;
6081 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6082 if (!assembly->sections [i].size)
6085 file_offset += FILE_ALIGN - 1;
6086 file_offset &= ~(FILE_ALIGN - 1);
6087 virtual_offset += VIRT_ALIGN - 1;
6088 virtual_offset &= ~(VIRT_ALIGN - 1);
6090 assembly->sections [i].offset = file_offset;
6091 assembly->sections [i].rva = virtual_offset;
6093 file_offset += assembly->sections [i].size;
6094 virtual_offset += assembly->sections [i].size;
6095 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6098 file_offset += FILE_ALIGN - 1;
6099 file_offset &= ~(FILE_ALIGN - 1);
6101 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6103 /* back-patch info */
6104 msdos = (MonoMSDOSHeader*)pefile->data;
6105 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6107 header = (MonoDotNetHeader*)(pefile->data + header_start);
6108 header->pesig [0] = 'P';
6109 header->pesig [1] = 'E';
6111 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6112 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6113 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6114 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6115 if (assemblyb->pekind == 1) {
6117 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6120 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6123 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6125 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6126 header->pe.pe_major = 6;
6127 header->pe.pe_minor = 0;
6128 size = assembly->sections [MONO_SECTION_TEXT].size;
6129 size += FILE_ALIGN - 1;
6130 size &= ~(FILE_ALIGN - 1);
6131 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6132 size = assembly->sections [MONO_SECTION_RSRC].size;
6133 size += FILE_ALIGN - 1;
6134 size &= ~(FILE_ALIGN - 1);
6135 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6136 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6137 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6138 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6139 /* pe_rva_entry_point always at the beginning of the text section */
6140 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6142 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6143 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6144 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6145 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6146 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6147 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6148 size = section_start;
6149 size += FILE_ALIGN - 1;
6150 size &= ~(FILE_ALIGN - 1);
6151 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6153 size += VIRT_ALIGN - 1;
6154 size &= ~(VIRT_ALIGN - 1);
6155 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6158 // Translate the PEFileKind value to the value expected by the Windows loader
6164 // PEFileKinds.Dll == 1
6165 // PEFileKinds.ConsoleApplication == 2
6166 // PEFileKinds.WindowApplication == 3
6169 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6170 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6172 if (assemblyb->pekind == 3)
6177 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6179 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6180 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6181 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6182 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6183 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6184 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6186 /* fill data directory entries */
6188 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6189 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6191 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6192 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6194 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6195 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6196 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6197 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6198 /* patch entrypoint name */
6199 if (assemblyb->pekind == 1)
6200 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6202 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6203 /* patch imported function RVA name */
6204 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6205 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6207 /* the import table */
6208 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6209 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6210 /* patch imported dll RVA name and other entries in the dir */
6211 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6212 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6213 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6214 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6215 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6216 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6218 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6219 value = (assembly->text_rva + assembly->imp_names_offset);
6220 *p++ = (value) & 0xff;
6221 *p++ = (value >> 8) & (0xff);
6222 *p++ = (value >> 16) & (0xff);
6223 *p++ = (value >> 24) & (0xff);
6225 /* the CLI header info */
6226 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6227 cli_header->ch_size = GUINT32_FROM_LE (72);
6228 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6229 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6230 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6231 if (assemblyb->entry_point) {
6232 guint32 table_idx = 0;
6233 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6234 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6235 table_idx = methodb->table_idx;
6237 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6239 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6241 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6243 /* The embedded managed resources */
6244 text_offset = assembly->text_rva + assembly->code.index;
6245 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6246 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6247 text_offset += assembly->resources.index;
6248 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6249 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6250 text_offset += assembly->meta_size;
6251 if (assembly->strong_name_size) {
6252 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6253 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6254 text_offset += assembly->strong_name_size;
6257 /* write the section tables and section content */
6258 section = (MonoSectionTable*)(pefile->data + section_start);
6259 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6260 static const char section_names [][7] = {
6261 ".text", ".rsrc", ".reloc"
6263 if (!assembly->sections [i].size)
6265 strcpy (section->st_name, section_names [i]);
6266 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6267 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6268 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6269 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6270 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6271 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6272 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6276 checked_write_file (file, pefile->data, pefile->index);
6278 mono_dynamic_stream_reset (pefile);
6280 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6281 if (!assembly->sections [i].size)
6284 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6285 g_error ("SetFilePointer returned %d\n", GetLastError ());
6288 case MONO_SECTION_TEXT:
6289 /* patch entry point */
6290 p = (guchar*)(assembly->code.data + 2);
6291 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6292 *p++ = (value) & 0xff;
6293 *p++ = (value >> 8) & 0xff;
6294 *p++ = (value >> 16) & 0xff;
6295 *p++ = (value >> 24) & 0xff;
6297 checked_write_file (file, assembly->code.data, assembly->code.index);
6298 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6299 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6300 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6303 g_free (assembly->image.raw_metadata);
6305 case MONO_SECTION_RELOC: {
6309 guint16 type_and_offset;
6313 g_assert (sizeof (reloc) == 12);
6315 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6316 reloc.block_size = GUINT32_FROM_LE (12);
6319 * the entrypoint is always at the start of the text section
6320 * 3 is IMAGE_REL_BASED_HIGHLOW
6321 * 2 is patch_size_rva - text_rva
6323 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6326 checked_write_file (file, &reloc, sizeof (reloc));
6330 case MONO_SECTION_RSRC:
6331 if (assembly->win32_res) {
6333 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6334 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6335 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6339 g_assert_not_reached ();
6343 /* check that the file is properly padded */
6344 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6345 g_error ("SetFilePointer returned %d\n", GetLastError ());
6346 if (! SetEndOfFile (file))
6347 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6349 mono_dynamic_stream_reset (&assembly->code);
6350 mono_dynamic_stream_reset (&assembly->us);
6351 mono_dynamic_stream_reset (&assembly->blob);
6352 mono_dynamic_stream_reset (&assembly->guid);
6353 mono_dynamic_stream_reset (&assembly->sheap);
6355 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6356 g_hash_table_destroy (assembly->blob_cache);
6357 assembly->blob_cache = NULL;
6360 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6363 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6365 g_assert_not_reached ();
6368 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6370 #ifndef DISABLE_REFLECTION_EMIT
6372 MonoReflectionModule *
6373 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6377 MonoImageOpenStatus status;
6378 MonoDynamicAssembly *assembly;
6379 guint32 module_count;
6380 MonoImage **new_modules;
6381 gboolean *new_modules_loaded;
6383 name = mono_string_to_utf8 (fileName);
6385 image = mono_image_open (name, &status);
6388 if (status == MONO_IMAGE_ERROR_ERRNO)
6389 exc = mono_get_exception_file_not_found (fileName);
6391 exc = mono_get_exception_bad_image_format (name);
6393 mono_raise_exception (exc);
6398 assembly = ab->dynamic_assembly;
6399 image->assembly = (MonoAssembly*)assembly;
6401 module_count = image->assembly->image->module_count;
6402 new_modules = g_new0 (MonoImage *, module_count + 1);
6403 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6405 if (image->assembly->image->modules)
6406 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6407 if (image->assembly->image->modules_loaded)
6408 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6409 new_modules [module_count] = image;
6410 new_modules_loaded [module_count] = TRUE;
6411 mono_image_addref (image);
6413 g_free (image->assembly->image->modules);
6414 image->assembly->image->modules = new_modules;
6415 image->assembly->image->modules_loaded = new_modules_loaded;
6416 image->assembly->image->module_count ++;
6418 mono_assembly_load_references (image, &status);
6420 mono_image_close (image);
6421 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6424 return mono_module_get_object (mono_domain_get (), image);
6427 #endif /* DISABLE_REFLECTION_EMIT */
6430 * We need to return always the same object for MethodInfo, FieldInfo etc..
6431 * but we need to consider the reflected type.
6432 * type uses a different hash, since it uses custom hash/equal functions.
6437 MonoClass *refclass;
6441 reflected_equal (gconstpointer a, gconstpointer b) {
6442 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6443 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6445 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6449 reflected_hash (gconstpointer a) {
6450 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6451 return mono_aligned_addr_hash (ea->item);
6454 #define CHECK_OBJECT(t,p,k) \
6460 mono_domain_lock (domain); \
6461 if (!domain->refobject_hash) \
6462 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"); \
6463 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6464 mono_domain_unlock (domain); \
6467 mono_domain_unlock (domain); \
6470 #ifdef HAVE_BOEHM_GC
6471 /* ReflectedEntry doesn't need to be GC tracked */
6472 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6473 #define FREE_REFENTRY(entry) g_free ((entry))
6474 #define REFENTRY_REQUIRES_CLEANUP
6476 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6478 #define FREE_REFENTRY(entry)
6481 #define CACHE_OBJECT(t,p,o,k) \
6484 ReflectedEntry pe; \
6486 pe.refclass = (k); \
6487 mono_domain_lock (domain); \
6488 if (!domain->refobject_hash) \
6489 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"); \
6490 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6492 ReflectedEntry *e = ALLOC_REFENTRY; \
6494 e->refclass = (k); \
6495 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6498 mono_domain_unlock (domain); \
6503 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6505 mono_domain_lock (domain);
6506 if (domain->refobject_hash) {
6508 gpointer orig_pe, orig_value;
6511 pe.refclass = klass;
6512 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6513 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6514 FREE_REFENTRY (orig_pe);
6517 mono_domain_unlock (domain);
6520 #ifdef REFENTRY_REQUIRES_CLEANUP
6522 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6524 FREE_REFENTRY (key);
6529 mono_reflection_cleanup_domain (MonoDomain *domain)
6531 if (domain->refobject_hash) {
6532 /*let's avoid scanning the whole hashtable if not needed*/
6533 #ifdef REFENTRY_REQUIRES_CLEANUP
6534 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6536 mono_g_hash_table_destroy (domain->refobject_hash);
6537 domain->refobject_hash = NULL;
6541 #ifndef DISABLE_REFLECTION_EMIT
6543 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6545 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6549 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6551 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6555 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6557 MonoDynamicImage *image = moduleb->dynamic_image;
6558 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6562 MonoImage **new_modules;
6564 char *name, *fqname;
6566 * FIXME: we already created an image in mono_image_basic_init (), but
6567 * we don't know which module it belongs to, since that is only
6568 * determined at assembly save time.
6570 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6571 name = mono_string_to_utf8 (ab->name);
6572 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6573 if (!mono_error_ok (&error)) {
6575 mono_error_raise_exception (&error);
6577 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6579 moduleb->module.image = &image->image;
6580 moduleb->dynamic_image = image;
6581 register_module (mono_object_domain (moduleb), moduleb, image);
6583 /* register the module with the assembly */
6584 ass = ab->dynamic_assembly->assembly.image;
6585 module_count = ass->module_count;
6586 new_modules = g_new0 (MonoImage *, module_count + 1);
6589 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6590 new_modules [module_count] = &image->image;
6591 mono_image_addref (&image->image);
6593 g_free (ass->modules);
6594 ass->modules = new_modules;
6595 ass->module_count ++;
6600 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6602 MonoDynamicImage *image = moduleb->dynamic_image;
6604 g_assert (type->type);
6605 image->wrappers_type = mono_class_from_mono_type (type->type);
6611 * mono_assembly_get_object:
6612 * @domain: an app domain
6613 * @assembly: an assembly
6615 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6617 MonoReflectionAssembly*
6618 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6621 static MonoClass *assembly_type;
6622 MonoReflectionAssembly *res;
6624 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6625 if (!assembly_type) {
6626 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6628 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6630 assembly_type = klass;
6632 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6633 mono_error_raise_exception (&error); /* FIXME don't raise here */
6634 res->assembly = assembly;
6636 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6641 MonoReflectionModule*
6642 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6645 static MonoClass *module_type;
6646 MonoReflectionModule *res;
6649 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6651 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6653 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6655 module_type = klass;
6657 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6658 mono_error_raise_exception (&error); /* FIXME don't raise here */
6661 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6663 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6664 basename = g_path_get_basename (image->name);
6665 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6666 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6670 if (image->assembly->image == image) {
6671 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6675 if (image->assembly->image->modules) {
6676 for (i = 0; i < image->assembly->image->module_count; i++) {
6677 if (image->assembly->image->modules [i] == image)
6678 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6680 g_assert (res->token);
6684 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6687 MonoReflectionModule*
6688 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6691 static MonoClass *module_type;
6692 MonoReflectionModule *res;
6693 MonoTableInfo *table;
6694 guint32 cols [MONO_FILE_SIZE];
6696 guint32 i, name_idx;
6700 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6702 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6704 module_type = klass;
6706 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6707 mono_error_raise_exception (&error); /* FIXME don't raise here */
6709 table = &image->tables [MONO_TABLE_FILE];
6710 g_assert (table_index < table->rows);
6711 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6714 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6715 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6717 /* Check whenever the row has a corresponding row in the moduleref table */
6718 table = &image->tables [MONO_TABLE_MODULEREF];
6719 for (i = 0; i < table->rows; ++i) {
6720 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6721 val = mono_metadata_string_heap (image, name_idx);
6722 if (strcmp (val, name) == 0)
6723 res->image = image->modules [i];
6726 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6727 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6728 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6729 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6730 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6736 verify_safe_for_managed_space (MonoType *type)
6738 switch (type->type) {
6740 case MONO_TYPE_ARRAY:
6741 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6743 return verify_safe_for_managed_space (type->data.type);
6744 case MONO_TYPE_SZARRAY:
6745 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6746 case MONO_TYPE_GENERICINST: {
6747 MonoGenericInst *inst = type->data.generic_class->inst;
6751 for (i = 0; i < inst->type_argc; ++i)
6752 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6758 case MONO_TYPE_MVAR:
6766 mono_type_normalize (MonoType *type)
6769 MonoGenericClass *gclass;
6770 MonoGenericInst *ginst;
6772 MonoGenericContainer *gcontainer;
6773 MonoType **argv = NULL;
6774 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6776 if (type->type != MONO_TYPE_GENERICINST)
6779 gclass = type->data.generic_class;
6780 ginst = gclass->context.class_inst;
6781 if (!ginst->is_open)
6784 gtd = gclass->container_class;
6785 gcontainer = gtd->generic_container;
6786 argv = g_newa (MonoType*, ginst->type_argc);
6788 for (i = 0; i < ginst->type_argc; ++i) {
6789 MonoType *t = ginst->type_argv [i], *norm;
6790 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6791 is_denorm_gtd = FALSE;
6792 norm = mono_type_normalize (t);
6795 requires_rebind = TRUE;
6799 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6801 if (requires_rebind) {
6802 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6803 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6809 * mono_type_get_object:
6810 * @domain: an app domain
6813 * Return an System.MonoType object representing the type @type.
6816 mono_type_get_object (MonoDomain *domain, MonoType *type)
6819 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6820 mono_error_raise_exception (&error);
6826 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6828 MonoType *norm_type;
6829 MonoReflectionType *res;
6832 mono_error_init (error);
6834 klass = mono_class_from_mono_type (type);
6836 /*we must avoid using @type as it might have come
6837 * from a mono_metadata_type_dup and the caller
6838 * expects that is can be freed.
6839 * Using the right type from
6841 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6843 /* void is very common */
6844 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6845 return (MonoReflectionType*)domain->typeof_void;
6848 * If the vtable of the given class was already created, we can use
6849 * the MonoType from there and avoid all locking and hash table lookups.
6851 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6852 * that the resulting object is different.
6854 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6855 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6856 if (vtable && vtable->type)
6857 return (MonoReflectionType *)vtable->type;
6860 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6861 mono_domain_lock (domain);
6862 if (!domain->type_hash)
6863 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6864 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6865 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6866 mono_domain_unlock (domain);
6867 mono_loader_unlock ();
6871 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6872 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6873 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6874 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6875 * artifact of how generics are encoded and should be transparent to managed code so we
6876 * need to weed out this diference when retrieving managed System.Type objects.
6878 norm_type = mono_type_normalize (type);
6879 if (norm_type != type) {
6880 res = mono_type_get_object_checked (domain, norm_type, error);
6881 if (!mono_error_ok (error))
6883 mono_g_hash_table_insert (domain->type_hash, type, res);
6884 mono_domain_unlock (domain);
6885 mono_loader_unlock ();
6889 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6890 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6893 if (!verify_safe_for_managed_space (type)) {
6894 mono_domain_unlock (domain);
6895 mono_loader_unlock ();
6896 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6900 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6901 gboolean is_type_done = TRUE;
6902 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6903 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6904 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6906 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6907 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6909 if (gparam->owner && gparam->owner->is_method) {
6910 MonoMethod *method = gparam->owner->owner.method;
6911 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6912 is_type_done = FALSE;
6913 } else if (gparam->owner && !gparam->owner->is_method) {
6914 MonoClass *klass = gparam->owner->owner.klass;
6915 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6916 is_type_done = FALSE;
6920 /* g_assert_not_reached (); */
6921 /* should this be considered an error condition? */
6922 if (is_type_done && !type->byref) {
6923 mono_domain_unlock (domain);
6924 mono_loader_unlock ();
6925 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6928 /* This is stored in vtables/JITted code so it has to be pinned */
6929 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6930 if (!mono_error_ok (error))
6934 mono_g_hash_table_insert (domain->type_hash, type, res);
6936 if (type->type == MONO_TYPE_VOID)
6937 domain->typeof_void = (MonoObject*)res;
6939 mono_domain_unlock (domain);
6940 mono_loader_unlock ();
6945 * mono_method_get_object:
6946 * @domain: an app domain
6948 * @refclass: the reflected type (can be NULL)
6950 * Return an System.Reflection.MonoMethod object representing the method @method.
6952 MonoReflectionMethod*
6953 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6956 MonoReflectionMethod *ret = NULL;
6957 ret = mono_method_get_object_checked (domain, method, refclass, &error);
6958 mono_error_raise_exception (&error);
6963 * mono_method_get_object_checked:
6964 * @domain: an app domain
6966 * @refclass: the reflected type (can be NULL)
6967 * @error: set on error.
6969 * Return an System.Reflection.MonoMethod object representing the method @method.
6970 * Returns NULL and sets @error on error.
6972 MonoReflectionMethod*
6973 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6976 * We use the same C representation for methods and constructors, but the type
6977 * name in C# is different.
6979 static MonoClass *System_Reflection_MonoMethod = NULL;
6980 static MonoClass *System_Reflection_MonoCMethod = NULL;
6981 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6982 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6983 MonoReflectionType *rt;
6985 MonoReflectionMethod *ret;
6987 mono_error_init (error);
6989 if (method->is_inflated) {
6990 MonoReflectionGenericMethod *gret;
6993 refclass = method->klass;
6994 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6995 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6996 if (!System_Reflection_MonoGenericCMethod) {
6997 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6998 if (!mono_error_ok (error))
7001 klass = System_Reflection_MonoGenericCMethod;
7003 if (!System_Reflection_MonoGenericMethod) {
7004 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
7005 if (!mono_error_ok (error))
7008 klass = System_Reflection_MonoGenericMethod;
7010 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7011 if (!mono_error_ok (error))
7013 gret->method.method = method;
7015 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7017 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7018 if (!mono_error_ok (error))
7021 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7023 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7027 refclass = method->klass;
7029 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7030 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7031 if (!System_Reflection_MonoCMethod) {
7032 System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7033 if (!mono_error_ok (error))
7036 klass = System_Reflection_MonoCMethod;
7039 if (!System_Reflection_MonoMethod) {
7040 System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7041 if (!mono_error_ok (error))
7044 klass = System_Reflection_MonoMethod;
7046 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7047 if (!mono_error_ok (error))
7049 ret->method = method;
7051 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7052 if (!mono_error_ok (error))
7055 MONO_OBJECT_SETREF (ret, reftype, rt);
7057 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7060 g_assert (!mono_error_ok (error));
7065 * mono_method_clear_object:
7067 * Clear the cached reflection objects for the dynamic method METHOD.
7070 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7073 g_assert (method_is_dynamic (method));
7075 klass = method->klass;
7077 clear_cached_object (domain, method, klass);
7078 klass = klass->parent;
7080 /* Added by mono_param_get_objects () */
7081 clear_cached_object (domain, &(method->signature), NULL);
7082 klass = method->klass;
7084 clear_cached_object (domain, &(method->signature), klass);
7085 klass = klass->parent;
7090 * mono_field_get_object:
7091 * @domain: an app domain
7095 * Return an System.Reflection.MonoField object representing the field @field
7098 MonoReflectionField*
7099 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7102 MonoReflectionField *result;
7103 result = mono_field_get_object_checked (domain, klass, field, &error);
7104 mono_error_raise_exception (&error);
7109 * mono_field_get_object_checked:
7110 * @domain: an app domain
7113 * @error: set on error
7115 * Return an System.Reflection.MonoField object representing the field @field
7116 * in class @klass. On error, returns NULL and sets @error.
7118 MonoReflectionField*
7119 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7121 MonoReflectionType *rt;
7122 MonoReflectionField *res;
7123 static MonoClass *monofield_klass;
7125 mono_error_init (error);
7127 CHECK_OBJECT (MonoReflectionField *, field, klass);
7128 if (!monofield_klass)
7129 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7130 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7131 mono_error_raise_exception (error); /* FIXME don't raise here */
7134 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7136 if (is_field_on_inst (field)) {
7137 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7139 rt = mono_type_get_object_checked (domain, field->type, error);
7140 if (!mono_error_ok (error))
7143 MONO_OBJECT_SETREF (res, type, rt);
7146 rt = mono_type_get_object_checked (domain, field->type, error);
7147 if (!mono_error_ok (error))
7150 MONO_OBJECT_SETREF (res, type, rt);
7152 res->attrs = mono_field_get_flags (field);
7154 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7158 * mono_property_get_object:
7159 * @domain: an app domain
7161 * @property: a property
7163 * Return an System.Reflection.MonoProperty object representing the property @property
7166 MonoReflectionProperty*
7167 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7170 MonoReflectionProperty *res;
7171 static MonoClass *monoproperty_klass;
7173 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7174 if (!monoproperty_klass)
7175 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7176 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7177 mono_error_raise_exception (&error); /* FIXME don't raise here */
7179 res->property = property;
7180 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7184 * mono_event_get_object:
7185 * @domain: an app domain
7189 * Return an System.Reflection.MonoEvent object representing the event @event
7192 MonoReflectionEvent*
7193 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7196 MonoReflectionEvent *res;
7197 MonoReflectionMonoEvent *mono_event;
7198 static MonoClass *monoevent_klass;
7200 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7201 if (!monoevent_klass)
7202 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7203 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7204 mono_error_raise_exception (&error); /* FIXME don't raise here */
7205 mono_event->klass = klass;
7206 mono_event->event = event;
7207 res = (MonoReflectionEvent*)mono_event;
7208 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7212 * mono_get_reflection_missing_object:
7213 * @domain: Domain where the object lives
7215 * Returns the System.Reflection.Missing.Value singleton object
7216 * (of type System.Reflection.Missing).
7218 * Used as the value for ParameterInfo.DefaultValue when Optional
7222 mono_get_reflection_missing_object (MonoDomain *domain)
7225 static MonoClassField *missing_value_field = NULL;
7227 if (!missing_value_field) {
7228 MonoClass *missing_klass;
7229 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7230 mono_class_init (missing_klass);
7231 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7232 g_assert (missing_value_field);
7234 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7240 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7243 *dbnull = mono_get_dbnull_object (domain);
7248 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7250 if (!*reflection_missing)
7251 *reflection_missing = mono_get_reflection_missing_object (domain);
7252 return *reflection_missing;
7256 * mono_param_get_objects:
7257 * @domain: an app domain
7260 * Return an System.Reflection.ParameterInfo array object representing the parameters
7261 * in the method @method.
7264 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7266 static MonoClass *System_Reflection_ParameterInfo;
7267 static MonoClass *System_Reflection_ParameterInfo_array;
7269 MonoArray *res = NULL;
7270 MonoReflectionMethod *member = NULL;
7271 MonoReflectionParameter *param = NULL;
7272 char **names, **blobs = NULL;
7273 guint32 *types = NULL;
7274 MonoType *type = NULL;
7275 MonoObject *dbnull = NULL;
7276 MonoObject *missing = NULL;
7277 MonoMarshalSpec **mspecs;
7278 MonoMethodSignature *sig;
7279 MonoVTable *pinfo_vtable;
7280 MonoReflectionType *rt;
7283 if (!System_Reflection_ParameterInfo_array) {
7286 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7288 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7290 mono_memory_barrier ();
7291 System_Reflection_ParameterInfo = klass;
7294 klass = mono_array_class_get (klass, 1);
7295 mono_memory_barrier ();
7296 System_Reflection_ParameterInfo_array = klass;
7299 sig = mono_method_signature_checked (method, &error);
7300 if (!mono_error_ok (&error))
7301 mono_error_raise_exception (&error);
7303 if (!sig->param_count) {
7304 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7305 mono_error_raise_exception (&error); /* FIXME don't raise here */
7310 /* Note: the cache is based on the address of the signature into the method
7311 * since we already cache MethodInfos with the method as keys.
7313 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7315 member = mono_method_get_object_checked (domain, method, refclass, &error);
7316 mono_error_raise_exception (&error); /* FIXME don't raise here */
7317 names = g_new (char *, sig->param_count);
7318 mono_method_get_param_names (method, (const char **) names);
7320 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7321 mono_method_get_marshal_info (method, mspecs);
7323 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7324 mono_error_raise_exception (&error); /* FIXME don't raise here */
7326 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7327 for (i = 0; i < sig->param_count; ++i) {
7328 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7329 mono_error_raise_exception (&error); /* FIXME don't raise here */
7331 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7332 mono_error_raise_exception (&error); /* FIXME don't raise here */
7334 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7336 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7338 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7340 param->PositionImpl = i;
7341 param->AttrsImpl = sig->params [i]->attrs;
7343 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7344 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7345 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7347 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7351 blobs = g_new0 (char *, sig->param_count);
7352 types = g_new0 (guint32, sig->param_count);
7353 get_default_param_value_blobs (method, blobs, types);
7356 /* Build MonoType for the type from the Constant Table */
7358 type = g_new0 (MonoType, 1);
7359 type->type = (MonoTypeEnum)types [i];
7360 type->data.klass = NULL;
7361 if (types [i] == MONO_TYPE_CLASS)
7362 type->data.klass = mono_defaults.object_class;
7363 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7364 /* For enums, types [i] contains the base type */
7366 type->type = MONO_TYPE_VALUETYPE;
7367 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7369 type->data.klass = mono_class_from_mono_type (type);
7371 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7373 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7374 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7375 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7376 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7378 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7384 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7386 mono_array_setref (res, i, param);
7393 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7395 mono_metadata_free_marshal_spec (mspecs [i]);
7398 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7402 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7404 return mono_param_get_objects_internal (domain, method, NULL);
7408 * mono_method_body_get_object:
7409 * @domain: an app domain
7412 * Return an System.Reflection.MethodBody object representing the method @method.
7414 MonoReflectionMethodBody*
7415 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7417 static MonoClass *System_Reflection_MethodBody = NULL;
7418 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7419 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7421 MonoReflectionMethodBody *ret;
7422 MonoMethodHeader *header;
7424 MonoReflectionType *rt;
7425 guint32 method_rva, local_var_sig_token;
7427 unsigned char format, flags;
7430 /* for compatibility with .net */
7431 if (method_is_dynamic (method))
7432 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7434 if (!System_Reflection_MethodBody)
7435 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7436 if (!System_Reflection_LocalVariableInfo)
7437 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7438 if (!System_Reflection_ExceptionHandlingClause)
7439 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7441 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7443 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7444 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7445 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7446 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7447 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7450 image = method->klass->image;
7451 header = mono_method_get_header (method);
7453 if (!image_is_dynamic (image)) {
7454 /* Obtain local vars signature token */
7455 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7456 ptr = mono_image_rva_map (image, method_rva);
7457 flags = *(const unsigned char *) ptr;
7458 format = flags & METHOD_HEADER_FORMAT_MASK;
7460 case METHOD_HEADER_TINY_FORMAT:
7461 local_var_sig_token = 0;
7463 case METHOD_HEADER_FAT_FORMAT:
7467 local_var_sig_token = read32 (ptr);
7470 g_assert_not_reached ();
7473 local_var_sig_token = 0; //FIXME
7475 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7476 mono_error_raise_exception (&error); /* FIXME don't raise here */
7478 ret->init_locals = header->init_locals;
7479 ret->max_stack = header->max_stack;
7480 ret->local_var_sig_token = local_var_sig_token;
7481 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7482 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7485 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7486 for (i = 0; i < header->num_locals; ++i) {
7487 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7488 mono_error_raise_exception (&error); /* FIXME don't raise here */
7490 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7491 mono_error_raise_exception (&error); /* FIXME don't raise here */
7493 MONO_OBJECT_SETREF (info, local_type, rt);
7495 info->is_pinned = header->locals [i]->pinned;
7496 info->local_index = i;
7497 mono_array_setref (ret->locals, i, info);
7501 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7502 for (i = 0; i < header->num_clauses; ++i) {
7503 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7504 mono_error_raise_exception (&error); /* FIXME don't raise here */
7505 MonoExceptionClause *clause = &header->clauses [i];
7507 info->flags = clause->flags;
7508 info->try_offset = clause->try_offset;
7509 info->try_length = clause->try_len;
7510 info->handler_offset = clause->handler_offset;
7511 info->handler_length = clause->handler_len;
7512 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7513 info->filter_offset = clause->data.filter_offset;
7514 else if (clause->data.catch_class) {
7515 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7516 mono_error_raise_exception (&error); /* FIXME don't raise here */
7518 MONO_OBJECT_SETREF (info, catch_type, rt);
7521 mono_array_setref (ret->clauses, i, info);
7524 mono_metadata_free_mh (header);
7525 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7530 * mono_get_dbnull_object:
7531 * @domain: Domain where the object lives
7533 * Returns the System.DBNull.Value singleton object
7535 * Used as the value for ParameterInfo.DefaultValue
7538 mono_get_dbnull_object (MonoDomain *domain)
7541 static MonoClassField *dbnull_value_field = NULL;
7543 if (!dbnull_value_field) {
7544 MonoClass *dbnull_klass;
7545 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7546 mono_class_init (dbnull_klass);
7547 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7548 g_assert (dbnull_value_field);
7550 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7556 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7558 guint32 param_index, i, lastp, crow = 0;
7559 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7562 MonoClass *klass = method->klass;
7563 MonoImage *image = klass->image;
7564 MonoMethodSignature *methodsig = mono_method_signature (method);
7566 MonoTableInfo *constt;
7567 MonoTableInfo *methodt;
7568 MonoTableInfo *paramt;
7570 if (!methodsig->param_count)
7573 mono_class_init (klass);
7575 if (image_is_dynamic (klass->image)) {
7576 MonoReflectionMethodAux *aux;
7577 if (method->is_inflated)
7578 method = ((MonoMethodInflated*)method)->declaring;
7579 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7580 if (aux && aux->param_defaults) {
7581 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7582 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7587 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7588 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7589 constt = &image->tables [MONO_TABLE_CONSTANT];
7591 idx = mono_method_get_index (method) - 1;
7592 g_assert (idx != -1);
7594 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7595 if (idx + 1 < methodt->rows)
7596 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7598 lastp = paramt->rows + 1;
7600 for (i = param_index; i < lastp; ++i) {
7603 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7604 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7606 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7609 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7614 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7615 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7616 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7623 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7629 MonoType *basetype = type;
7634 klass = mono_class_from_mono_type (type);
7635 if (klass->valuetype) {
7636 object = mono_object_new_checked (domain, klass, &error);
7637 mono_error_raise_exception (&error); /* FIXME don't raise here */
7638 retval = ((gchar *) object + sizeof (MonoObject));
7639 if (klass->enumtype)
7640 basetype = mono_class_enum_basetype (klass);
7645 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7652 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7655 gboolean quoted = FALSE;
7657 memset (assembly, 0, sizeof (MonoAssemblyName));
7658 assembly->culture = "";
7659 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7666 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7677 /* Remove trailing whitespace */
7679 while (*s && g_ascii_isspace (*s))
7682 while (g_ascii_isspace (*p))
7685 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7687 assembly->major = strtoul (p, &s, 10);
7688 if (s == p || *s != '.')
7691 assembly->minor = strtoul (p, &s, 10);
7692 if (s == p || *s != '.')
7695 assembly->build = strtoul (p, &s, 10);
7696 if (s == p || *s != '.')
7699 assembly->revision = strtoul (p, &s, 10);
7703 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7705 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7706 assembly->culture = "";
7709 assembly->culture = p;
7710 while (*p && *p != ',') {
7714 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7716 if (strncmp (p, "null", 4) == 0) {
7721 while (*p && *p != ',') {
7724 len = (p - start + 1);
7725 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7726 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7727 g_strlcpy ((char*)assembly->public_key_token, start, len);
7730 while (*p && *p != ',')
7734 while (g_ascii_isspace (*p) || *p == ',') {
7748 * mono_reflection_parse_type:
7751 * Parse a type name as accepted by the GetType () method and output the info
7752 * extracted in the info structure.
7753 * the name param will be mangled, so, make a copy before passing it to this function.
7754 * The fields in info will be valid until the memory pointed to by name is valid.
7756 * See also mono_type_get_name () below.
7758 * Returns: 0 on parse error.
7761 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7762 MonoTypeNameParse *info)
7764 char *start, *p, *w, *last_point, *startn;
7765 int in_modifiers = 0;
7766 int isbyref = 0, rank = 0, isptr = 0;
7768 start = p = w = name;
7770 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7771 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7772 info->name = info->name_space = NULL;
7773 info->nested = NULL;
7774 info->modifiers = NULL;
7775 info->type_arguments = NULL;
7777 /* last_point separates the namespace from the name */
7780 while (*p == ' ') p++, start++, w++, name++;
7785 *p = 0; /* NULL terminate the name */
7787 info->nested = g_list_append (info->nested, startn);
7788 /* we have parsed the nesting namespace + name */
7792 info->name_space = start;
7794 info->name = last_point + 1;
7796 info->name_space = (char *)"";
7824 info->name_space = start;
7826 info->name = last_point + 1;
7828 info->name_space = (char *)"";
7835 if (isbyref) /* only one level allowed by the spec */
7839 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7843 if (isbyref) /* pointer to ref not okay */
7845 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7850 if (isbyref) /* array of ref and generic ref are not okay */
7852 //Decide if it's an array of a generic argument list
7857 if (*p == ',' || *p == '*' || *p == ']') { //array
7865 else if (*p == '*') /* '*' means unknown lower bound */
7866 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7873 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7875 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7878 info->type_arguments = g_ptr_array_new ();
7880 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7881 gboolean fqname = FALSE;
7883 g_ptr_array_add (info->type_arguments, subinfo);
7885 while (*p == ' ') p++;
7891 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7894 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7895 if (fqname && (*p != ']')) {
7903 while (*p && (*p != ']'))
7911 if (g_ascii_isspace (*aname)) {
7918 !assembly_name_to_aname (&subinfo->assembly, aname))
7920 } else if (fqname && (*p == ']')) {
7942 if (g_ascii_isspace (*p)) {
7949 return 0; /* missing assembly name */
7950 if (!assembly_name_to_aname (&info->assembly, p))
7956 if (info->assembly.name)
7959 // *w = 0; /* terminate class name */
7961 if (!info->name || !*info->name)
7965 /* add other consistency checks */
7971 * mono_identifier_unescape_type_name_chars:
7972 * @identifier: the display name of a mono type
7975 * The name in internal form, that is without escaping backslashes.
7977 * The string is modified in place!
7980 mono_identifier_unescape_type_name_chars(char* identifier)
7985 for (w = r = identifier; *r != 0; r++)
8003 mono_identifier_unescape_info (MonoTypeNameParse* info);
8006 unescape_each_type_argument(void* data, void* user_data)
8008 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8009 mono_identifier_unescape_info (info);
8013 unescape_each_nested_name (void* data, void* user_data)
8015 char* nested_name = (char*) data;
8016 mono_identifier_unescape_type_name_chars(nested_name);
8020 * mono_identifier_unescape_info:
8022 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8026 * Destructively updates the info by unescaping the identifiers that
8027 * comprise the type namespace, name, nested types (if any) and
8028 * generic type arguments (if any).
8030 * The resulting info has the names in internal form.
8034 mono_identifier_unescape_info (MonoTypeNameParse *info)
8038 mono_identifier_unescape_type_name_chars(info->name_space);
8039 mono_identifier_unescape_type_name_chars(info->name);
8040 // but don't escape info->assembly
8041 if (info->type_arguments)
8042 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8044 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8048 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8050 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8052 mono_identifier_unescape_info (info);
8058 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8060 gboolean type_resolve = FALSE;
8062 MonoImage *rootimage = image;
8064 if (info->assembly.name) {
8065 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8066 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8068 * This could happen in the AOT compiler case when the search hook is not
8071 assembly = image->assembly;
8073 /* then we must load the assembly ourselve - see #60439 */
8074 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8078 image = assembly->image;
8079 } else if (!image) {
8080 image = mono_defaults.corlib;
8083 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8084 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8085 image = mono_defaults.corlib;
8086 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8093 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
8099 gboolean bounded = FALSE;
8102 image = mono_defaults.corlib;
8105 rootimage = mono_defaults.corlib;
8109 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
8110 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
8112 klass = mono_class_from_name (image, info->name_space, info->name);
8116 for (mod = info->nested; mod; mod = mod->next) {
8117 gpointer iter = NULL;
8121 mono_class_init (parent);
8123 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8125 char *nested_name, *nested_nspace;
8126 gboolean match = TRUE;
8128 lastp = strrchr ((const char *)mod->data, '.');
8130 /* Nested classes can have namespaces */
8133 nested_name = g_strdup (lastp + 1);
8134 nspace_len = lastp - (char*)mod->data;
8135 nested_nspace = (char *)g_malloc (nspace_len + 1);
8136 memcpy (nested_nspace, mod->data, nspace_len);
8137 nested_nspace [nspace_len] = '\0';
8140 nested_name = (char *)mod->data;
8141 nested_nspace = NULL;
8144 if (nested_nspace) {
8146 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8149 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8155 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8158 if (strcmp (klass->name, nested_name) != 0)
8163 g_free (nested_name);
8164 g_free (nested_nspace);
8176 if (info->type_arguments) {
8177 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8178 MonoReflectionType *the_type;
8182 for (i = 0; i < info->type_arguments->len; i++) {
8183 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8185 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8186 if (!type_args [i]) {
8192 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8193 mono_error_raise_exception (&error); /* FIXME don't raise here */
8195 instance = mono_reflection_bind_generic_parameters (
8196 the_type, info->type_arguments->len, type_args);
8202 klass = mono_class_from_mono_type (instance);
8205 for (mod = info->modifiers; mod; mod = mod->next) {
8206 modval = GPOINTER_TO_UINT (mod->data);
8207 if (!modval) { /* byref: must be last modifier */
8208 return &klass->this_arg;
8209 } else if (modval == -1) {
8210 klass = mono_ptr_class_get (&klass->byval_arg);
8211 } else if (modval == -2) {
8213 } else { /* array rank */
8214 klass = mono_bounded_array_class_get (klass, modval, bounded);
8218 return &klass->byval_arg;
8222 * mono_reflection_get_type:
8223 * @image: a metadata context
8224 * @info: type description structure
8225 * @ignorecase: flag for case-insensitive string compares
8226 * @type_resolve: whenever type resolve was already tried
8228 * Build a MonoType from the type description in @info.
8233 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8234 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8238 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8240 MonoReflectionAssemblyBuilder *abuilder;
8244 g_assert (assembly_is_dynamic (assembly));
8245 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8247 /* Enumerate all modules */
8250 if (abuilder->modules) {
8251 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8252 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8253 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8259 if (!type && abuilder->loaded_modules) {
8260 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8261 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8262 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8272 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8275 MonoReflectionAssembly *assembly;
8279 if (image && image_is_dynamic (image))
8280 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8282 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8285 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8292 *type_resolve = TRUE;
8295 /* Reconstruct the type name */
8296 fullName = g_string_new ("");
8297 if (info->name_space && (info->name_space [0] != '\0'))
8298 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8300 g_string_printf (fullName, "%s", info->name);
8301 for (mod = info->nested; mod; mod = mod->next)
8302 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8304 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8306 if (assembly_is_dynamic (assembly->assembly))
8307 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8309 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8312 g_string_free (fullName, TRUE);
8317 mono_reflection_free_type_info (MonoTypeNameParse *info)
8319 g_list_free (info->modifiers);
8320 g_list_free (info->nested);
8322 if (info->type_arguments) {
8325 for (i = 0; i < info->type_arguments->len; i++) {
8326 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8328 mono_reflection_free_type_info (subinfo);
8329 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8333 g_ptr_array_free (info->type_arguments, TRUE);
8338 * mono_reflection_type_from_name:
8340 * @image: a metadata context (can be NULL).
8342 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8343 * it defaults to get the type from @image or, if @image is NULL or loading
8344 * from it fails, uses corlib.
8348 mono_reflection_type_from_name (char *name, MonoImage *image)
8350 MonoType *type = NULL;
8351 MonoTypeNameParse info;
8354 /* Make a copy since parse_type modifies its argument */
8355 tmp = g_strdup (name);
8357 /*g_print ("requested type %s\n", str);*/
8358 if (mono_reflection_parse_type (tmp, &info)) {
8359 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8363 mono_reflection_free_type_info (&info);
8368 * mono_reflection_get_token:
8370 * Return the metadata token of OBJ which should be an object
8371 * representing a metadata element.
8374 mono_reflection_get_token (MonoObject *obj)
8379 klass = obj->vtable->klass;
8381 if (strcmp (klass->name, "MethodBuilder") == 0) {
8382 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8384 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8385 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8386 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8388 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8389 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8390 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8392 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8393 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8394 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8395 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8396 } else if (strcmp (klass->name, "MonoType") == 0) {
8397 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8398 MonoClass *mc = mono_class_from_mono_type (type);
8399 if (!mono_class_init (mc))
8400 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8402 token = mc->type_token;
8403 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8404 strcmp (klass->name, "MonoMethod") == 0 ||
8405 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8406 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8407 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8408 if (m->method->is_inflated) {
8409 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8410 return inflated->declaring->token;
8412 token = m->method->token;
8414 } else if (strcmp (klass->name, "MonoField") == 0) {
8415 MonoReflectionField *f = (MonoReflectionField*)obj;
8417 if (is_field_on_inst (f->field)) {
8418 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8420 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8421 int field_index = f->field - dgclass->fields;
8424 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8425 obj = dgclass->field_objects [field_index];
8426 return mono_reflection_get_token (obj);
8429 token = mono_class_get_field_token (f->field);
8430 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8431 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8433 token = mono_class_get_property_token (p->property);
8434 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8435 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8437 token = mono_class_get_event_token (p->event);
8438 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8439 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8440 MonoClass *member_class = mono_object_class (p->MemberImpl);
8441 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8443 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8444 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8445 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8448 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8449 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8451 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8452 MonoException *ex = mono_get_exception_not_implemented (msg);
8454 mono_raise_exception (ex);
8461 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8465 int slen = mono_metadata_decode_value (p, &p);
8467 mono_error_init (error);
8469 n = (char *)g_memdup (p, slen + 1);
8471 t = mono_reflection_type_from_name (n, image);
8473 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8474 /* We don't free n, it's consumed by mono_error */
8475 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8481 return mono_class_from_mono_type (t);
8485 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8487 int slen, type = t->type;
8488 MonoClass *tklass = t->data.klass;
8490 mono_error_init (error);
8496 case MONO_TYPE_BOOLEAN: {
8497 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8502 case MONO_TYPE_CHAR:
8504 case MONO_TYPE_I2: {
8505 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8510 #if SIZEOF_VOID_P == 4
8516 case MONO_TYPE_I4: {
8517 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8522 #if SIZEOF_VOID_P == 8
8523 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8527 case MONO_TYPE_I8: {
8528 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8533 case MONO_TYPE_R8: {
8534 double *val = (double *)g_malloc (sizeof (double));
8539 case MONO_TYPE_VALUETYPE:
8540 if (t->data.klass->enumtype) {
8541 type = mono_class_enum_basetype (t->data.klass)->type;
8544 MonoClass *k = t->data.klass;
8546 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8547 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8553 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8556 case MONO_TYPE_STRING:
8557 if (*p == (char)0xFF) {
8561 slen = mono_metadata_decode_value (p, &p);
8563 return mono_string_new_len (mono_domain_get (), p, slen);
8564 case MONO_TYPE_CLASS: {
8565 MonoReflectionType *rt;
8568 if (*p == (char)0xFF) {
8573 slen = mono_metadata_decode_value (p, &p);
8574 n = (char *)g_memdup (p, slen + 1);
8576 t = mono_reflection_type_from_name (n, image);
8578 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8579 /* We don't free n, it's consumed by mono_error */
8580 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8586 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8587 if (!mono_error_ok (error))
8592 case MONO_TYPE_OBJECT: {
8595 MonoClass *subc = NULL;
8600 } else if (subt == 0x0E) {
8601 type = MONO_TYPE_STRING;
8603 } else if (subt == 0x1D) {
8604 MonoType simple_type = {{0}};
8608 type = MONO_TYPE_SZARRAY;
8609 if (etype == 0x50) {
8610 tklass = mono_defaults.systemtype_class;
8611 } else if (etype == 0x55) {
8612 tklass = load_cattr_enum_type (image, p, &p, error);
8613 if (!mono_error_ok (error))
8617 /* See Partition II, Appendix B3 */
8618 etype = MONO_TYPE_OBJECT;
8619 simple_type.type = (MonoTypeEnum)etype;
8620 tklass = mono_class_from_mono_type (&simple_type);
8623 } else if (subt == 0x55) {
8626 slen = mono_metadata_decode_value (p, &p);
8627 n = (char *)g_memdup (p, slen + 1);
8629 t = mono_reflection_type_from_name (n, image);
8631 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8632 /* We don't free n, it's consumed by mono_error */
8633 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8638 subc = mono_class_from_mono_type (t);
8639 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8640 MonoType simple_type = {{0}};
8641 simple_type.type = (MonoTypeEnum)subt;
8642 subc = mono_class_from_mono_type (&simple_type);
8644 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8646 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8648 if (mono_error_ok (error)) {
8649 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8650 g_assert (!subc->has_references);
8651 if (mono_error_ok (error))
8652 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8658 case MONO_TYPE_SZARRAY: {
8660 guint32 i, alen, basetype;
8663 if (alen == 0xffffffff) {
8667 arr = mono_array_new (mono_domain_get(), tklass, alen);
8668 basetype = tklass->byval_arg.type;
8669 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8670 basetype = mono_class_enum_basetype (tklass)->type;
8675 case MONO_TYPE_BOOLEAN:
8676 for (i = 0; i < alen; i++) {
8677 MonoBoolean val = *p++;
8678 mono_array_set (arr, MonoBoolean, i, val);
8681 case MONO_TYPE_CHAR:
8684 for (i = 0; i < alen; i++) {
8685 guint16 val = read16 (p);
8686 mono_array_set (arr, guint16, i, val);
8693 for (i = 0; i < alen; i++) {
8694 guint32 val = read32 (p);
8695 mono_array_set (arr, guint32, i, val);
8700 for (i = 0; i < alen; i++) {
8703 mono_array_set (arr, double, i, val);
8709 for (i = 0; i < alen; i++) {
8710 guint64 val = read64 (p);
8711 mono_array_set (arr, guint64, i, val);
8715 case MONO_TYPE_CLASS:
8716 case MONO_TYPE_OBJECT:
8717 case MONO_TYPE_STRING:
8718 case MONO_TYPE_SZARRAY:
8719 for (i = 0; i < alen; i++) {
8720 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8721 if (!mono_error_ok (error))
8723 mono_array_setref (arr, i, item);
8727 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8733 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8739 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8741 static MonoClass *klass;
8742 static MonoMethod *ctor;
8745 void *params [2], *unboxed;
8748 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8750 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8752 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8753 mono_error_raise_exception (&error); /* FIXME don't raise here */
8756 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8757 mono_error_raise_exception (&error); /* FIXME don't raise here */
8758 unboxed = mono_object_unbox (retval);
8759 mono_runtime_invoke (ctor, unboxed, params, NULL);
8765 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8767 static MonoClass *klass;
8768 static MonoMethod *ctor;
8771 void *unboxed, *params [2];
8774 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8776 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8779 params [1] = typedarg;
8780 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8781 mono_error_raise_exception (&error); /* FIXME don't raise here */
8782 unboxed = mono_object_unbox (retval);
8783 mono_runtime_invoke (ctor, unboxed, params, NULL);
8789 type_is_reference (MonoType *type)
8791 switch (type->type) {
8792 case MONO_TYPE_BOOLEAN:
8793 case MONO_TYPE_CHAR:
8806 case MONO_TYPE_VALUETYPE:
8814 free_param_data (MonoMethodSignature *sig, void **params) {
8816 for (i = 0; i < sig->param_count; ++i) {
8817 if (!type_is_reference (sig->params [i]))
8818 g_free (params [i]);
8823 * Find the field index in the metadata FieldDef table.
8826 find_field_index (MonoClass *klass, MonoClassField *field) {
8829 for (i = 0; i < klass->field.count; ++i) {
8830 if (field == &klass->fields [i])
8831 return klass->field.first + 1 + i;
8837 * Find the property index in the metadata Property table.
8840 find_property_index (MonoClass *klass, MonoProperty *property) {
8843 for (i = 0; i < klass->ext->property.count; ++i) {
8844 if (property == &klass->ext->properties [i])
8845 return klass->ext->property.first + 1 + i;
8851 * Find the event index in the metadata Event table.
8854 find_event_index (MonoClass *klass, MonoEvent *event) {
8857 for (i = 0; i < klass->ext->event.count; ++i) {
8858 if (event == &klass->ext->events [i])
8859 return klass->ext->event.first + 1 + i;
8865 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8867 const char *p = (const char*)data;
8869 guint32 i, j, num_named;
8871 void *params_buf [32];
8872 void **params = NULL;
8873 MonoMethodSignature *sig;
8874 MonoObject *exc = NULL;
8876 mono_error_init (error);
8878 mono_class_init (method->klass);
8880 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8881 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8886 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8887 if (!mono_error_ok (error)) return NULL;
8888 mono_runtime_invoke (method, attr, NULL, NULL);
8892 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8895 /*g_print ("got attr %s\n", method->klass->name);*/
8897 sig = mono_method_signature (method);
8898 if (sig->param_count < 32) {
8899 params = params_buf;
8900 memset (params, 0, sizeof (void*) * sig->param_count);
8902 /* Allocate using GC so it gets GC tracking */
8903 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8908 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8909 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8910 if (!mono_error_ok (error))
8915 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8916 if (!mono_error_ok (error)) goto fail;
8918 mono_runtime_invoke (method, attr, params, &exc);
8921 num_named = read16 (named);
8923 for (j = 0; j < num_named; j++) {
8925 char *name, named_type, data_type;
8926 named_type = *named++;
8927 data_type = *named++; /* type of data */
8928 if (data_type == MONO_TYPE_SZARRAY)
8929 data_type = *named++;
8930 if (data_type == MONO_TYPE_ENUM) {
8933 type_len = mono_metadata_decode_blob_size (named, &named);
8934 type_name = (char *)g_malloc (type_len + 1);
8935 memcpy (type_name, named, type_len);
8936 type_name [type_len] = 0;
8938 /* FIXME: lookup the type and check type consistency */
8941 name_len = mono_metadata_decode_blob_size (named, &named);
8942 name = (char *)g_malloc (name_len + 1);
8943 memcpy (name, named, name_len);
8944 name [name_len] = 0;
8946 if (named_type == 0x53) {
8947 MonoClassField *field;
8950 /* how this fail is a blackbox */
8951 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8953 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8958 val = load_cattr_value (image, field->type, named, &named, error);
8959 if (!mono_error_ok (error)) {
8961 if (!type_is_reference (field->type))
8966 mono_field_set_value (attr, field, val);
8967 if (!type_is_reference (field->type))
8969 } else if (named_type == 0x54) {
8972 MonoType *prop_type;
8974 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8977 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8983 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8988 /* can we have more that 1 arg in a custom attr named property? */
8989 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8990 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8992 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8993 if (!mono_error_ok (error)) {
8995 if (!type_is_reference (prop_type))
8996 g_free (pparams [0]);
9001 mono_property_set_value (prop, attr, pparams, NULL);
9002 if (!type_is_reference (prop_type))
9003 g_free (pparams [0]);
9008 free_param_data (method->signature, params);
9009 if (params != params_buf)
9010 mono_gc_free_fixed (params);
9015 free_param_data (method->signature, params);
9016 if (params != params_buf)
9017 mono_gc_free_fixed (params);
9019 mono_raise_exception ((MonoException*)exc);
9024 * mono_reflection_create_custom_attr_data_args:
9026 * Create an array of typed and named arguments from the cattr blob given by DATA.
9027 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9028 * NAMED_ARG_INFO will contain information about the named arguments.
9031 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)
9033 MonoArray *typedargs, *namedargs;
9034 MonoClass *attrklass;
9036 const char *p = (const char*)data;
9038 guint32 i, j, num_named;
9039 CattrNamedArg *arginfo = NULL;
9043 *named_arg_info = NULL;
9045 mono_error_init (error);
9047 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9048 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9052 mono_class_init (method->klass);
9054 domain = mono_domain_get ();
9056 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9059 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9063 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9067 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9068 if (!mono_error_ok (error)) {
9069 if (!type_is_reference (mono_method_signature (method)->params [i]))
9074 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9075 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9076 mono_array_setref (typedargs, i, obj);
9078 if (!type_is_reference (mono_method_signature (method)->params [i]))
9083 num_named = read16 (named);
9084 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9086 attrklass = method->klass;
9088 arginfo = g_new0 (CattrNamedArg, num_named);
9089 *named_arg_info = arginfo;
9091 for (j = 0; j < num_named; j++) {
9093 char *name, named_type, data_type;
9094 named_type = *named++;
9095 data_type = *named++; /* type of data */
9096 if (data_type == MONO_TYPE_SZARRAY)
9097 data_type = *named++;
9098 if (data_type == MONO_TYPE_ENUM) {
9101 type_len = mono_metadata_decode_blob_size (named, &named);
9102 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9105 type_name = (char *)g_malloc (type_len + 1);
9106 memcpy (type_name, named, type_len);
9107 type_name [type_len] = 0;
9109 /* FIXME: lookup the type and check type consistency */
9112 name_len = mono_metadata_decode_blob_size (named, &named);
9113 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9115 name = (char *)g_malloc (name_len + 1);
9116 memcpy (name, named, name_len);
9117 name [name_len] = 0;
9119 if (named_type == 0x53) {
9121 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9129 arginfo [j].type = field->type;
9130 arginfo [j].field = field;
9132 val = load_cattr_value (image, field->type, named, &named, error);
9133 if (!mono_error_ok (error)) {
9134 if (!type_is_reference (field->type))
9140 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9141 mono_array_setref (namedargs, j, obj);
9142 if (!type_is_reference (field->type))
9144 } else if (named_type == 0x54) {
9146 MonoType *prop_type;
9147 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9150 if (!prop || !prop->set) {
9155 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9156 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9158 arginfo [j].type = prop_type;
9159 arginfo [j].prop = prop;
9161 val = load_cattr_value (image, prop_type, named, &named, error);
9162 if (!mono_error_ok (error)) {
9163 if (!type_is_reference (prop_type))
9169 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9170 mono_array_setref (namedargs, j, obj);
9171 if (!type_is_reference (prop_type))
9177 *typed_args = typedargs;
9178 *named_args = namedargs;
9181 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9183 *named_arg_info = NULL;
9187 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9190 MonoArray *typedargs, *namedargs;
9193 CattrNamedArg *arginfo = NULL;
9197 mono_error_init (&error);
9205 image = assembly->assembly->image;
9206 method = ref_method->method;
9207 domain = mono_object_domain (ref_method);
9209 if (!mono_class_init (method->klass))
9210 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9212 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9213 if (!mono_error_ok (&error))
9216 if (mono_loader_get_last_error ()) {
9217 mono_error_set_from_loader_error (&error);
9221 if (!typedargs || !namedargs)
9224 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9225 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9226 MonoObject *typedarg;
9228 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9229 mono_array_setref (typedargs, i, typedarg);
9232 for (i = 0; i < mono_array_length (namedargs); ++i) {
9233 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9234 MonoObject *typedarg, *namedarg, *minfo;
9236 if (arginfo [i].prop)
9237 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9239 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9240 if (!mono_error_ok (&error))
9244 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9245 namedarg = create_cattr_named_arg (minfo, typedarg);
9247 mono_array_setref (namedargs, i, namedarg);
9250 *ctor_args = typedargs;
9251 *named_args = namedargs;
9254 mono_error_raise_exception (&error);
9259 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9261 static MonoMethod *ctor;
9268 g_assert (image->assembly);
9271 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9273 domain = mono_domain_get ();
9274 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9275 mono_error_raise_exception (&error); /* FIXME don't raise here */
9276 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9277 mono_error_raise_exception (&error); /* FIXME don't raise here */
9278 params [1] = mono_assembly_get_object (domain, image->assembly);
9279 params [2] = (gpointer)&cattr->data;
9280 params [3] = &cattr->data_size;
9281 mono_runtime_invoke (ctor, attr, params, NULL);
9286 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9292 mono_error_init (error);
9295 for (i = 0; i < cinfo->num_attrs; ++i) {
9296 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9300 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9302 for (i = 0; i < cinfo->num_attrs; ++i) {
9303 if (!cinfo->attrs [i].ctor)
9304 /* The cattr type is not finished yet */
9305 /* We should include the type name but cinfo doesn't contain it */
9306 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9307 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9308 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9309 if (!mono_error_ok (error))
9311 mono_array_setref (result, n, attr);
9319 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9322 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9323 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9329 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9335 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9336 for (i = 0; i < cinfo->num_attrs; ++i) {
9337 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9338 mono_array_setref (result, i, attr);
9344 * mono_custom_attrs_from_index:
9346 * Returns: NULL if no attributes are found or if a loading error occurs.
9349 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9351 guint32 mtoken, i, len;
9352 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9354 MonoCustomAttrInfo *ainfo;
9355 GList *tmp, *list = NULL;
9357 MonoCustomAttrEntry* attr;
9359 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9361 i = mono_metadata_custom_attrs_from_index (image, idx);
9365 while (i < ca->rows) {
9366 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9368 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9371 len = g_list_length (list);
9374 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9375 ainfo->num_attrs = len;
9376 ainfo->image = image;
9377 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9379 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9380 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9381 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9382 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9383 mtoken |= MONO_TOKEN_METHOD_DEF;
9385 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9386 mtoken |= MONO_TOKEN_MEMBER_REF;
9389 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9392 attr = &ainfo->attrs [i - 1];
9393 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9395 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9396 mono_loader_set_error_from_mono_error (&error);
9402 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9403 /*FIXME raising an exception here doesn't make any sense*/
9404 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9409 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9410 attr->data_size = mono_metadata_decode_value (data, &data);
9411 attr->data = (guchar*)data;
9419 mono_custom_attrs_from_method (MonoMethod *method)
9424 * An instantiated method has the same cattrs as the generic method definition.
9426 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9427 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9429 if (method->is_inflated)
9430 method = ((MonoMethodInflated *) method)->declaring;
9432 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9433 return lookup_custom_attr (method->klass->image, method);
9436 /* Synthetic methods */
9439 idx = mono_method_get_index (method);
9440 idx <<= MONO_CUSTOM_ATTR_BITS;
9441 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9442 return mono_custom_attrs_from_index (method->klass->image, idx);
9446 mono_custom_attrs_from_class (MonoClass *klass)
9450 if (klass->generic_class)
9451 klass = klass->generic_class->container_class;
9453 if (image_is_dynamic (klass->image))
9454 return lookup_custom_attr (klass->image, klass);
9456 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9457 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9458 idx <<= MONO_CUSTOM_ATTR_BITS;
9459 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9461 idx = mono_metadata_token_index (klass->type_token);
9462 idx <<= MONO_CUSTOM_ATTR_BITS;
9463 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9465 return mono_custom_attrs_from_index (klass->image, idx);
9469 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9473 if (image_is_dynamic (assembly->image))
9474 return lookup_custom_attr (assembly->image, assembly);
9475 idx = 1; /* there is only one assembly */
9476 idx <<= MONO_CUSTOM_ATTR_BITS;
9477 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9478 return mono_custom_attrs_from_index (assembly->image, idx);
9481 static MonoCustomAttrInfo*
9482 mono_custom_attrs_from_module (MonoImage *image)
9486 if (image_is_dynamic (image))
9487 return lookup_custom_attr (image, image);
9488 idx = 1; /* there is only one module */
9489 idx <<= MONO_CUSTOM_ATTR_BITS;
9490 idx |= MONO_CUSTOM_ATTR_MODULE;
9491 return mono_custom_attrs_from_index (image, idx);
9495 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9499 if (image_is_dynamic (klass->image)) {
9500 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9501 return lookup_custom_attr (klass->image, property);
9503 idx = find_property_index (klass, property);
9504 idx <<= MONO_CUSTOM_ATTR_BITS;
9505 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9506 return mono_custom_attrs_from_index (klass->image, idx);
9510 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9514 if (image_is_dynamic (klass->image)) {
9515 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9516 return lookup_custom_attr (klass->image, event);
9518 idx = find_event_index (klass, event);
9519 idx <<= MONO_CUSTOM_ATTR_BITS;
9520 idx |= MONO_CUSTOM_ATTR_EVENT;
9521 return mono_custom_attrs_from_index (klass->image, idx);
9525 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9528 if (image_is_dynamic (klass->image)) {
9529 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9530 return lookup_custom_attr (klass->image, field);
9532 idx = find_field_index (klass, field);
9533 idx <<= MONO_CUSTOM_ATTR_BITS;
9534 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9535 return mono_custom_attrs_from_index (klass->image, idx);
9539 * mono_custom_attrs_from_param:
9540 * @method: handle to the method that we want to retrieve custom parameter information from
9541 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9543 * The result must be released with mono_custom_attrs_free().
9545 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9548 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9551 guint32 i, idx, method_index;
9552 guint32 param_list, param_last, param_pos, found;
9554 MonoReflectionMethodAux *aux;
9557 * An instantiated method has the same cattrs as the generic method definition.
9559 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9560 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9562 if (method->is_inflated)
9563 method = ((MonoMethodInflated *) method)->declaring;
9565 if (image_is_dynamic (method->klass->image)) {
9566 MonoCustomAttrInfo *res, *ainfo;
9569 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9570 if (!aux || !aux->param_cattr)
9573 /* Need to copy since it will be freed later */
9574 ainfo = aux->param_cattr [param];
9577 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9578 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9579 memcpy (res, ainfo, size);
9583 image = method->klass->image;
9584 method_index = mono_method_get_index (method);
9587 ca = &image->tables [MONO_TABLE_METHOD];
9589 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9590 if (method_index == ca->rows) {
9591 ca = &image->tables [MONO_TABLE_PARAM];
9592 param_last = ca->rows + 1;
9594 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9595 ca = &image->tables [MONO_TABLE_PARAM];
9598 for (i = param_list; i < param_last; ++i) {
9599 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9600 if (param_pos == param) {
9608 idx <<= MONO_CUSTOM_ATTR_BITS;
9609 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9610 return mono_custom_attrs_from_index (image, idx);
9614 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9618 for (i = 0; i < ainfo->num_attrs; ++i) {
9619 klass = ainfo->attrs [i].ctor->klass;
9620 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9627 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9630 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9631 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9636 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9642 mono_error_init (error);
9645 for (i = 0; i < ainfo->num_attrs; ++i) {
9646 klass = ainfo->attrs [i].ctor->klass;
9647 if (mono_class_has_parent (klass, attr_klass)) {
9652 if (attr_index == -1)
9655 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9656 if (!mono_error_ok (error))
9658 return mono_array_get (attrs, MonoObject*, attr_index);
9662 * mono_reflection_get_custom_attrs_info:
9663 * @obj: a reflection object handle
9665 * Return the custom attribute info for attributes defined for the
9666 * reflection handle @obj. The objects.
9668 * FIXME this function leaks like a sieve for SRE objects.
9671 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9674 MonoCustomAttrInfo *cinfo = NULL;
9676 klass = obj->vtable->klass;
9677 if (klass == mono_defaults.monotype_class) {
9678 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9679 klass = mono_class_from_mono_type (type);
9680 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9681 cinfo = mono_custom_attrs_from_class (klass);
9682 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9683 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9684 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9685 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9686 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9687 cinfo = mono_custom_attrs_from_module (module->image);
9688 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9689 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9690 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9691 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9692 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9693 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9694 } else if (strcmp ("MonoField", klass->name) == 0) {
9695 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9696 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9697 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9698 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9699 cinfo = mono_custom_attrs_from_method (rmethod->method);
9700 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9701 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9702 cinfo = mono_custom_attrs_from_method (rmethod->method);
9703 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9704 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9705 MonoClass *member_class = mono_object_class (param->MemberImpl);
9706 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9707 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9708 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9709 } else if (is_sr_mono_property (member_class)) {
9710 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9712 if (!(method = prop->property->get))
9713 method = prop->property->set;
9716 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9718 #ifndef DISABLE_REFLECTION_EMIT
9719 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9720 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9721 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9722 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9723 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9724 MonoMethod *method = NULL;
9725 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9726 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9727 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9728 method = ((MonoReflectionMethod *)c->cb)->method;
9730 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));
9732 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9736 char *type_name = mono_type_get_full_name (member_class);
9737 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9738 MonoException *ex = mono_get_exception_not_supported (msg);
9741 mono_raise_exception (ex);
9743 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9744 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9745 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9746 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9747 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9748 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9749 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9750 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9751 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9752 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9753 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9754 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9755 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9756 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9757 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9758 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9759 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9760 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9761 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9762 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9763 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9764 } else { /* handle other types here... */
9765 g_error ("get custom attrs not yet supported for %s", klass->name);
9772 * mono_reflection_get_custom_attrs_by_type:
9773 * @obj: a reflection object handle
9775 * Return an array with all the custom attributes defined of the
9776 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9777 * of that type are returned. The objects are fully build. Return NULL if a loading error
9781 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9784 MonoCustomAttrInfo *cinfo;
9786 mono_error_init (error);
9788 cinfo = mono_reflection_get_custom_attrs_info (obj);
9790 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9792 mono_custom_attrs_free (cinfo);
9794 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9795 if (mono_loader_get_last_error ())
9797 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9804 * mono_reflection_get_custom_attrs:
9805 * @obj: a reflection object handle
9807 * Return an array with all the custom attributes defined of the
9808 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9812 mono_reflection_get_custom_attrs (MonoObject *obj)
9816 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9820 * mono_reflection_get_custom_attrs_data:
9821 * @obj: a reflection obj handle
9823 * Returns an array of System.Reflection.CustomAttributeData,
9824 * which include information about attributes reflected on
9825 * types loaded using the Reflection Only methods
9828 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9831 MonoCustomAttrInfo *cinfo;
9833 cinfo = mono_reflection_get_custom_attrs_info (obj);
9835 result = mono_custom_attrs_data_construct (cinfo);
9837 mono_custom_attrs_free (cinfo);
9839 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9844 static MonoReflectionType*
9845 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9847 static MonoMethod *method_get_underlying_system_type = NULL;
9848 MonoMethod *usertype_method;
9850 if (!method_get_underlying_system_type)
9851 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9852 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9853 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9858 is_corlib_type (MonoClass *klass)
9860 return klass->image == mono_defaults.corlib;
9863 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9864 static MonoClass *cached_class; \
9866 return cached_class == _class; \
9867 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9868 cached_class = _class; \
9875 #ifndef DISABLE_REFLECTION_EMIT
9877 is_sre_array (MonoClass *klass)
9879 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9883 is_sre_byref (MonoClass *klass)
9885 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9889 is_sre_pointer (MonoClass *klass)
9891 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9895 is_sre_generic_instance (MonoClass *klass)
9897 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9901 is_sre_type_builder (MonoClass *klass)
9903 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9907 is_sre_method_builder (MonoClass *klass)
9909 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9913 is_sre_ctor_builder (MonoClass *klass)
9915 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9919 is_sre_field_builder (MonoClass *klass)
9921 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9925 is_sre_method_on_tb_inst (MonoClass *klass)
9927 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9931 is_sre_ctor_on_tb_inst (MonoClass *klass)
9933 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9937 mono_reflection_type_get_handle (MonoReflectionType* ref)
9945 if (is_usertype (ref)) {
9946 ref = mono_reflection_type_get_underlying_system_type (ref);
9947 if (ref == NULL || is_usertype (ref))
9953 klass = mono_object_class (ref);
9955 if (is_sre_array (klass)) {
9957 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9958 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9960 if (sre_array->rank == 0) //single dimentional array
9961 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9963 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9964 sre_array->type.type = res;
9966 } else if (is_sre_byref (klass)) {
9968 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9969 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9971 res = &mono_class_from_mono_type (base)->this_arg;
9972 sre_byref->type.type = res;
9974 } else if (is_sre_pointer (klass)) {
9976 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9977 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9979 res = &mono_ptr_class_get (base)->byval_arg;
9980 sre_pointer->type.type = res;
9982 } else if (is_sre_generic_instance (klass)) {
9983 MonoType *res, **types;
9984 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9987 count = mono_array_length (gclass->type_arguments);
9988 types = g_new0 (MonoType*, count);
9989 for (i = 0; i < count; ++i) {
9990 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9991 types [i] = mono_reflection_type_get_handle (t);
9998 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10001 gclass->type.type = res;
10005 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10012 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10014 mono_reflection_type_get_handle (type);
10018 mono_reflection_register_with_runtime (MonoReflectionType *type)
10020 MonoType *res = mono_reflection_type_get_handle (type);
10021 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10025 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10027 klass = mono_class_from_mono_type (res);
10029 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10030 mono_domain_lock (domain);
10032 if (!image_is_dynamic (klass->image)) {
10033 mono_class_setup_supertypes (klass);
10035 if (!domain->type_hash)
10036 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10037 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10038 mono_g_hash_table_insert (domain->type_hash, res, type);
10040 mono_domain_unlock (domain);
10041 mono_loader_unlock ();
10045 * LOCKING: Assumes the loader lock is held.
10047 static MonoMethodSignature*
10048 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10049 MonoMethodSignature *sig;
10052 count = parameters? mono_array_length (parameters): 0;
10054 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10055 sig->param_count = count;
10056 sig->sentinelpos = -1; /* FIXME */
10057 for (i = 0; i < count; ++i)
10058 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10063 * LOCKING: Assumes the loader lock is held.
10065 static MonoMethodSignature*
10066 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10067 MonoMethodSignature *sig;
10069 sig = parameters_to_signature (image, ctor->parameters);
10070 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10071 sig->ret = &mono_defaults.void_class->byval_arg;
10076 * LOCKING: Assumes the loader lock is held.
10078 static MonoMethodSignature*
10079 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10080 MonoMethodSignature *sig;
10082 sig = parameters_to_signature (image, method->parameters);
10083 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10084 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10085 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10089 static MonoMethodSignature*
10090 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10091 MonoMethodSignature *sig;
10093 sig = parameters_to_signature (NULL, method->parameters);
10094 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10095 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10096 sig->generic_param_count = 0;
10101 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10103 MonoClass *klass = mono_object_class (prop);
10104 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10105 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10106 *name = mono_string_to_utf8 (pb->name);
10107 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10109 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10110 *name = g_strdup (p->property->name);
10111 if (p->property->get)
10112 *type = mono_method_signature (p->property->get)->ret;
10114 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10119 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10121 MonoClass *klass = mono_object_class (field);
10122 if (strcmp (klass->name, "FieldBuilder") == 0) {
10123 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10124 *name = mono_string_to_utf8 (fb->name);
10125 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10127 MonoReflectionField *f = (MonoReflectionField *)field;
10128 *name = g_strdup (mono_field_get_name (f->field));
10129 *type = f->field->type;
10133 #else /* DISABLE_REFLECTION_EMIT */
10136 mono_reflection_register_with_runtime (MonoReflectionType *type)
10138 /* This is empty */
10142 is_sre_type_builder (MonoClass *klass)
10148 is_sre_generic_instance (MonoClass *klass)
10154 init_type_builder_generics (MonoObject *type)
10158 #endif /* !DISABLE_REFLECTION_EMIT */
10162 is_sr_mono_field (MonoClass *klass)
10164 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10168 is_sr_mono_property (MonoClass *klass)
10170 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10174 is_sr_mono_method (MonoClass *klass)
10176 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10180 is_sr_mono_cmethod (MonoClass *klass)
10182 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10186 is_sr_mono_generic_method (MonoClass *klass)
10188 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10192 is_sr_mono_generic_cmethod (MonoClass *klass)
10194 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10198 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10200 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10204 is_usertype (MonoReflectionType *ref)
10206 MonoClass *klass = mono_object_class (ref);
10207 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10210 static MonoReflectionType*
10211 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10213 mono_error_init (error);
10214 if (!type || type->type)
10217 if (is_usertype (type)) {
10218 type = mono_reflection_type_get_underlying_system_type (type);
10219 if (is_usertype (type)) {
10220 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10228 * Encode a value in a custom attribute stream of bytes.
10229 * The value to encode is either supplied as an object in argument val
10230 * (valuetypes are boxed), or as a pointer to the data in the
10232 * @type represents the type of the value
10233 * @buffer is the start of the buffer
10234 * @p the current position in the buffer
10235 * @buflen contains the size of the buffer and is used to return the new buffer size
10236 * if this needs to be realloced.
10237 * @retbuffer and @retp return the start and the position of the buffer
10240 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10242 MonoTypeEnum simple_type;
10244 if ((p-buffer) + 10 >= *buflen) {
10247 newbuf = (char *)g_realloc (buffer, *buflen);
10248 p = newbuf + (p-buffer);
10252 argval = ((char*)arg + sizeof (MonoObject));
10253 simple_type = type->type;
10255 switch (simple_type) {
10256 case MONO_TYPE_BOOLEAN:
10261 case MONO_TYPE_CHAR:
10264 swap_with_size (p, argval, 2, 1);
10270 swap_with_size (p, argval, 4, 1);
10274 swap_with_size (p, argval, 8, 1);
10279 swap_with_size (p, argval, 8, 1);
10282 case MONO_TYPE_VALUETYPE:
10283 if (type->data.klass->enumtype) {
10284 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10287 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10290 case MONO_TYPE_STRING: {
10297 str = mono_string_to_utf8 ((MonoString*)arg);
10298 slen = strlen (str);
10299 if ((p-buffer) + 10 + slen >= *buflen) {
10303 newbuf = (char *)g_realloc (buffer, *buflen);
10304 p = newbuf + (p-buffer);
10307 mono_metadata_encode_value (slen, p, &p);
10308 memcpy (p, str, slen);
10313 case MONO_TYPE_CLASS: {
10321 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10322 slen = strlen (str);
10323 if ((p-buffer) + 10 + slen >= *buflen) {
10327 newbuf = (char *)g_realloc (buffer, *buflen);
10328 p = newbuf + (p-buffer);
10331 mono_metadata_encode_value (slen, p, &p);
10332 memcpy (p, str, slen);
10337 case MONO_TYPE_SZARRAY: {
10339 MonoClass *eclass, *arg_eclass;
10342 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10345 len = mono_array_length ((MonoArray*)arg);
10347 *p++ = (len >> 8) & 0xff;
10348 *p++ = (len >> 16) & 0xff;
10349 *p++ = (len >> 24) & 0xff;
10351 *retbuffer = buffer;
10352 eclass = type->data.klass;
10353 arg_eclass = mono_object_class (arg)->element_class;
10356 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10357 eclass = mono_defaults.object_class;
10359 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10360 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10361 int elsize = mono_class_array_element_size (arg_eclass);
10362 for (i = 0; i < len; ++i) {
10363 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10366 } else if (eclass->valuetype && arg_eclass->valuetype) {
10367 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10368 int elsize = mono_class_array_element_size (eclass);
10369 for (i = 0; i < len; ++i) {
10370 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10374 for (i = 0; i < len; ++i) {
10375 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10380 case MONO_TYPE_OBJECT: {
10386 * The parameter type is 'object' but the type of the actual
10387 * argument is not. So we have to add type information to the blob
10388 * too. This is completely undocumented in the spec.
10392 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10397 klass = mono_object_class (arg);
10399 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10402 } else if (klass->enumtype) {
10404 } else if (klass == mono_defaults.string_class) {
10405 simple_type = MONO_TYPE_STRING;
10408 } else if (klass->rank == 1) {
10410 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10411 /* See Partition II, Appendix B3 */
10414 *p++ = klass->element_class->byval_arg.type;
10415 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10417 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10418 *p++ = simple_type = klass->byval_arg.type;
10421 g_error ("unhandled type in custom attr");
10423 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10424 slen = strlen (str);
10425 if ((p-buffer) + 10 + slen >= *buflen) {
10429 newbuf = (char *)g_realloc (buffer, *buflen);
10430 p = newbuf + (p-buffer);
10433 mono_metadata_encode_value (slen, p, &p);
10434 memcpy (p, str, slen);
10437 simple_type = mono_class_enum_basetype (klass)->type;
10441 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10444 *retbuffer = buffer;
10448 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10450 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10451 char *str = type_get_qualified_name (type, NULL);
10452 int slen = strlen (str);
10456 * This seems to be optional...
10459 mono_metadata_encode_value (slen, p, &p);
10460 memcpy (p, str, slen);
10463 } else if (type->type == MONO_TYPE_OBJECT) {
10465 } else if (type->type == MONO_TYPE_CLASS) {
10466 /* it should be a type: encode_cattr_value () has the check */
10469 mono_metadata_encode_value (type->type, p, &p);
10470 if (type->type == MONO_TYPE_SZARRAY)
10471 /* See the examples in Partition VI, Annex B */
10472 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10478 #ifndef DISABLE_REFLECTION_EMIT
10480 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10483 /* Preallocate a large enough buffer */
10484 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10485 char *str = type_get_qualified_name (type, NULL);
10486 len = strlen (str);
10488 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10489 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10490 len = strlen (str);
10495 len += strlen (name);
10497 if ((p-buffer) + 20 + len >= *buflen) {
10501 newbuf = (char *)g_realloc (buffer, *buflen);
10502 p = newbuf + (p-buffer);
10506 encode_field_or_prop_type (type, p, &p);
10508 len = strlen (name);
10509 mono_metadata_encode_value (len, p, &p);
10510 memcpy (p, name, len);
10512 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10514 *retbuffer = buffer;
10518 * mono_reflection_get_custom_attrs_blob:
10519 * @ctor: custom attribute constructor
10520 * @ctorArgs: arguments o the constructor
10526 * Creates the blob of data that needs to be saved in the metadata and that represents
10527 * the custom attributed described by @ctor, @ctorArgs etc.
10528 * Returns: a Byte array representing the blob of data.
10531 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10534 MonoMethodSignature *sig;
10539 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10540 /* sig is freed later so allocate it in the heap */
10541 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10543 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10546 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10548 p = buffer = (char *)g_malloc (buflen);
10549 /* write the prolog */
10552 for (i = 0; i < sig->param_count; ++i) {
10553 arg = mono_array_get (ctorArgs, MonoObject*, i);
10554 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10558 i += mono_array_length (properties);
10560 i += mono_array_length (fields);
10562 *p++ = (i >> 8) & 0xff;
10565 for (i = 0; i < mono_array_length (properties); ++i) {
10569 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10570 get_prop_name_and_type (prop, &pname, &ptype);
10571 *p++ = 0x54; /* PROPERTY signature */
10572 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10579 for (i = 0; i < mono_array_length (fields); ++i) {
10583 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10584 get_field_name_and_type (field, &fname, &ftype);
10585 *p++ = 0x53; /* FIELD signature */
10586 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10591 g_assert (p - buffer <= buflen);
10592 buflen = p - buffer;
10593 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10594 p = mono_array_addr (result, char, 0);
10595 memcpy (p, buffer, buflen);
10597 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10603 * mono_reflection_setup_internal_class:
10604 * @tb: a TypeBuilder object
10606 * Creates a MonoClass that represents the TypeBuilder.
10607 * This is a trick that lets us simplify a lot of reflection code
10608 * (and will allow us to support Build and Run assemblies easier).
10611 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10614 MonoClass *klass, *parent;
10616 RESOLVE_TYPE (tb->parent, &error);
10617 mono_error_raise_exception (&error); /* FIXME don't raise here */
10619 mono_loader_lock ();
10622 /* check so we can compile corlib correctly */
10623 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10624 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10625 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10627 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10633 /* the type has already being created: it means we just have to change the parent */
10634 if (tb->type.type) {
10635 klass = mono_class_from_mono_type (tb->type.type);
10636 klass->parent = NULL;
10637 /* fool mono_class_setup_parent */
10638 klass->supertypes = NULL;
10639 mono_class_setup_parent (klass, parent);
10640 mono_class_setup_mono_type (klass);
10641 mono_loader_unlock ();
10645 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10647 klass->image = &tb->module->dynamic_image->image;
10649 klass->inited = 1; /* we lie to the runtime */
10650 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10651 if (!mono_error_ok (&error))
10653 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10654 if (!mono_error_ok (&error))
10656 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10657 klass->flags = tb->attrs;
10659 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10661 klass->element_class = klass;
10663 if (mono_class_get_ref_info (klass) == NULL) {
10665 mono_class_set_ref_info (klass, tb);
10667 /* Put into cache so mono_class_get_checked () will find it.
10668 Skip nested types as those should not be available on the global scope. */
10669 if (!tb->nesting_type)
10670 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10673 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10674 by performing a mono_class_get which does the full resolution.
10676 Working around this semantics would require us to write a lot of code for no clear advantage.
10678 mono_image_append_class_to_reflection_info_set (klass);
10680 g_assert (mono_class_get_ref_info (klass) == tb);
10683 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10685 if (parent != NULL) {
10686 mono_class_setup_parent (klass, parent);
10687 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10688 const char *old_n = klass->name;
10689 /* trick to get relative numbering right when compiling corlib */
10690 klass->name = "BuildingObject";
10691 mono_class_setup_parent (klass, mono_defaults.object_class);
10692 klass->name = old_n;
10695 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10696 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10697 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10698 klass->instance_size = sizeof (MonoObject);
10699 klass->size_inited = 1;
10700 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10703 mono_class_setup_mono_type (klass);
10705 mono_class_setup_supertypes (klass);
10708 * FIXME: handle interfaces.
10711 tb->type.type = &klass->byval_arg;
10713 if (tb->nesting_type) {
10714 g_assert (tb->nesting_type->type);
10715 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10718 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10720 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10722 mono_loader_unlock ();
10726 mono_loader_unlock ();
10727 mono_error_raise_exception (&error);
10731 * mono_reflection_setup_generic_class:
10732 * @tb: a TypeBuilder object
10734 * Setup the generic class before adding the first generic parameter.
10737 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10742 * mono_reflection_create_generic_class:
10743 * @tb: a TypeBuilder object
10745 * Creates the generic class after all generic parameters have been added.
10748 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10753 klass = mono_class_from_mono_type (tb->type.type);
10755 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10757 if (klass->generic_container || (count == 0))
10760 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10762 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10764 klass->generic_container->owner.klass = klass;
10765 klass->generic_container->type_argc = count;
10766 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10768 klass->is_generic = 1;
10770 for (i = 0; i < count; i++) {
10771 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10772 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10773 klass->generic_container->type_params [i] = *param;
10774 /*Make sure we are a diferent type instance */
10775 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10776 klass->generic_container->type_params [i].info.pklass = NULL;
10777 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10779 g_assert (klass->generic_container->type_params [i].param.owner);
10782 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10786 * mono_reflection_create_internal_class:
10787 * @tb: a TypeBuilder object
10789 * Actually create the MonoClass that is associated with the TypeBuilder.
10792 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10796 klass = mono_class_from_mono_type (tb->type.type);
10798 mono_loader_lock ();
10799 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10800 MonoReflectionFieldBuilder *fb;
10802 MonoType *enum_basetype;
10804 g_assert (tb->fields != NULL);
10805 g_assert (mono_array_length (tb->fields) >= 1);
10807 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10809 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10810 mono_loader_unlock ();
10814 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10815 klass->element_class = mono_class_from_mono_type (enum_basetype);
10816 if (!klass->element_class)
10817 klass->element_class = mono_class_from_mono_type (enum_basetype);
10820 * get the element_class from the current corlib.
10822 ec = default_class_from_mono_type (enum_basetype);
10823 klass->instance_size = ec->instance_size;
10824 klass->size_inited = 1;
10826 * this is almost safe to do with enums and it's needed to be able
10827 * to create objects of the enum type (for use in SetConstant).
10829 /* FIXME: Does this mean enums can't have method overrides ? */
10830 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10832 mono_loader_unlock ();
10835 static MonoMarshalSpec*
10836 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10837 MonoReflectionMarshal *minfo)
10839 MonoMarshalSpec *res;
10841 res = image_g_new0 (image, MonoMarshalSpec, 1);
10842 res->native = (MonoMarshalNative)minfo->type;
10844 switch (minfo->type) {
10845 case MONO_NATIVE_LPARRAY:
10846 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10847 if (minfo->has_size) {
10848 res->data.array_data.param_num = minfo->param_num;
10849 res->data.array_data.num_elem = minfo->count;
10850 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10853 res->data.array_data.param_num = -1;
10854 res->data.array_data.num_elem = -1;
10855 res->data.array_data.elem_mult = -1;
10859 case MONO_NATIVE_BYVALTSTR:
10860 case MONO_NATIVE_BYVALARRAY:
10861 res->data.array_data.num_elem = minfo->count;
10864 case MONO_NATIVE_CUSTOM:
10865 if (minfo->marshaltyperef)
10866 res->data.custom_data.custom_name =
10867 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10868 if (minfo->mcookie)
10869 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10878 #endif /* !DISABLE_REFLECTION_EMIT */
10880 MonoReflectionMarshalAsAttribute*
10881 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10882 MonoMarshalSpec *spec)
10884 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10886 MonoReflectionType *rt;
10887 MonoReflectionMarshalAsAttribute *minfo;
10890 if (!System_Reflection_Emit_MarshalAsAttribute) {
10891 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10892 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10893 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10896 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10897 mono_error_raise_exception (&error); /* FIXME don't raise here */
10898 minfo->utype = spec->native;
10900 switch (minfo->utype) {
10901 case MONO_NATIVE_LPARRAY:
10902 minfo->array_subtype = spec->data.array_data.elem_type;
10903 minfo->size_const = spec->data.array_data.num_elem;
10904 if (spec->data.array_data.param_num != -1)
10905 minfo->size_param_index = spec->data.array_data.param_num;
10908 case MONO_NATIVE_BYVALTSTR:
10909 case MONO_NATIVE_BYVALARRAY:
10910 minfo->size_const = spec->data.array_data.num_elem;
10913 case MONO_NATIVE_CUSTOM:
10914 if (spec->data.custom_data.custom_name) {
10915 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10917 rt = mono_type_get_object_checked (domain, mtype, &error);
10918 mono_error_raise_exception (&error); /* FIXME don't raise here */
10920 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10923 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10925 if (spec->data.custom_data.cookie)
10926 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10936 #ifndef DISABLE_REFLECTION_EMIT
10938 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10939 ReflectionMethodBuilder *rmb,
10940 MonoMethodSignature *sig)
10944 MonoMethodWrapper *wrapperm;
10945 MonoMarshalSpec **specs;
10946 MonoReflectionMethodAux *method_aux;
10951 mono_error_init (&error);
10953 * Methods created using a MethodBuilder should have their memory allocated
10954 * inside the image mempool, while dynamic methods should have their memory
10957 dynamic = rmb->refs != NULL;
10958 image = dynamic ? NULL : klass->image;
10961 g_assert (!klass->generic_class);
10963 mono_loader_lock ();
10965 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10966 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10967 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10969 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10971 wrapperm = (MonoMethodWrapper*)m;
10973 m->dynamic = dynamic;
10975 m->flags = rmb->attrs;
10976 m->iflags = rmb->iattrs;
10977 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10979 m->signature = sig;
10980 m->sre_method = TRUE;
10981 m->skip_visibility = rmb->skip_visibility;
10982 if (rmb->table_idx)
10983 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10985 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10986 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10987 m->string_ctor = 1;
10989 m->signature->pinvoke = 1;
10990 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10991 m->signature->pinvoke = 1;
10993 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10995 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10996 g_assert (mono_error_ok (&error));
10997 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10998 g_assert (mono_error_ok (&error));
11000 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11002 if (image_is_dynamic (klass->image))
11003 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11005 mono_loader_unlock ();
11008 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11009 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11010 MonoMethodHeader *header;
11012 gint32 max_stack, i;
11013 gint32 num_locals = 0;
11014 gint32 num_clauses = 0;
11018 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11019 code_size = rmb->ilgen->code_len;
11020 max_stack = rmb->ilgen->max_stack;
11021 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11022 if (rmb->ilgen->ex_handlers)
11023 num_clauses = method_count_clauses (rmb->ilgen);
11026 code = mono_array_addr (rmb->code, guint8, 0);
11027 code_size = mono_array_length (rmb->code);
11028 /* we probably need to run a verifier on the code... */
11038 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11039 header->code_size = code_size;
11040 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11041 memcpy ((char*)header->code, code, code_size);
11042 header->max_stack = max_stack;
11043 header->init_locals = rmb->init_locals;
11044 header->num_locals = num_locals;
11046 for (i = 0; i < num_locals; ++i) {
11047 MonoReflectionLocalBuilder *lb =
11048 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11050 header->locals [i] = image_g_new0 (image, MonoType, 1);
11051 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11054 header->num_clauses = num_clauses;
11056 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11057 rmb->ilgen, num_clauses);
11060 wrapperm->header = header;
11063 if (rmb->generic_params) {
11064 int count = mono_array_length (rmb->generic_params);
11065 MonoGenericContainer *container = rmb->generic_container;
11067 g_assert (container);
11069 container->type_argc = count;
11070 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11071 container->owner.method = m;
11072 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11074 m->is_generic = TRUE;
11075 mono_method_set_generic_container (m, container);
11077 for (i = 0; i < count; i++) {
11078 MonoReflectionGenericParam *gp =
11079 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11080 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11081 container->type_params [i] = *param;
11085 * The method signature might have pointers to generic parameters that belong to other methods.
11086 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11087 * generic parameters.
11089 for (i = 0; i < m->signature->param_count; ++i) {
11090 MonoType *t = m->signature->params [i];
11091 if (t->type == MONO_TYPE_MVAR) {
11092 MonoGenericParam *gparam = t->data.generic_param;
11093 if (gparam->num < count) {
11094 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11095 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11101 if (klass->generic_container) {
11102 container->parent = klass->generic_container;
11103 container->context.class_inst = klass->generic_container->context.class_inst;
11105 container->context.method_inst = mono_get_shared_generic_inst (container);
11109 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11113 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11115 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11116 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11117 for (i = 0; i < rmb->nrefs; ++i)
11118 data [i + 1] = rmb->refs [i];
11123 /* Parameter info */
11126 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11127 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11128 for (i = 0; i <= m->signature->param_count; ++i) {
11129 MonoReflectionParamBuilder *pb;
11130 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11131 if ((i > 0) && (pb->attrs)) {
11132 /* Make a copy since it might point to a shared type structure */
11133 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11134 m->signature->params [i - 1]->attrs = pb->attrs;
11137 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11138 MonoDynamicImage *assembly;
11140 MonoTypeEnum def_type;
11144 if (!method_aux->param_defaults) {
11145 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11146 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11148 assembly = (MonoDynamicImage*)klass->image;
11149 idx = encode_constant (assembly, pb->def_value, &def_type);
11150 /* Copy the data from the blob since it might get realloc-ed */
11151 p = assembly->blob.data + idx;
11152 len = mono_metadata_decode_blob_size (p, &p2);
11154 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11155 method_aux->param_default_types [i] = def_type;
11156 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11160 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11161 g_assert (mono_error_ok (&error));
11164 if (!method_aux->param_cattr)
11165 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11166 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11172 /* Parameter marshalling */
11175 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11176 MonoReflectionParamBuilder *pb;
11177 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11178 if (pb->marshal_info) {
11180 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11181 specs [pb->position] =
11182 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11186 if (specs != NULL) {
11188 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11189 method_aux->param_marshall = specs;
11192 if (image_is_dynamic (klass->image) && method_aux)
11193 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11195 mono_loader_unlock ();
11201 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11204 ReflectionMethodBuilder rmb;
11205 MonoMethodSignature *sig;
11207 mono_loader_lock ();
11208 sig = ctor_builder_to_signature (klass->image, mb);
11209 mono_loader_unlock ();
11211 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, &error))
11212 mono_error_raise_exception (&error); /* FIXME don't raise here*/
11214 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11215 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11217 /* If we are in a generic class, we might be called multiple times from inflate_method */
11218 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11219 /* ilgen is no longer needed */
11223 return mb->mhandle;
11227 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11230 ReflectionMethodBuilder rmb;
11231 MonoMethodSignature *sig;
11233 mono_loader_lock ();
11234 sig = method_builder_to_signature (klass->image, mb);
11235 mono_loader_unlock ();
11237 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
11238 mono_error_raise_exception (&error); /* FIXME don't raise here */
11240 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11241 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11243 /* If we are in a generic class, we might be called multiple times from inflate_method */
11244 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11245 /* ilgen is no longer needed */
11248 return mb->mhandle;
11251 static MonoClassField*
11252 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11254 MonoClassField *field;
11258 field = g_new0 (MonoClassField, 1);
11260 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11261 g_assert (mono_error_ok (&error));
11262 if (fb->attrs || fb->modreq || fb->modopt) {
11263 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11264 field->type->attrs = fb->attrs;
11266 g_assert (image_is_dynamic (klass->image));
11267 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11268 g_free (field->type);
11269 field->type = mono_metadata_type_dup (klass->image, custom);
11272 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11274 if (fb->offset != -1)
11275 field->offset = fb->offset;
11276 field->parent = klass;
11277 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11279 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11286 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11289 MonoReflectionTypeBuilder *tb = NULL;
11290 gboolean is_dynamic = FALSE;
11291 MonoClass *geninst;
11293 mono_loader_lock ();
11295 if (is_sre_type_builder (mono_object_class (type))) {
11296 tb = (MonoReflectionTypeBuilder *) type;
11299 } else if (is_sre_generic_instance (mono_object_class (type))) {
11300 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11301 MonoReflectionType *gtd = rgi->generic_type;
11303 if (is_sre_type_builder (mono_object_class (gtd))) {
11304 tb = (MonoReflectionTypeBuilder *)gtd;
11309 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11310 if (tb && tb->generic_container)
11311 mono_reflection_create_generic_class (tb);
11313 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11314 if (!klass->generic_container) {
11315 mono_loader_unlock ();
11319 if (klass->wastypebuilder) {
11320 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11325 mono_loader_unlock ();
11327 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11329 return &geninst->byval_arg;
11333 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11335 MonoGenericClass *gclass;
11336 MonoGenericInst *inst;
11338 g_assert (klass->generic_container);
11340 inst = mono_metadata_get_generic_inst (type_argc, types);
11341 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11343 return mono_generic_class_get_class (gclass);
11346 MonoReflectionMethod*
11347 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11351 MonoMethod *method, *inflated;
11352 MonoMethodInflated *imethod;
11353 MonoGenericContext tmp_context;
11354 MonoGenericInst *ginst;
11355 MonoType **type_argv;
11358 /*FIXME but this no longer should happen*/
11359 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11360 #ifndef DISABLE_REFLECTION_EMIT
11361 MonoReflectionMethodBuilder *mb = NULL;
11362 MonoReflectionTypeBuilder *tb;
11365 mb = (MonoReflectionMethodBuilder *) rmethod;
11366 tb = (MonoReflectionTypeBuilder *) mb->type;
11367 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11369 method = methodbuilder_to_mono_method (klass, mb);
11371 g_assert_not_reached ();
11375 method = rmethod->method;
11378 klass = method->klass;
11380 if (method->is_inflated)
11381 method = ((MonoMethodInflated *) method)->declaring;
11383 count = mono_method_signature (method)->generic_param_count;
11384 if (count != mono_array_length (types))
11387 type_argv = g_new0 (MonoType *, count);
11388 for (i = 0; i < count; i++) {
11389 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11390 type_argv [i] = mono_reflection_type_get_handle (garg);
11392 ginst = mono_metadata_get_generic_inst (count, type_argv);
11393 g_free (type_argv);
11395 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11396 tmp_context.method_inst = ginst;
11398 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11399 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11400 imethod = (MonoMethodInflated *) inflated;
11402 /*FIXME but I think this is no longer necessary*/
11403 if (image_is_dynamic (method->klass->image)) {
11404 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11406 * This table maps metadata structures representing inflated methods/fields
11407 * to the reflection objects representing their generic definitions.
11409 mono_image_lock ((MonoImage*)image);
11410 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11411 mono_image_unlock ((MonoImage*)image);
11414 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11415 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11417 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11418 mono_error_raise_exception (&error); /* FIXME don't raise here */
11422 #ifndef DISABLE_REFLECTION_EMIT
11424 static MonoMethod *
11425 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11427 MonoMethodInflated *imethod;
11428 MonoGenericContext *context;
11432 * With generic code sharing the klass might not be inflated.
11433 * This can happen because classes inflated with their own
11434 * type arguments are "normalized" to the uninflated class.
11436 if (!klass->generic_class)
11439 context = mono_class_get_context (klass);
11441 if (klass->method.count && klass->methods) {
11442 /* Find the already created inflated method */
11443 for (i = 0; i < klass->method.count; ++i) {
11444 g_assert (klass->methods [i]->is_inflated);
11445 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11448 g_assert (i < klass->method.count);
11449 imethod = (MonoMethodInflated*)klass->methods [i];
11452 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11453 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11456 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11457 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11459 mono_image_lock ((MonoImage*)image);
11460 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11461 mono_image_unlock ((MonoImage*)image);
11463 return (MonoMethod *) imethod;
11466 static MonoMethod *
11467 inflate_method (MonoReflectionType *type, MonoObject *obj)
11469 MonoMethod *method;
11472 MonoClass *type_class = mono_object_class (type);
11474 if (is_sre_generic_instance (type_class)) {
11475 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11476 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11477 } else if (is_sre_type_builder (type_class)) {
11478 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11479 } else if (type->type) {
11480 gklass = mono_class_from_mono_type (type->type);
11481 gklass = mono_class_get_generic_type_definition (gklass);
11483 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11486 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11487 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11488 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11490 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11491 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11492 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11493 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11494 method = ((MonoReflectionMethod *) obj)->method;
11496 method = NULL; /* prevent compiler warning */
11497 g_error ("can't handle type %s", obj->vtable->klass->name);
11500 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11503 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11505 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11507 MonoGenericClass *gclass;
11508 MonoDynamicGenericClass *dgclass;
11509 MonoClass *klass, *gklass;
11513 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11514 klass = mono_class_from_mono_type (gtype);
11515 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11516 gclass = gtype->data.generic_class;
11518 if (!gclass->is_dynamic)
11521 dgclass = (MonoDynamicGenericClass *) gclass;
11523 if (dgclass->initialized)
11526 gklass = gclass->container_class;
11527 mono_class_init (gklass);
11529 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11531 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11532 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11533 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11535 for (i = 0; i < dgclass->count_fields; i++) {
11536 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11537 MonoClassField *field, *inflated_field = NULL;
11539 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11540 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11541 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11542 field = ((MonoReflectionField *) obj)->field;
11544 field = NULL; /* prevent compiler warning */
11545 g_assert_not_reached ();
11548 dgclass->fields [i] = *field;
11549 dgclass->fields [i].parent = klass;
11550 dgclass->fields [i].type = mono_class_inflate_generic_type (
11551 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11552 dgclass->field_generic_types [i] = field->type;
11553 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11554 dgclass->field_objects [i] = obj;
11556 if (inflated_field) {
11557 g_free (inflated_field);
11559 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11563 dgclass->initialized = TRUE;
11567 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11569 MonoDynamicGenericClass *dgclass;
11572 g_assert (gclass->is_dynamic);
11574 dgclass = (MonoDynamicGenericClass *)gclass;
11576 for (i = 0; i < dgclass->count_fields; ++i) {
11577 MonoClassField *field = dgclass->fields + i;
11578 mono_metadata_free_type (field->type);
11579 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11584 fix_partial_generic_class (MonoClass *klass)
11586 MonoClass *gklass = klass->generic_class->container_class;
11587 MonoDynamicGenericClass *dgclass;
11590 if (klass->wastypebuilder)
11593 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11594 if (klass->parent != gklass->parent) {
11596 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11597 if (mono_error_ok (&error)) {
11598 MonoClass *parent = mono_class_from_mono_type (parent_type);
11599 mono_metadata_free_type (parent_type);
11600 if (parent != klass->parent) {
11601 /*fool mono_class_setup_parent*/
11602 klass->supertypes = NULL;
11603 mono_class_setup_parent (klass, parent);
11606 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11607 mono_error_cleanup (&error);
11608 if (gklass->wastypebuilder)
11609 klass->wastypebuilder = TRUE;
11614 if (!dgclass->initialized)
11617 if (klass->method.count != gklass->method.count) {
11618 klass->method.count = gklass->method.count;
11619 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11621 for (i = 0; i < klass->method.count; i++) {
11623 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11624 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11625 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11629 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11630 klass->interface_count = gklass->interface_count;
11631 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11632 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11634 for (i = 0; i < gklass->interface_count; ++i) {
11635 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11636 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11637 mono_metadata_free_type (iface_type);
11639 ensure_runtime_vtable (klass->interfaces [i]);
11641 klass->interfaces_inited = 1;
11644 if (klass->field.count != gklass->field.count) {
11645 klass->field.count = gklass->field.count;
11646 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11648 for (i = 0; i < klass->field.count; i++) {
11649 klass->fields [i] = gklass->fields [i];
11650 klass->fields [i].parent = klass;
11651 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11655 /*We can only finish with this klass once it's parent has as well*/
11656 if (gklass->wastypebuilder)
11657 klass->wastypebuilder = TRUE;
11662 ensure_generic_class_runtime_vtable (MonoClass *klass)
11664 MonoClass *gklass = klass->generic_class->container_class;
11666 ensure_runtime_vtable (gklass);
11668 fix_partial_generic_class (klass);
11672 ensure_runtime_vtable (MonoClass *klass)
11674 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11677 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11680 ensure_runtime_vtable (klass->parent);
11683 num = tb->ctors? mono_array_length (tb->ctors): 0;
11684 num += tb->num_methods;
11685 klass->method.count = num;
11686 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11687 num = tb->ctors? mono_array_length (tb->ctors): 0;
11688 for (i = 0; i < num; ++i)
11689 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11690 num = tb->num_methods;
11692 for (i = 0; i < num; ++i)
11693 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11695 if (tb->interfaces) {
11696 klass->interface_count = mono_array_length (tb->interfaces);
11697 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11698 for (i = 0; i < klass->interface_count; ++i) {
11699 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11700 klass->interfaces [i] = mono_class_from_mono_type (iface);
11701 ensure_runtime_vtable (klass->interfaces [i]);
11703 klass->interfaces_inited = 1;
11705 } else if (klass->generic_class){
11706 ensure_generic_class_runtime_vtable (klass);
11709 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11711 for (i = 0; i < klass->method.count; ++i) {
11712 MonoMethod *im = klass->methods [i];
11713 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11714 im->slot = slot_num++;
11717 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11718 mono_class_setup_interface_offsets (klass);
11719 mono_class_setup_interface_id (klass);
11723 * The generic vtable is needed even if image->run is not set since some
11724 * runtime code like ves_icall_Type_GetMethodsByName depends on
11725 * method->slot being defined.
11729 * tb->methods could not be freed since it is used for determining
11730 * overrides during dynamic vtable construction.
11735 mono_reflection_method_get_handle (MonoObject *method)
11737 MonoClass *klass = mono_object_class (method);
11738 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11739 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11740 return sr_method->method;
11742 if (is_sre_method_builder (klass)) {
11743 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11744 return mb->mhandle;
11746 if (is_sre_method_on_tb_inst (klass)) {
11747 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11748 MonoMethod *result;
11749 /*FIXME move this to a proper method and unify with resolve_object*/
11750 if (m->method_args) {
11751 result = mono_reflection_method_on_tb_inst_get_handle (m);
11753 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11754 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11755 MonoMethod *mono_method;
11757 if (is_sre_method_builder (mono_object_class (m->mb)))
11758 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11759 else if (is_sr_mono_method (mono_object_class (m->mb)))
11760 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11762 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)));
11764 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11769 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11774 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11776 MonoReflectionTypeBuilder *tb;
11778 MonoReflectionMethod *m;
11781 *num_overrides = 0;
11783 g_assert (image_is_dynamic (klass->image));
11785 if (!mono_class_get_ref_info (klass))
11788 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11790 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11794 for (i = 0; i < tb->num_methods; ++i) {
11795 MonoReflectionMethodBuilder *mb =
11796 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11797 if (mb->override_methods)
11798 onum += mono_array_length (mb->override_methods);
11803 *overrides = g_new0 (MonoMethod*, onum * 2);
11806 for (i = 0; i < tb->num_methods; ++i) {
11807 MonoReflectionMethodBuilder *mb =
11808 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11809 if (mb->override_methods) {
11810 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11811 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11813 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11814 (*overrides) [onum * 2 + 1] = mb->mhandle;
11816 g_assert (mb->mhandle);
11824 *num_overrides = onum;
11828 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11830 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11831 MonoReflectionFieldBuilder *fb;
11832 MonoClassField *field;
11833 MonoImage *image = klass->image;
11834 const char *p, *p2;
11836 guint32 len, idx, real_size = 0;
11838 klass->field.count = tb->num_fields;
11839 klass->field.first = 0;
11841 mono_error_init (error);
11843 if (tb->class_size) {
11844 if ((tb->packing_size & 0xffffff00) != 0) {
11845 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11846 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11849 klass->packing_size = tb->packing_size;
11850 real_size = klass->instance_size + tb->class_size;
11853 if (!klass->field.count) {
11854 klass->instance_size = MAX (klass->instance_size, real_size);
11858 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11859 mono_class_alloc_ext (klass);
11860 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11862 This is, guess what, a hack.
11863 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11864 On the static path no field class is resolved, only types are built. This is the right thing to do
11866 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11868 klass->size_inited = 1;
11870 for (i = 0; i < klass->field.count; ++i) {
11871 MonoArray *rva_data;
11872 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11873 field = &klass->fields [i];
11874 field->name = mono_string_to_utf8_image (image, fb->name, error);
11875 if (!mono_error_ok (error))
11878 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11879 field->type->attrs = fb->attrs;
11881 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11884 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11885 char *base = mono_array_addr (rva_data, char, 0);
11886 size_t size = mono_array_length (rva_data);
11887 char *data = (char *)mono_image_alloc (klass->image, size);
11888 memcpy (data, base, size);
11889 klass->ext->field_def_values [i].data = data;
11891 if (fb->offset != -1)
11892 field->offset = fb->offset;
11893 field->parent = klass;
11894 fb->handle = field;
11895 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11897 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11898 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11900 if (fb->def_value) {
11901 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11902 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11903 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11904 /* Copy the data from the blob since it might get realloc-ed */
11905 p = assembly->blob.data + idx;
11906 len = mono_metadata_decode_blob_size (p, &p2);
11908 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11909 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11913 klass->instance_size = MAX (klass->instance_size, real_size);
11914 mono_class_layout_fields (klass);
11918 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11920 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11921 MonoReflectionPropertyBuilder *pb;
11922 MonoImage *image = klass->image;
11923 MonoProperty *properties;
11926 mono_error_init (error);
11929 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11931 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11932 klass->ext->property.first = 0;
11934 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11935 klass->ext->properties = properties;
11936 for (i = 0; i < klass->ext->property.count; ++i) {
11937 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11938 properties [i].parent = klass;
11939 properties [i].attrs = pb->attrs;
11940 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11941 if (!mono_error_ok (error))
11943 if (pb->get_method)
11944 properties [i].get = pb->get_method->mhandle;
11945 if (pb->set_method)
11946 properties [i].set = pb->set_method->mhandle;
11948 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11949 if (pb->def_value) {
11951 const char *p, *p2;
11952 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11953 if (!klass->ext->prop_def_values)
11954 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11955 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11956 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11957 /* Copy the data from the blob since it might get realloc-ed */
11958 p = assembly->blob.data + idx;
11959 len = mono_metadata_decode_blob_size (p, &p2);
11961 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11962 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11967 MonoReflectionEvent *
11968 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11970 MonoEvent *event = g_new0 (MonoEvent, 1);
11973 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11975 event->parent = klass;
11976 event->attrs = eb->attrs;
11977 event->name = mono_string_to_utf8 (eb->name);
11978 if (eb->add_method)
11979 event->add = eb->add_method->mhandle;
11980 if (eb->remove_method)
11981 event->remove = eb->remove_method->mhandle;
11982 if (eb->raise_method)
11983 event->raise = eb->raise_method->mhandle;
11985 #ifndef MONO_SMALL_CONFIG
11986 if (eb->other_methods) {
11988 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11989 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11990 MonoReflectionMethodBuilder *mb =
11991 mono_array_get (eb->other_methods,
11992 MonoReflectionMethodBuilder*, j);
11993 event->other [j] = mb->mhandle;
11998 return mono_event_get_object (mono_object_domain (tb), klass, event);
12002 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12004 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12005 MonoReflectionEventBuilder *eb;
12006 MonoImage *image = klass->image;
12010 mono_error_init (error);
12013 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12015 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12016 klass->ext->event.first = 0;
12018 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12019 klass->ext->events = events;
12020 for (i = 0; i < klass->ext->event.count; ++i) {
12021 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12022 events [i].parent = klass;
12023 events [i].attrs = eb->attrs;
12024 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12025 if (!mono_error_ok (error))
12027 if (eb->add_method)
12028 events [i].add = eb->add_method->mhandle;
12029 if (eb->remove_method)
12030 events [i].remove = eb->remove_method->mhandle;
12031 if (eb->raise_method)
12032 events [i].raise = eb->raise_method->mhandle;
12034 #ifndef MONO_SMALL_CONFIG
12035 if (eb->other_methods) {
12037 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12038 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12039 MonoReflectionMethodBuilder *mb =
12040 mono_array_get (eb->other_methods,
12041 MonoReflectionMethodBuilder*, j);
12042 events [i].other [j] = mb->mhandle;
12046 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12051 remove_instantiations_of_and_ensure_contents (gpointer key,
12053 gpointer user_data)
12055 MonoType *type = (MonoType*)key;
12056 MonoClass *klass = (MonoClass*)user_data;
12058 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12059 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12066 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12068 mono_error_init (error);
12074 for (i = 0; i < mono_array_length (arr); ++i) {
12075 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12076 if (!mono_error_ok (error))
12081 MonoReflectionType*
12082 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12086 MonoDomain* domain;
12087 MonoReflectionType* res;
12090 domain = mono_object_domain (tb);
12091 klass = mono_class_from_mono_type (tb->type.type);
12094 * Check for user defined Type subclasses.
12096 RESOLVE_TYPE (tb->parent, &error);
12097 mono_error_raise_exception (&error); /* FIXME don't raise here */
12098 check_array_for_usertypes (tb->interfaces, &error);
12099 mono_error_raise_exception (&error); /*FIXME don't raise here */
12101 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12102 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12104 RESOLVE_TYPE (fb->type, &error);
12105 mono_error_raise_exception (&error); /* FIXME don't raise here */
12106 check_array_for_usertypes (fb->modreq, &error);
12107 mono_error_raise_exception (&error); /*FIXME don't raise here */
12108 check_array_for_usertypes (fb->modopt, &error);
12109 mono_error_raise_exception (&error); /*FIXME don't raise here */
12110 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12111 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12112 mono_error_raise_exception (&error); /* FIXME don't raise here */
12118 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12119 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12121 RESOLVE_TYPE (mb->rtype, &error);
12122 mono_error_raise_exception (&error); /* FIXME don't raise here */
12123 check_array_for_usertypes (mb->return_modreq, &error);
12124 mono_error_raise_exception (&error); /*FIXME don't raise here */
12125 check_array_for_usertypes (mb->return_modopt, &error);
12126 mono_error_raise_exception (&error); /*FIXME don't raise here */
12127 check_array_for_usertypes (mb->parameters, &error);
12128 mono_error_raise_exception (&error); /*FIXME don't raise here */
12129 if (mb->param_modreq)
12130 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12131 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12132 mono_error_raise_exception (&error); /*FIXME don't raise here */
12134 if (mb->param_modopt)
12135 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12136 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12137 mono_error_raise_exception (&error); /*FIXME don't raise here */
12143 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12144 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12146 check_array_for_usertypes (mb->parameters, &error);
12147 mono_error_raise_exception (&error); /*FIXME don't raise here */
12148 if (mb->param_modreq)
12149 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12150 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12151 mono_error_raise_exception (&error); /*FIXME don't raise here */
12153 if (mb->param_modopt)
12154 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12155 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12156 mono_error_raise_exception (&error); /*FIXME don't raise here */
12162 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12165 * we need to lock the domain because the lock will be taken inside
12166 * So, we need to keep the locking order correct.
12168 mono_loader_lock ();
12169 mono_domain_lock (domain);
12170 if (klass->wastypebuilder) {
12171 mono_domain_unlock (domain);
12172 mono_loader_unlock ();
12174 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12175 mono_error_raise_exception (&error); /* FIXME don't raise here */
12180 * Fields to set in klass:
12181 * the various flags: delegate/unicode/contextbound etc.
12183 klass->flags = tb->attrs;
12184 klass->has_cctor = 1;
12185 klass->has_finalize = 1;
12186 klass->has_finalize_inited = 1;
12188 mono_class_setup_parent (klass, klass->parent);
12189 /* fool mono_class_setup_supertypes */
12190 klass->supertypes = NULL;
12191 mono_class_setup_supertypes (klass);
12192 mono_class_setup_mono_type (klass);
12195 if (!((MonoDynamicImage*)klass->image)->run) {
12196 if (klass->generic_container) {
12197 /* FIXME: The code below can't handle generic classes */
12198 klass->wastypebuilder = TRUE;
12199 mono_loader_unlock ();
12200 mono_domain_unlock (domain);
12202 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12203 mono_error_raise_exception (&error); /* FIXME don't raise here */
12210 /* enums are done right away */
12211 if (!klass->enumtype)
12212 ensure_runtime_vtable (klass);
12214 if (tb->subtypes) {
12215 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12216 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12217 mono_class_alloc_ext (klass);
12218 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)));
12222 klass->nested_classes_inited = TRUE;
12224 /* fields and object layout */
12225 if (klass->parent) {
12226 if (!klass->parent->size_inited)
12227 mono_class_init (klass->parent);
12228 klass->instance_size = klass->parent->instance_size;
12229 klass->sizes.class_size = 0;
12230 klass->min_align = klass->parent->min_align;
12231 /* if the type has no fields we won't call the field_setup
12232 * routine which sets up klass->has_references.
12234 klass->has_references |= klass->parent->has_references;
12236 klass->instance_size = sizeof (MonoObject);
12237 klass->min_align = 1;
12240 /* FIXME: handle packing_size and instance_size */
12241 typebuilder_setup_fields (klass, &error);
12242 if (!mono_error_ok (&error))
12244 typebuilder_setup_properties (klass, &error);
12245 if (!mono_error_ok (&error))
12248 typebuilder_setup_events (klass, &error);
12249 if (!mono_error_ok (&error))
12252 klass->wastypebuilder = TRUE;
12255 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12256 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12257 * we want to return normal System.MonoType objects, so clear these out from the cache.
12259 * Together with this we must ensure the contents of all instances to match the created type.
12261 if (domain->type_hash && klass->generic_container)
12262 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12264 mono_domain_unlock (domain);
12265 mono_loader_unlock ();
12267 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12268 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12269 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12272 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12273 mono_error_raise_exception (&error); /* FIXME don't raise here */
12275 g_assert (res != (MonoReflectionType*)tb);
12280 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12281 klass->wastypebuilder = TRUE;
12282 mono_domain_unlock (domain);
12283 mono_loader_unlock ();
12284 mono_error_raise_exception (&error);
12289 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12291 MonoGenericParamFull *param;
12296 image = &gparam->tbuilder->module->dynamic_image->image;
12298 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12300 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12301 g_assert (mono_error_ok (&error));
12302 param->param.num = gparam->index;
12304 if (gparam->mbuilder) {
12305 if (!gparam->mbuilder->generic_container) {
12306 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12307 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12308 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12309 gparam->mbuilder->generic_container->is_method = TRUE;
12311 * Cannot set owner.method, since the MonoMethod is not created yet.
12312 * Set the image field instead, so type_in_image () works.
12314 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12315 gparam->mbuilder->generic_container->owner.image = klass->image;
12317 param->param.owner = gparam->mbuilder->generic_container;
12318 } else if (gparam->tbuilder) {
12319 if (!gparam->tbuilder->generic_container) {
12320 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12321 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12322 gparam->tbuilder->generic_container->owner.klass = klass;
12324 param->param.owner = gparam->tbuilder->generic_container;
12327 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12329 gparam->type.type = &pklass->byval_arg;
12331 mono_class_set_ref_info (pklass, gparam);
12332 mono_image_append_class_to_reflection_info_set (pklass);
12336 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12339 MonoReflectionModuleBuilder *module = sig->module;
12340 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12341 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12346 check_array_for_usertypes (sig->arguments, &error);
12347 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12349 sigbuffer_init (&buf, 32);
12351 sigbuffer_add_value (&buf, 0x07);
12352 sigbuffer_add_value (&buf, na);
12353 if (assembly != NULL){
12354 for (i = 0; i < na; ++i) {
12355 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12356 encode_reflection_type (assembly, type, &buf);
12360 buflen = buf.p - buf.buf;
12361 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12362 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12363 sigbuffer_free (&buf);
12369 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12372 MonoDynamicImage *assembly = sig->module->dynamic_image;
12373 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12378 check_array_for_usertypes (sig->arguments, &error);
12379 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12381 sigbuffer_init (&buf, 32);
12383 sigbuffer_add_value (&buf, 0x06);
12384 for (i = 0; i < na; ++i) {
12385 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12386 encode_reflection_type (assembly, type, &buf);
12389 buflen = buf.p - buf.buf;
12390 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12391 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12392 sigbuffer_free (&buf);
12398 MonoMethod *handle;
12399 MonoDomain *domain;
12400 } DynamicMethodReleaseData;
12403 * The runtime automatically clean up those after finalization.
12405 static MonoReferenceQueue *dynamic_method_queue;
12408 free_dynamic_method (void *dynamic_method)
12410 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12411 MonoDomain *domain = data->domain;
12412 MonoMethod *method = data->handle;
12415 mono_domain_lock (domain);
12416 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12417 g_hash_table_remove (domain->method_to_dyn_method, method);
12418 mono_domain_unlock (domain);
12419 g_assert (dis_link);
12420 mono_gchandle_free (dis_link);
12422 mono_runtime_free_method (domain, method);
12427 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12429 MonoReferenceQueue *queue;
12430 MonoMethod *handle;
12431 DynamicMethodReleaseData *release_data;
12432 ReflectionMethodBuilder rmb;
12433 MonoMethodSignature *sig;
12435 MonoDomain *domain;
12439 if (mono_runtime_is_shutting_down ())
12440 mono_raise_exception (mono_get_exception_invalid_operation (""));
12442 if (!(queue = dynamic_method_queue)) {
12443 mono_loader_lock ();
12444 if (!(queue = dynamic_method_queue))
12445 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12446 mono_loader_unlock ();
12449 sig = dynamic_method_to_signature (mb);
12451 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12454 * Resolve references.
12457 * Every second entry in the refs array is reserved for storing handle_class,
12458 * which is needed by the ldtoken implementation in the JIT.
12460 rmb.nrefs = mb->nrefs;
12461 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12462 for (i = 0; i < mb->nrefs; i += 2) {
12463 MonoClass *handle_class;
12465 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12467 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12468 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12470 * The referenced DynamicMethod should already be created by the managed
12471 * code, except in the case of circular references. In that case, we store
12472 * method in the refs array, and fix it up later when the referenced
12473 * DynamicMethod is created.
12475 if (method->mhandle) {
12476 ref = method->mhandle;
12478 /* FIXME: GC object stored in unmanaged memory */
12481 /* FIXME: GC object stored in unmanaged memory */
12482 method->referenced_by = g_slist_append (method->referenced_by, mb);
12484 handle_class = mono_defaults.methodhandle_class;
12486 MonoException *ex = NULL;
12487 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12489 ex = mono_get_exception_type_load (NULL, NULL);
12490 else if (mono_security_core_clr_enabled ())
12491 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12495 mono_raise_exception (ex);
12500 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12501 rmb.refs [i + 1] = handle_class;
12504 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12506 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12507 release_data = g_new (DynamicMethodReleaseData, 1);
12508 release_data->handle = handle;
12509 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12510 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12511 g_free (release_data);
12513 /* Fix up refs entries pointing at us */
12514 for (l = mb->referenced_by; l; l = l->next) {
12515 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12516 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12519 g_assert (method->mhandle);
12521 data = (gpointer*)wrapper->method_data;
12522 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12523 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12524 data [i + 1] = mb->mhandle;
12527 g_slist_free (mb->referenced_by);
12531 /* ilgen is no longer needed */
12534 domain = mono_domain_get ();
12535 mono_domain_lock (domain);
12536 if (!domain->method_to_dyn_method)
12537 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12538 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12539 mono_domain_unlock (domain);
12542 #endif /* DISABLE_REFLECTION_EMIT */
12546 * mono_reflection_is_valid_dynamic_token:
12548 * Returns TRUE if token is valid.
12552 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12554 return lookup_dyn_token (image, token) != NULL;
12557 MonoMethodSignature *
12558 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12560 MonoMethodSignature *sig;
12561 g_assert (image_is_dynamic (image));
12563 mono_error_init (error);
12565 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12569 return mono_method_signature_checked (method, error);
12572 #ifndef DISABLE_REFLECTION_EMIT
12575 * mono_reflection_lookup_dynamic_token:
12577 * Finish the Builder object pointed to by TOKEN and return the corresponding
12578 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12579 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12582 * LOCKING: Take the loader lock
12585 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12587 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12591 obj = lookup_dyn_token (assembly, token);
12594 g_error ("Could not find required dynamic token 0x%08x", token);
12600 handle_class = &klass;
12601 return resolve_object (image, obj, handle_class, context);
12605 * ensure_complete_type:
12607 * Ensure that KLASS is completed if it is a dynamic type, or references
12611 ensure_complete_type (MonoClass *klass)
12613 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12614 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12616 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12618 // Asserting here could break a lot of code
12619 //g_assert (klass->wastypebuilder);
12622 if (klass->generic_class) {
12623 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12626 for (i = 0; i < inst->type_argc; ++i) {
12627 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12633 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12635 gpointer result = NULL;
12637 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12638 result = mono_string_intern ((MonoString*)obj);
12639 *handle_class = mono_defaults.string_class;
12641 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12642 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12643 MonoClass *mc = mono_class_from_mono_type (type);
12644 if (!mono_class_init (mc))
12645 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12648 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12649 result = mono_class_from_mono_type (inflated);
12650 mono_metadata_free_type (inflated);
12652 result = mono_class_from_mono_type (type);
12654 *handle_class = mono_defaults.typehandle_class;
12656 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12657 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12658 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12659 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12660 result = ((MonoReflectionMethod*)obj)->method;
12663 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12664 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12666 *handle_class = mono_defaults.methodhandle_class;
12668 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12669 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12670 result = mb->mhandle;
12672 /* Type is not yet created */
12673 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12675 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12678 * Hopefully this has been filled in by calling CreateType() on the
12682 * TODO: This won't work if the application finishes another
12683 * TypeBuilder instance instead of this one.
12685 result = mb->mhandle;
12689 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12690 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12692 *handle_class = mono_defaults.methodhandle_class;
12693 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12694 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12696 result = cb->mhandle;
12698 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12700 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12701 result = cb->mhandle;
12705 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12706 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12708 *handle_class = mono_defaults.methodhandle_class;
12709 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12710 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12712 ensure_complete_type (field->parent);
12714 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12715 MonoClass *klass = mono_class_from_mono_type (inflated);
12716 MonoClassField *inflated_field;
12717 gpointer iter = NULL;
12718 mono_metadata_free_type (inflated);
12719 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12720 if (!strcmp (field->name, inflated_field->name))
12723 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12724 result = inflated_field;
12728 *handle_class = mono_defaults.fieldhandle_class;
12730 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12731 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12732 result = fb->handle;
12735 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12737 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12738 result = fb->handle;
12741 if (fb->handle && fb->handle->parent->generic_container) {
12742 MonoClass *klass = fb->handle->parent;
12743 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12744 MonoClass *inflated = mono_class_from_mono_type (type);
12746 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12748 mono_metadata_free_type (type);
12750 *handle_class = mono_defaults.fieldhandle_class;
12751 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12752 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12753 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12756 klass = type->data.klass;
12757 if (klass->wastypebuilder) {
12758 /* Already created */
12762 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12763 result = type->data.klass;
12766 *handle_class = mono_defaults.typehandle_class;
12767 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12768 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12769 MonoMethodSignature *sig;
12772 if (helper->arguments)
12773 nargs = mono_array_length (helper->arguments);
12777 sig = mono_metadata_signature_alloc (image, nargs);
12778 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12779 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12781 if (helper->unmanaged_call_conv) { /* unmanaged */
12782 sig->call_convention = helper->unmanaged_call_conv - 1;
12783 sig->pinvoke = TRUE;
12784 } else if (helper->call_conv & 0x02) {
12785 sig->call_convention = MONO_CALL_VARARG;
12787 sig->call_convention = MONO_CALL_DEFAULT;
12790 sig->param_count = nargs;
12791 /* TODO: Copy type ? */
12792 sig->ret = helper->return_type->type;
12793 for (i = 0; i < nargs; ++i)
12794 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12797 *handle_class = NULL;
12798 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12799 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12800 /* Already created by the managed code */
12801 g_assert (method->mhandle);
12802 result = method->mhandle;
12803 *handle_class = mono_defaults.methodhandle_class;
12804 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12805 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12806 type = mono_class_inflate_generic_type (type, context);
12807 result = mono_class_from_mono_type (type);
12808 *handle_class = mono_defaults.typehandle_class;
12810 mono_metadata_free_type (type);
12811 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12812 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12813 type = mono_class_inflate_generic_type (type, context);
12814 result = mono_class_from_mono_type (type);
12815 *handle_class = mono_defaults.typehandle_class;
12817 mono_metadata_free_type (type);
12818 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12819 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12820 MonoClass *inflated;
12822 MonoClassField *field;
12824 if (is_sre_field_builder (mono_object_class (f->fb)))
12825 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12826 else if (is_sr_mono_field (mono_object_class (f->fb)))
12827 field = ((MonoReflectionField*)f->fb)->field;
12829 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)));
12831 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12832 inflated = mono_class_from_mono_type (type);
12834 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12835 ensure_complete_type (field->parent);
12837 mono_metadata_free_type (type);
12838 *handle_class = mono_defaults.fieldhandle_class;
12839 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12840 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12841 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12842 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12843 MonoMethod *method;
12845 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12846 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12847 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12848 method = ((MonoReflectionMethod *)c->cb)->method;
12850 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)));
12852 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12853 *handle_class = mono_defaults.methodhandle_class;
12854 mono_metadata_free_type (type);
12855 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12856 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12857 if (m->method_args) {
12858 result = mono_reflection_method_on_tb_inst_get_handle (m);
12861 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12862 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12865 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12866 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12867 MonoMethod *method;
12869 if (is_sre_method_builder (mono_object_class (m->mb)))
12870 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12871 else if (is_sr_mono_method (mono_object_class (m->mb)))
12872 method = ((MonoReflectionMethod *)m->mb)->method;
12874 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)));
12876 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12877 mono_metadata_free_type (type);
12879 *handle_class = mono_defaults.methodhandle_class;
12880 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12881 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12884 MonoMethod *method;
12888 mtype = mono_reflection_type_get_handle (m->parent);
12889 klass = mono_class_from_mono_type (mtype);
12891 /* Find the method */
12893 name = mono_string_to_utf8 (m->name);
12895 while ((method = mono_class_get_methods (klass, &iter))) {
12896 if (!strcmp (method->name, name))
12903 // FIXME: Check parameters/return value etc. match
12906 *handle_class = mono_defaults.methodhandle_class;
12907 } else if (is_sre_array (mono_object_get_class(obj)) ||
12908 is_sre_byref (mono_object_get_class(obj)) ||
12909 is_sre_pointer (mono_object_get_class(obj))) {
12910 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12911 MonoType *type = mono_reflection_type_get_handle (ref_type);
12914 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12915 result = mono_class_from_mono_type (inflated);
12916 mono_metadata_free_type (inflated);
12918 result = mono_class_from_mono_type (type);
12920 *handle_class = mono_defaults.typehandle_class;
12922 g_print ("%s\n", obj->vtable->klass->name);
12923 g_assert_not_reached ();
12928 #else /* DISABLE_REFLECTION_EMIT */
12931 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12933 g_assert_not_reached ();
12938 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12940 g_assert_not_reached ();
12944 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12946 g_assert_not_reached ();
12950 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12952 g_assert_not_reached ();
12956 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12958 g_assert_not_reached ();
12962 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12964 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12968 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12970 g_assert_not_reached ();
12974 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12976 g_assert_not_reached ();
12979 MonoReflectionModule *
12980 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12982 g_assert_not_reached ();
12987 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12989 g_assert_not_reached ();
12994 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
12996 g_assert_not_reached ();
13001 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13002 gboolean create_open_instance, gboolean register_token)
13004 g_assert_not_reached ();
13009 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13014 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13016 g_assert_not_reached ();
13020 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13023 *num_overrides = 0;
13026 MonoReflectionEvent *
13027 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13029 g_assert_not_reached ();
13033 MonoReflectionType*
13034 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13036 g_assert_not_reached ();
13041 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13043 g_assert_not_reached ();
13047 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13049 g_assert_not_reached ();
13054 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13056 g_assert_not_reached ();
13061 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13066 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13072 mono_reflection_type_get_handle (MonoReflectionType* ref)
13080 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13082 g_assert_not_reached ();
13085 #endif /* DISABLE_REFLECTION_EMIT */
13087 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13088 const static guint32 declsec_flags_map[] = {
13089 0x00000000, /* empty */
13090 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13091 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13092 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13093 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13094 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13095 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13096 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13097 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13098 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13099 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13100 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13101 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13102 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13103 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13104 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13105 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13106 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13107 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13111 * Returns flags that includes all available security action associated to the handle.
13112 * @token: metadata token (either for a class or a method)
13113 * @image: image where resides the metadata.
13116 mono_declsec_get_flags (MonoImage *image, guint32 token)
13118 int index = mono_metadata_declsec_from_index (image, token);
13119 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13120 guint32 result = 0;
13124 /* HasSecurity can be present for other, not specially encoded, attributes,
13125 e.g. SuppressUnmanagedCodeSecurityAttribute */
13129 for (i = index; i < t->rows; i++) {
13130 guint32 cols [MONO_DECL_SECURITY_SIZE];
13132 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13133 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13136 action = cols [MONO_DECL_SECURITY_ACTION];
13137 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13138 result |= declsec_flags_map [action];
13140 g_assert_not_reached ();
13147 * Get the security actions (in the form of flags) associated with the specified method.
13149 * @method: The method for which we want the declarative security flags.
13150 * Return the declarative security flags for the method (only).
13152 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13153 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13156 mono_declsec_flags_from_method (MonoMethod *method)
13158 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13159 /* FIXME: No cache (for the moment) */
13160 guint32 idx = mono_method_get_index (method);
13161 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13162 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13163 return mono_declsec_get_flags (method->klass->image, idx);
13169 * Get the security actions (in the form of flags) associated with the specified class.
13171 * @klass: The class for which we want the declarative security flags.
13172 * Return the declarative security flags for the class.
13174 * Note: We cache the flags inside the MonoClass structure as this will get
13175 * called very often (at least for each method).
13178 mono_declsec_flags_from_class (MonoClass *klass)
13180 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13181 if (!klass->ext || !klass->ext->declsec_flags) {
13184 idx = mono_metadata_token_index (klass->type_token);
13185 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13186 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13187 mono_loader_lock ();
13188 mono_class_alloc_ext (klass);
13189 mono_loader_unlock ();
13190 /* we cache the flags on classes */
13191 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13193 return klass->ext->declsec_flags;
13199 * Get the security actions (in the form of flags) associated with the specified assembly.
13201 * @assembly: The assembly for which we want the declarative security flags.
13202 * Return the declarative security flags for the assembly.
13205 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13207 guint32 idx = 1; /* there is only one assembly */
13208 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13209 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13210 return mono_declsec_get_flags (assembly->image, idx);
13215 * Fill actions for the specific index (which may either be an encoded class token or
13216 * an encoded method token) from the metadata image.
13217 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13220 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13221 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13223 MonoBoolean result = FALSE;
13225 guint32 cols [MONO_DECL_SECURITY_SIZE];
13226 int index = mono_metadata_declsec_from_index (image, token);
13229 t = &image->tables [MONO_TABLE_DECLSECURITY];
13230 for (i = index; i < t->rows; i++) {
13231 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13233 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13236 /* if present only replace (class) permissions with method permissions */
13237 /* if empty accept either class or method permissions */
13238 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13239 if (!actions->demand.blob) {
13240 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13241 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13242 actions->demand.blob = (char*) (blob + 2);
13243 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13246 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13247 if (!actions->noncasdemand.blob) {
13248 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13249 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13250 actions->noncasdemand.blob = (char*) (blob + 2);
13251 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13254 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13255 if (!actions->demandchoice.blob) {
13256 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13257 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13258 actions->demandchoice.blob = (char*) (blob + 2);
13259 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13269 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13270 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13272 guint32 idx = mono_metadata_token_index (klass->type_token);
13273 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13274 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13275 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13279 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13280 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13282 guint32 idx = mono_method_get_index (method);
13283 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13284 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13285 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13289 * Collect all actions (that requires to generate code in mini) assigned for
13290 * the specified method.
13291 * Note: Don't use the content of actions if the function return FALSE.
13294 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13296 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13297 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13298 MonoBoolean result = FALSE;
13301 /* quick exit if no declarative security is present in the metadata */
13302 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13305 /* we want the original as the wrapper is "free" of the security informations */
13306 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13307 method = mono_marshal_method_from_wrapper (method);
13312 /* First we look for method-level attributes */
13313 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13314 mono_class_init (method->klass);
13315 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13317 result = mono_declsec_get_method_demands_params (method, demands,
13318 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13321 /* Here we use (or create) the class declarative cache to look for demands */
13322 flags = mono_declsec_flags_from_class (method->klass);
13323 if (flags & mask) {
13325 mono_class_init (method->klass);
13326 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13328 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13329 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13332 /* The boolean return value is used as a shortcut in case nothing needs to
13333 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13339 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13341 * Note: Don't use the content of actions if the function return FALSE.
13344 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13346 MonoBoolean result = FALSE;
13349 /* quick exit if no declarative security is present in the metadata */
13350 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13353 /* we want the original as the wrapper is "free" of the security informations */
13354 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13355 method = mono_marshal_method_from_wrapper (method);
13360 /* results are independant - zeroize both */
13361 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13362 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13364 /* First we look for method-level attributes */
13365 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13366 mono_class_init (method->klass);
13368 result = mono_declsec_get_method_demands_params (method, cmethod,
13369 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13372 /* Here we use (or create) the class declarative cache to look for demands */
13373 flags = mono_declsec_flags_from_class (method->klass);
13374 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13375 mono_class_init (method->klass);
13377 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13378 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13385 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13387 * @klass The inherited class - this is the class that provides the security check (attributes)
13389 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13391 * Note: Don't use the content of actions if the function return FALSE.
13394 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13396 MonoBoolean result = FALSE;
13399 /* quick exit if no declarative security is present in the metadata */
13400 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13403 /* Here we use (or create) the class declarative cache to look for demands */
13404 flags = mono_declsec_flags_from_class (klass);
13405 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13406 mono_class_init (klass);
13407 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13409 result |= mono_declsec_get_class_demands_params (klass, demands,
13410 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13417 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13419 * Note: Don't use the content of actions if the function return FALSE.
13422 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13424 /* quick exit if no declarative security is present in the metadata */
13425 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13428 /* we want the original as the wrapper is "free" of the security informations */
13429 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13430 method = mono_marshal_method_from_wrapper (method);
13435 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13436 mono_class_init (method->klass);
13437 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13439 return mono_declsec_get_method_demands_params (method, demands,
13440 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13447 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13449 guint32 cols [MONO_DECL_SECURITY_SIZE];
13453 int index = mono_metadata_declsec_from_index (image, token);
13457 t = &image->tables [MONO_TABLE_DECLSECURITY];
13458 for (i = index; i < t->rows; i++) {
13459 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13461 /* shortcut - index are ordered */
13462 if (token != cols [MONO_DECL_SECURITY_PARENT])
13465 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13466 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13467 entry->blob = (char*) (metadata + 2);
13468 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13477 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13479 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13480 guint32 idx = mono_method_get_index (method);
13481 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13482 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13483 return get_declsec_action (method->klass->image, idx, action, entry);
13489 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13492 guint32 flags = mono_declsec_flags_from_class (klass);
13493 if (declsec_flags_map [action] & flags) {
13494 guint32 idx = mono_metadata_token_index (klass->type_token);
13495 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13496 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13497 return get_declsec_action (klass->image, idx, action, entry);
13503 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13505 guint32 idx = 1; /* there is only one assembly */
13506 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13507 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13509 return get_declsec_action (assembly->image, idx, action, entry);
13513 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13516 MonoObject *res, *exc;
13518 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13519 static MonoMethod *method = NULL;
13521 if (!System_Reflection_Emit_TypeBuilder) {
13522 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13523 g_assert (System_Reflection_Emit_TypeBuilder);
13525 if (method == NULL) {
13526 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13531 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13532 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13534 g_assert (mono_class_get_ref_info (klass));
13535 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13537 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13538 mono_error_raise_exception (&error); /* FIXME don't raise here */
13540 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13544 return *(MonoBoolean*)mono_object_unbox (res);
13548 * mono_reflection_type_get_type:
13549 * @reftype: the System.Type object
13551 * Returns the MonoType* associated with the C# System.Type object @reftype.
13554 mono_reflection_type_get_type (MonoReflectionType *reftype)
13556 g_assert (reftype);
13558 return mono_reflection_type_get_handle (reftype);
13562 * mono_reflection_assembly_get_assembly:
13563 * @refassembly: the System.Reflection.Assembly object
13565 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13568 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13570 g_assert (refassembly);
13572 return refassembly->assembly;