2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
226 dynamic_images_lock (void)
228 mono_os_mutex_lock (&dynamic_images_mutex);
232 dynamic_images_unlock (void)
234 mono_os_mutex_unlock (&dynamic_images_mutex);
238 * mono_find_dynamic_image_owner:
240 * Find the dynamic image, if any, which a given pointer is located in the memory of.
243 mono_find_dynamic_image_owner (void *ptr)
245 MonoImage *owner = NULL;
248 dynamic_images_lock ();
252 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254 if (mono_mempool_contains_addr (image->mempool, ptr))
259 dynamic_images_unlock ();
265 mono_reflection_init (void)
267 mono_os_mutex_init (&dynamic_images_mutex);
271 dynamic_image_lock (MonoDynamicImage *image)
273 MONO_PREPARE_BLOCKING;
274 mono_image_lock ((MonoImage*)image);
275 MONO_FINISH_BLOCKING;
279 dynamic_image_unlock (MonoDynamicImage *image)
281 mono_image_unlock ((MonoImage*)image);
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
287 MONO_REQ_GC_UNSAFE_MODE;
289 dynamic_image_lock (assembly);
290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291 dynamic_image_unlock (assembly);
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
297 MONO_REQ_GC_UNSAFE_MODE;
301 dynamic_image_lock (assembly);
302 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303 dynamic_image_unlock (assembly);
309 sigbuffer_init (SigBuffer *buf, int size)
311 MONO_REQ_GC_NEUTRAL_MODE;
313 buf->buf = (char *)g_malloc (size);
315 buf->end = buf->buf + size;
319 sigbuffer_make_room (SigBuffer *buf, int size)
321 MONO_REQ_GC_NEUTRAL_MODE;
323 if (buf->end - buf->p < size) {
324 int new_size = buf->end - buf->buf + size + 32;
325 char *p = (char *)g_realloc (buf->buf, new_size);
326 size = buf->p - buf->buf;
329 buf->end = buf->buf + new_size;
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
336 MONO_REQ_GC_NEUTRAL_MODE;
338 sigbuffer_make_room (buf, 6);
339 mono_metadata_encode_value (val, buf->p, &buf->p);
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
345 MONO_REQ_GC_NEUTRAL_MODE;
347 sigbuffer_make_room (buf, 1);
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
355 MONO_REQ_GC_NEUTRAL_MODE;
357 sigbuffer_make_room (buf, size);
358 memcpy (buf->p, p, size);
363 sigbuffer_free (SigBuffer *buf)
365 MONO_REQ_GC_NEUTRAL_MODE;
370 #ifndef DISABLE_REFLECTION_EMIT
374 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
378 image_g_malloc (MonoImage *image, guint size)
380 MONO_REQ_GC_NEUTRAL_MODE;
383 return mono_image_alloc (image, size);
385 return g_malloc (size);
387 #endif /* !DISABLE_REFLECTION_EMIT */
392 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 image_g_malloc0 (MonoImage *image, guint size)
398 MONO_REQ_GC_NEUTRAL_MODE;
401 return mono_image_alloc0 (image, size);
403 return g_malloc0 (size);
406 #ifndef DISABLE_REFLECTION_EMIT
408 image_strdup (MonoImage *image, const char *s)
410 MONO_REQ_GC_NEUTRAL_MODE;
413 return mono_image_strdup (image, s);
419 #define image_g_new(image,struct_type, n_structs) \
420 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
422 #define image_g_new0(image,struct_type, n_structs) \
423 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
427 alloc_table (MonoDynamicTable *table, guint nrows)
429 MONO_REQ_GC_NEUTRAL_MODE;
432 g_assert (table->columns);
433 if (nrows + 1 >= table->alloc_rows) {
434 while (nrows + 1 >= table->alloc_rows) {
435 if (table->alloc_rows == 0)
436 table->alloc_rows = 16;
438 table->alloc_rows *= 2;
441 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
446 make_room_in_stream (MonoDynamicStream *stream, int size)
448 MONO_REQ_GC_NEUTRAL_MODE;
450 if (size <= stream->alloc_size)
453 while (stream->alloc_size <= size) {
454 if (stream->alloc_size < 4096)
455 stream->alloc_size = 4096;
457 stream->alloc_size *= 2;
460 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
466 MONO_REQ_GC_NEUTRAL_MODE;
470 gpointer oldkey, oldval;
472 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473 return GPOINTER_TO_UINT (oldval);
475 len = strlen (str) + 1;
478 make_room_in_stream (sh, idx + len);
481 * We strdup the string even if we already copy them in sh->data
482 * so that the string pointers in the hash remain valid even if
483 * we need to realloc sh->data. We may want to avoid that later.
485 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486 memcpy (sh->data + idx, str, len);
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
494 MONO_REQ_GC_UNSAFE_MODE;
496 char *name = mono_string_to_utf8 (str);
498 idx = string_heap_insert (sh, name);
503 #ifndef DISABLE_REFLECTION_EMIT
505 string_heap_init (MonoDynamicStream *sh)
507 MONO_REQ_GC_NEUTRAL_MODE;
510 sh->alloc_size = 4096;
511 sh->data = (char *)g_malloc (4096);
512 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513 string_heap_insert (sh, "");
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 make_room_in_stream (stream, stream->index + len);
525 memcpy (stream->data + stream->index, data, len);
527 stream->index += len;
529 * align index? Not without adding an additional param that controls it since
530 * we may store a blob value in pieces.
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
538 MONO_REQ_GC_NEUTRAL_MODE;
542 make_room_in_stream (stream, stream->index + len);
543 memset (stream->data + stream->index, 0, len);
545 stream->index += len;
550 stream_data_align (MonoDynamicStream *stream)
552 MONO_REQ_GC_NEUTRAL_MODE;
555 guint32 count = stream->index % 4;
557 /* we assume the stream data will be aligned */
559 mono_image_add_stream_data (stream, buf, 4 - count);
562 #ifndef DISABLE_REFLECTION_EMIT
564 mono_blob_entry_hash (const char* str)
566 MONO_REQ_GC_NEUTRAL_MODE;
570 len = mono_metadata_decode_blob_size (str, &str);
574 for (str += 1; str < end; str++)
575 h = (h << 5) - h + *str;
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584 MONO_REQ_GC_NEUTRAL_MODE;
589 len = mono_metadata_decode_blob_size (str1, &end1);
590 len2 = mono_metadata_decode_blob_size (str2, &end2);
593 return memcmp (end1, end2, len) == 0;
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
599 MONO_REQ_GC_NEUTRAL_MODE;
603 gpointer oldkey, oldval;
605 copy = (char *)g_malloc (s1+s2);
606 memcpy (copy, b1, s1);
607 memcpy (copy + s1, b2, s2);
608 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
610 idx = GPOINTER_TO_UINT (oldval);
612 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613 mono_image_add_stream_data (&assembly->blob, b2, s2);
614 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
622 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 size = buf->p - buf->buf;
628 g_assert (size <= (buf->end - buf->buf));
629 mono_metadata_encode_value (size, b, &b);
630 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
634 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635 * dest may be misaligned.
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639 MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
643 for (elem = 0; elem < nelem; ++elem) {
669 g_assert_not_reached ();
675 memcpy (dest, val, len * nelem);
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
682 MONO_REQ_GC_UNSAFE_MODE;
686 guint32 idx = 0, len;
688 len = str->length * 2;
689 mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
692 char *swapped = g_malloc (2 * mono_string_length (str));
693 const char *p = (const char*)mono_string_chars (str);
695 swap_with_size (swapped, p, 2, mono_string_length (str));
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
700 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
705 #ifndef DISABLE_REFLECTION_EMIT
707 default_class_from_mono_type (MonoType *type)
709 MONO_REQ_GC_NEUTRAL_MODE;
711 switch (type->type) {
712 case MONO_TYPE_OBJECT:
713 return mono_defaults.object_class;
715 return mono_defaults.void_class;
716 case MONO_TYPE_BOOLEAN:
717 return mono_defaults.boolean_class;
719 return mono_defaults.char_class;
721 return mono_defaults.sbyte_class;
723 return mono_defaults.byte_class;
725 return mono_defaults.int16_class;
727 return mono_defaults.uint16_class;
729 return mono_defaults.int32_class;
731 return mono_defaults.uint32_class;
733 return mono_defaults.int_class;
735 return mono_defaults.uint_class;
737 return mono_defaults.int64_class;
739 return mono_defaults.uint64_class;
741 return mono_defaults.single_class;
743 return mono_defaults.double_class;
744 case MONO_TYPE_STRING:
745 return mono_defaults.string_class;
747 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748 g_assert_not_reached ();
756 * mono_class_get_ref_info:
758 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
761 mono_class_get_ref_info (MonoClass *klass)
763 MONO_REQ_GC_UNSAFE_MODE;
765 if (klass->ref_info_handle == 0)
768 return mono_gchandle_get_target (klass->ref_info_handle);
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
774 MONO_REQ_GC_UNSAFE_MODE;
776 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777 g_assert (klass->ref_info_handle != 0);
781 mono_class_free_ref_info (MonoClass *klass)
783 MONO_REQ_GC_NEUTRAL_MODE;
785 if (klass->ref_info_handle) {
786 mono_gchandle_free (klass->ref_info_handle);
787 klass->ref_info_handle = 0;
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
794 MONO_REQ_GC_NEUTRAL_MODE;
797 MonoGenericInst *class_inst;
802 class_inst = gclass->context.class_inst;
804 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805 klass = gclass->container_class;
806 sigbuffer_add_value (buf, klass->byval_arg.type);
807 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
809 sigbuffer_add_value (buf, class_inst->type_argc);
810 for (i = 0; i < class_inst->type_argc; ++i)
811 encode_type (assembly, class_inst->type_argv [i], buf);
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
818 MONO_REQ_GC_NEUTRAL_MODE;
821 g_assert_not_reached ();
826 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
830 case MONO_TYPE_BOOLEAN:
844 case MONO_TYPE_STRING:
845 case MONO_TYPE_OBJECT:
846 case MONO_TYPE_TYPEDBYREF:
847 sigbuffer_add_value (buf, type->type);
850 sigbuffer_add_value (buf, type->type);
851 encode_type (assembly, type->data.type, buf);
853 case MONO_TYPE_SZARRAY:
854 sigbuffer_add_value (buf, type->type);
855 encode_type (assembly, &type->data.klass->byval_arg, buf);
857 case MONO_TYPE_VALUETYPE:
858 case MONO_TYPE_CLASS: {
859 MonoClass *k = mono_class_from_mono_type (type);
861 if (k->generic_container) {
862 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863 encode_generic_class (assembly, gclass, buf);
866 * Make sure we use the correct type.
868 sigbuffer_add_value (buf, k->byval_arg.type);
870 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871 * otherwise two typerefs could point to the same type, leading to
872 * verification errors.
874 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
878 case MONO_TYPE_ARRAY:
879 sigbuffer_add_value (buf, type->type);
880 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881 sigbuffer_add_value (buf, type->data.array->rank);
882 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883 sigbuffer_add_value (buf, 0);
885 case MONO_TYPE_GENERICINST:
886 encode_generic_class (assembly, type->data.generic_class, buf);
890 sigbuffer_add_value (buf, type->type);
891 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
894 g_error ("need to encode type %x", type->type);
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
901 MONO_REQ_GC_UNSAFE_MODE;
904 sigbuffer_add_value (buf, MONO_TYPE_VOID);
908 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
914 MONO_REQ_GC_UNSAFE_MODE;
919 for (i = 0; i < mono_array_length (modreq); ++i) {
920 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926 for (i = 0; i < mono_array_length (modopt); ++i) {
927 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
934 #ifndef DISABLE_REFLECTION_EMIT
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
938 MONO_REQ_GC_UNSAFE_MODE;
942 guint32 nparams = sig->param_count;
948 sigbuffer_init (&buf, 32);
950 * FIXME: vararg, explicit_this, differenc call_conv values...
952 idx = sig->call_convention;
954 idx |= 0x20; /* hasthis */
955 if (sig->generic_param_count)
956 idx |= 0x10; /* generic */
957 sigbuffer_add_byte (&buf, idx);
958 if (sig->generic_param_count)
959 sigbuffer_add_value (&buf, sig->generic_param_count);
960 sigbuffer_add_value (&buf, nparams);
961 encode_type (assembly, sig->ret, &buf);
962 for (i = 0; i < nparams; ++i) {
963 if (i == sig->sentinelpos)
964 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965 encode_type (assembly, sig->params [i], &buf);
967 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968 sigbuffer_free (&buf);
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
976 MONO_REQ_GC_UNSAFE_MODE;
979 * FIXME: reuse code from method_encode_signature().
983 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
984 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
988 sigbuffer_init (&buf, 32);
989 /* LAMESPEC: all the call conv spec is foobared */
990 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991 if (mb->call_conv & 2)
992 idx |= 0x5; /* vararg */
993 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994 idx |= 0x20; /* hasthis */
996 idx |= 0x10; /* generic */
997 sigbuffer_add_byte (&buf, idx);
999 sigbuffer_add_value (&buf, ngparams);
1000 sigbuffer_add_value (&buf, nparams + notypes);
1001 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002 encode_reflection_type (assembly, mb->rtype, &buf);
1003 for (i = 0; i < nparams; ++i) {
1004 MonoArray *modreq = NULL;
1005 MonoArray *modopt = NULL;
1006 MonoReflectionType *pt;
1008 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014 encode_reflection_type (assembly, pt, &buf);
1017 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018 for (i = 0; i < notypes; ++i) {
1019 MonoReflectionType *pt;
1021 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022 encode_reflection_type (assembly, pt, &buf);
1025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026 sigbuffer_free (&buf);
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1033 MONO_REQ_GC_UNSAFE_MODE;
1035 MonoDynamicTable *table;
1037 guint32 idx, sig_idx;
1038 guint nl = mono_array_length (ilgen->locals);
1042 sigbuffer_init (&buf, 32);
1043 sigbuffer_add_value (&buf, 0x07);
1044 sigbuffer_add_value (&buf, nl);
1045 for (i = 0; i < nl; ++i) {
1046 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1049 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1051 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1053 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1056 if (assembly->standalonesig_cache == NULL)
1057 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1062 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063 idx = table->next_idx ++;
1065 alloc_table (table, table->rows);
1066 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1068 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1070 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1078 MONO_REQ_GC_UNSAFE_MODE;
1080 guint32 num_clauses = 0;
1083 MonoILExceptionInfo *ex_info;
1084 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086 if (ex_info->handlers)
1087 num_clauses += mono_array_length (ex_info->handlers);
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 MonoExceptionClause *clauses;
1102 MonoExceptionClause *clause;
1103 MonoILExceptionInfo *ex_info;
1104 MonoILExceptionBlock *ex_block;
1105 guint32 finally_start;
1106 int i, j, clause_index;;
1108 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1111 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113 finally_start = ex_info->start + ex_info->len;
1114 if (!ex_info->handlers)
1116 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118 clause = &(clauses [clause_index]);
1120 clause->flags = ex_block->type;
1121 clause->try_offset = ex_info->start;
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124 clause->try_len = finally_start - ex_info->start;
1126 clause->try_len = ex_info->len;
1127 clause->handler_offset = ex_block->start;
1128 clause->handler_len = ex_block->len;
1129 if (ex_block->extype) {
1130 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1132 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133 clause->data.filter_offset = ex_block->filter_offset;
1135 clause->data.filter_offset = 0;
1137 finally_start = ex_block->start + ex_block->len;
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1148 * method_encode_code:
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)
1658 MONO_REQ_GC_UNSAFE_MODE;
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 mono_error_raise_exception (&error); /* FIXME don't raise here */
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;
1698 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1700 MONO_REQ_GC_UNSAFE_MODE;
1703 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1705 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1707 rmb->ilgen = mb->ilgen;
1708 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1709 mono_error_raise_exception (&error); /* FIXME don't raise here */
1710 rmb->parameters = mb->parameters;
1711 rmb->generic_params = NULL;
1712 rmb->generic_container = NULL;
1713 rmb->opt_types = NULL;
1714 rmb->pinfo = mb->pinfo;
1715 rmb->attrs = mb->attrs;
1716 rmb->iattrs = mb->iattrs;
1717 rmb->call_conv = mb->call_conv;
1719 rmb->type = mb->type;
1720 rmb->name = mono_string_new (mono_domain_get (), name);
1721 rmb->table_idx = &mb->table_idx;
1722 rmb->init_locals = mb->init_locals;
1723 rmb->skip_visibility = FALSE;
1724 rmb->return_modreq = NULL;
1725 rmb->return_modopt = NULL;
1726 rmb->param_modreq = mb->param_modreq;
1727 rmb->param_modopt = mb->param_modopt;
1728 rmb->permissions = mb->permissions;
1729 rmb->mhandle = mb->mhandle;
1735 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1737 MONO_REQ_GC_UNSAFE_MODE;
1739 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1741 rmb->ilgen = mb->ilgen;
1742 rmb->rtype = mb->rtype;
1743 rmb->parameters = mb->parameters;
1744 rmb->generic_params = NULL;
1745 rmb->generic_container = NULL;
1746 rmb->opt_types = NULL;
1748 rmb->attrs = mb->attrs;
1750 rmb->call_conv = mb->call_conv;
1752 rmb->type = (MonoObject *) mb->owner;
1753 rmb->name = mb->name;
1754 rmb->table_idx = NULL;
1755 rmb->init_locals = mb->init_locals;
1756 rmb->skip_visibility = mb->skip_visibility;
1757 rmb->return_modreq = NULL;
1758 rmb->return_modopt = NULL;
1759 rmb->param_modreq = NULL;
1760 rmb->param_modopt = NULL;
1761 rmb->permissions = NULL;
1762 rmb->mhandle = mb->mhandle;
1769 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1771 MONO_REQ_GC_UNSAFE_MODE;
1773 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1774 MonoDynamicTable *table;
1777 MonoReflectionMethod *m;
1780 mono_error_init (error);
1782 if (!mb->override_methods)
1785 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1786 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1788 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1790 alloc_table (table, table->rows);
1791 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1792 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1793 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1795 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1796 return_val_if_nok (error, FALSE);
1798 switch (mono_metadata_token_table (tok)) {
1799 case MONO_TABLE_MEMBERREF:
1800 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1802 case MONO_TABLE_METHOD:
1803 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1806 g_assert_not_reached ();
1808 values [MONO_METHODIMPL_DECLARATION] = tok;
1814 #ifndef DISABLE_REFLECTION_EMIT
1816 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1818 MONO_REQ_GC_UNSAFE_MODE;
1822 MonoDynamicTable *table;
1824 ReflectionMethodBuilder rmb;
1827 reflection_methodbuilder_from_method_builder (&rmb, mb);
1829 mono_image_basic_method (&rmb, assembly, &error);
1830 mono_error_raise_exception (&error); /* FIXME don't raise here */
1831 mb->table_idx = *rmb.table_idx;
1833 if (mb->dll) { /* It's a P/Invoke method */
1835 /* map CharSet values to on-disk values */
1836 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1837 int extra_flags = mb->extra_flags;
1838 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1840 alloc_table (table, table->rows);
1841 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1843 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1844 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1846 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1848 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1849 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1850 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1851 table = &assembly->tables [MONO_TABLE_MODULEREF];
1853 alloc_table (table, table->rows);
1854 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1855 values [MONO_IMPLMAP_SCOPE] = table->rows;
1859 if (mb->generic_params) {
1860 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1861 table->rows += mono_array_length (mb->generic_params);
1862 alloc_table (table, table->rows);
1863 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1864 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1866 mono_image_get_generic_param_info (
1867 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1874 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1876 MONO_REQ_GC_UNSAFE_MODE;
1878 ReflectionMethodBuilder rmb;
1880 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1882 if (!mono_image_basic_method (&rmb, assembly, error))
1885 mb->table_idx = *rmb.table_idx;
1892 type_get_fully_qualified_name (MonoType *type)
1894 MONO_REQ_GC_NEUTRAL_MODE;
1896 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1900 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1902 MONO_REQ_GC_UNSAFE_MODE;
1907 klass = mono_class_from_mono_type (type);
1909 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1910 ta = klass->image->assembly;
1911 if (assembly_is_dynamic (ta) || (ta == ass)) {
1912 if (klass->generic_class || klass->generic_container)
1913 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1914 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1916 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1919 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1922 #ifndef DISABLE_REFLECTION_EMIT
1923 /*field_image is the image to which the eventual custom mods have been encoded against*/
1925 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1927 MONO_REQ_GC_NEUTRAL_MODE;
1930 guint32 idx, i, token;
1932 if (!assembly->save)
1935 sigbuffer_init (&buf, 32);
1937 sigbuffer_add_value (&buf, 0x06);
1938 /* encode custom attributes before the type */
1939 if (type->num_mods) {
1940 for (i = 0; i < type->num_mods; ++i) {
1943 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1944 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1946 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1948 token = type->modifiers [i].token;
1951 if (type->modifiers [i].required)
1952 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1954 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1956 sigbuffer_add_value (&buf, token);
1959 encode_type (assembly, type, &buf);
1960 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961 sigbuffer_free (&buf);
1967 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1969 MONO_REQ_GC_UNSAFE_MODE;
1973 guint32 typespec = 0;
1977 init_type_builder_generics (fb->type);
1979 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1980 klass = mono_class_from_mono_type (type);
1982 sigbuffer_init (&buf, 32);
1984 sigbuffer_add_value (&buf, 0x06);
1985 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1986 /* encode custom attributes before the type */
1988 if (klass->generic_container)
1989 typespec = create_typespec (assembly, type);
1992 MonoGenericClass *gclass;
1993 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1994 encode_generic_class (assembly, gclass, &buf);
1996 encode_type (assembly, type, &buf);
1998 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1999 sigbuffer_free (&buf);
2004 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2006 MONO_REQ_GC_UNSAFE_MODE;
2008 char blob_size [64];
2009 char *b = blob_size;
2012 guint32 idx = 0, len = 0, dummy = 0;
2014 buf = (char *)g_malloc (64);
2016 *ret_type = MONO_TYPE_CLASS;
2018 box_val = (char*)&dummy;
2020 box_val = ((char*)val) + sizeof (MonoObject);
2021 *ret_type = val->vtable->klass->byval_arg.type;
2024 switch (*ret_type) {
2025 case MONO_TYPE_BOOLEAN:
2030 case MONO_TYPE_CHAR:
2047 case MONO_TYPE_VALUETYPE: {
2048 MonoClass *klass = val->vtable->klass;
2050 if (klass->enumtype) {
2051 *ret_type = mono_class_enum_basetype (klass)->type;
2053 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2056 g_error ("we can't encode valuetypes, we should have never reached this line");
2059 case MONO_TYPE_CLASS:
2061 case MONO_TYPE_STRING: {
2062 MonoString *str = (MonoString*)val;
2063 /* there is no signature */
2064 len = str->length * 2;
2065 mono_metadata_encode_value (len, b, &b);
2066 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2068 char *swapped = g_malloc (2 * mono_string_length (str));
2069 const char *p = (const char*)mono_string_chars (str);
2071 swap_with_size (swapped, p, 2, mono_string_length (str));
2072 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2076 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2082 case MONO_TYPE_GENERICINST:
2083 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2086 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2089 /* there is no signature */
2090 mono_metadata_encode_value (len, b, &b);
2091 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2092 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2093 swap_with_size (blob_size, box_val, len, 1);
2094 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2096 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2104 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2106 MONO_REQ_GC_UNSAFE_MODE;
2112 sigbuffer_init (&buf, 32);
2114 sigbuffer_add_value (&buf, minfo->type);
2116 switch (minfo->type) {
2117 case MONO_NATIVE_BYVALTSTR:
2118 case MONO_NATIVE_BYVALARRAY:
2119 sigbuffer_add_value (&buf, minfo->count);
2121 case MONO_NATIVE_LPARRAY:
2122 if (minfo->eltype || minfo->has_size) {
2123 sigbuffer_add_value (&buf, minfo->eltype);
2124 if (minfo->has_size) {
2125 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2126 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2128 /* LAMESPEC: ElemMult is undocumented */
2129 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2133 case MONO_NATIVE_SAFEARRAY:
2135 sigbuffer_add_value (&buf, minfo->eltype);
2137 case MONO_NATIVE_CUSTOM:
2139 str = mono_string_to_utf8 (minfo->guid);
2141 sigbuffer_add_value (&buf, len);
2142 sigbuffer_add_mem (&buf, str, len);
2145 sigbuffer_add_value (&buf, 0);
2147 /* native type name */
2148 sigbuffer_add_value (&buf, 0);
2149 /* custom marshaler type name */
2150 if (minfo->marshaltype || minfo->marshaltyperef) {
2151 if (minfo->marshaltyperef)
2152 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2154 str = mono_string_to_utf8 (minfo->marshaltype);
2156 sigbuffer_add_value (&buf, len);
2157 sigbuffer_add_mem (&buf, str, len);
2160 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2161 sigbuffer_add_value (&buf, 0);
2163 if (minfo->mcookie) {
2164 str = mono_string_to_utf8 (minfo->mcookie);
2166 sigbuffer_add_value (&buf, len);
2167 sigbuffer_add_mem (&buf, str, len);
2170 sigbuffer_add_value (&buf, 0);
2176 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2177 sigbuffer_free (&buf);
2182 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2184 MONO_REQ_GC_UNSAFE_MODE;
2186 MonoDynamicTable *table;
2189 /* maybe this fixup should be done in the C# code */
2190 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2191 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2192 table = &assembly->tables [MONO_TABLE_FIELD];
2193 fb->table_idx = table->next_idx ++;
2194 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2195 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2196 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2197 values [MONO_FIELD_FLAGS] = fb->attrs;
2198 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2200 if (fb->offset != -1) {
2201 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2203 alloc_table (table, table->rows);
2204 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2205 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2206 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2208 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2209 MonoTypeEnum field_type = (MonoTypeEnum)0;
2210 table = &assembly->tables [MONO_TABLE_CONSTANT];
2212 alloc_table (table, table->rows);
2213 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2214 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2215 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2216 values [MONO_CONSTANT_TYPE] = field_type;
2217 values [MONO_CONSTANT_PADDING] = 0;
2219 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2221 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2223 alloc_table (table, table->rows);
2224 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2225 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2227 * We store it in the code section because it's simpler for now.
2230 if (mono_array_length (fb->rva_data) >= 10)
2231 stream_data_align (&assembly->code);
2232 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2234 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2235 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2237 if (fb->marshal_info) {
2238 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2240 alloc_table (table, table->rows);
2241 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2242 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2243 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2248 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2250 MONO_REQ_GC_UNSAFE_MODE;
2253 guint32 nparams = 0;
2254 MonoReflectionMethodBuilder *mb = fb->get_method;
2255 MonoReflectionMethodBuilder *smb = fb->set_method;
2258 if (mb && mb->parameters)
2259 nparams = mono_array_length (mb->parameters);
2260 if (!mb && smb && smb->parameters)
2261 nparams = mono_array_length (smb->parameters) - 1;
2262 sigbuffer_init (&buf, 32);
2263 if (fb->call_conv & 0x20)
2264 sigbuffer_add_byte (&buf, 0x28);
2266 sigbuffer_add_byte (&buf, 0x08);
2267 sigbuffer_add_value (&buf, nparams);
2269 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2270 for (i = 0; i < nparams; ++i) {
2271 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2272 encode_reflection_type (assembly, pt, &buf);
2274 } else if (smb && smb->parameters) {
2275 /* the property type is the last param */
2276 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2277 for (i = 0; i < nparams; ++i) {
2278 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2279 encode_reflection_type (assembly, pt, &buf);
2282 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2285 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2286 sigbuffer_free (&buf);
2291 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2293 MONO_REQ_GC_UNSAFE_MODE;
2295 MonoDynamicTable *table;
2297 guint num_methods = 0;
2301 * we need to set things in the following tables:
2302 * PROPERTYMAP (info already filled in _get_type_info ())
2303 * PROPERTY (rows already preallocated in _get_type_info ())
2304 * METHOD (method info already done with the generic method code)
2308 table = &assembly->tables [MONO_TABLE_PROPERTY];
2309 pb->table_idx = table->next_idx ++;
2310 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2311 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2312 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2313 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2315 /* FIXME: we still don't handle 'other' methods */
2316 if (pb->get_method) num_methods ++;
2317 if (pb->set_method) num_methods ++;
2319 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2320 table->rows += num_methods;
2321 alloc_table (table, table->rows);
2323 if (pb->get_method) {
2324 semaidx = table->next_idx ++;
2325 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2326 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2327 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2328 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2330 if (pb->set_method) {
2331 semaidx = table->next_idx ++;
2332 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2333 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2334 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2335 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2337 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2338 MonoTypeEnum field_type = (MonoTypeEnum)0;
2339 table = &assembly->tables [MONO_TABLE_CONSTANT];
2341 alloc_table (table, table->rows);
2342 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2343 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2344 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2345 values [MONO_CONSTANT_TYPE] = field_type;
2346 values [MONO_CONSTANT_PADDING] = 0;
2351 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2353 MONO_REQ_GC_UNSAFE_MODE;
2355 MonoDynamicTable *table;
2357 guint num_methods = 0;
2361 * we need to set things in the following tables:
2362 * EVENTMAP (info already filled in _get_type_info ())
2363 * EVENT (rows already preallocated in _get_type_info ())
2364 * METHOD (method info already done with the generic method code)
2367 table = &assembly->tables [MONO_TABLE_EVENT];
2368 eb->table_idx = table->next_idx ++;
2369 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2370 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2371 values [MONO_EVENT_FLAGS] = eb->attrs;
2372 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2375 * FIXME: we still don't handle 'other' methods
2377 if (eb->add_method) num_methods ++;
2378 if (eb->remove_method) num_methods ++;
2379 if (eb->raise_method) num_methods ++;
2381 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2382 table->rows += num_methods;
2383 alloc_table (table, table->rows);
2385 if (eb->add_method) {
2386 semaidx = table->next_idx ++;
2387 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2388 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2389 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2390 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2392 if (eb->remove_method) {
2393 semaidx = table->next_idx ++;
2394 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2395 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2396 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2397 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2399 if (eb->raise_method) {
2400 semaidx = table->next_idx ++;
2401 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2402 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2403 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2404 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2409 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2411 MONO_REQ_GC_UNSAFE_MODE;
2413 MonoDynamicTable *table;
2414 guint32 num_constraints, i;
2418 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2419 num_constraints = gparam->iface_constraints ?
2420 mono_array_length (gparam->iface_constraints) : 0;
2421 table->rows += num_constraints;
2422 if (gparam->base_type)
2424 alloc_table (table, table->rows);
2426 if (gparam->base_type) {
2427 table_idx = table->next_idx ++;
2428 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2430 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2431 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2432 assembly, mono_reflection_type_get_handle (gparam->base_type));
2435 for (i = 0; i < num_constraints; i++) {
2436 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2437 gparam->iface_constraints, gpointer, i);
2439 table_idx = table->next_idx ++;
2440 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2442 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2443 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2444 assembly, mono_reflection_type_get_handle (constraint));
2449 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2451 MONO_REQ_GC_UNSAFE_MODE;
2453 GenericParamTableEntry *entry;
2456 * The GenericParam table must be sorted according to the `owner' field.
2457 * We need to do this sorting prior to writing the GenericParamConstraint
2458 * table, since we have to use the final GenericParam table indices there
2459 * and they must also be sorted.
2462 entry = g_new0 (GenericParamTableEntry, 1);
2463 entry->owner = owner;
2464 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2465 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2466 entry->gparam = gparam;
2468 g_ptr_array_add (assembly->gen_params, entry);
2472 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2474 MONO_REQ_GC_UNSAFE_MODE;
2478 MonoDynamicTable *table;
2479 MonoGenericParam *param;
2483 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2484 table_idx = table->next_idx ++;
2485 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2487 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2489 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2490 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2491 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2492 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2494 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, &error))
2497 encode_constraints (entry->gparam, table_idx, assembly);
2501 mono_error_raise_exception (&error); /* FIXME don't raise here */
2505 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2507 MONO_REQ_GC_UNSAFE_MODE;
2509 MonoDynamicTable *table;
2512 guint32 cols [MONO_ASSEMBLY_SIZE];
2516 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2519 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2520 table = &assembly->tables [MONO_TABLE_MODULEREF];
2521 token = table->next_idx ++;
2523 alloc_table (table, table->rows);
2524 values = table->values + token * MONO_MODULEREF_SIZE;
2525 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2527 token <<= MONO_RESOLUTION_SCOPE_BITS;
2528 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2529 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2534 if (assembly_is_dynamic (image->assembly))
2536 memset (cols, 0, sizeof (cols));
2538 /* image->assembly->image is the manifest module */
2539 image = image->assembly->image;
2540 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2543 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2544 token = table->next_idx ++;
2546 alloc_table (table, table->rows);
2547 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2548 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2549 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2550 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2551 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2552 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2553 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2554 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2555 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2557 if (strcmp ("", image->assembly->aname.culture)) {
2558 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2559 image->assembly->aname.culture);
2562 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2563 guchar pubtoken [9];
2565 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2566 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2568 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2570 token <<= MONO_RESOLUTION_SCOPE_BITS;
2571 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2572 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2577 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2579 MONO_REQ_GC_NEUTRAL_MODE;
2581 MonoDynamicTable *table;
2586 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2589 sigbuffer_init (&buf, 32);
2590 switch (type->type) {
2591 case MONO_TYPE_FNPTR:
2593 case MONO_TYPE_SZARRAY:
2594 case MONO_TYPE_ARRAY:
2596 case MONO_TYPE_MVAR:
2597 case MONO_TYPE_GENERICINST:
2598 encode_type (assembly, type, &buf);
2600 case MONO_TYPE_CLASS:
2601 case MONO_TYPE_VALUETYPE: {
2602 MonoClass *k = mono_class_from_mono_type (type);
2603 if (!k || !k->generic_container) {
2604 sigbuffer_free (&buf);
2607 encode_type (assembly, type, &buf);
2611 sigbuffer_free (&buf);
2615 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2616 if (assembly->save) {
2617 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2618 alloc_table (table, table->rows + 1);
2619 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2620 values [MONO_TYPESPEC_SIGNATURE] = token;
2622 sigbuffer_free (&buf);
2624 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2625 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2631 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2633 MONO_REQ_GC_UNSAFE_MODE;
2635 MonoDynamicTable *table;
2637 guint32 token, scope, enclosing;
2640 /* if the type requires a typespec, we must try that first*/
2641 if (try_typespec && (token = create_typespec (assembly, type)))
2643 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2646 klass = mono_class_from_mono_type (type);
2648 klass = mono_class_from_mono_type (type);
2651 * If it's in the same module and not a generic type parameter:
2653 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2654 (type->type != MONO_TYPE_MVAR)) {
2655 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2656 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2657 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2661 if (klass->nested_in) {
2662 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2663 /* get the typeref idx of the enclosing type */
2664 enclosing >>= MONO_TYPEDEFORREF_BITS;
2665 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2667 scope = resolution_scope_from_image (assembly, klass->image);
2669 table = &assembly->tables [MONO_TABLE_TYPEREF];
2670 if (assembly->save) {
2671 alloc_table (table, table->rows + 1);
2672 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2673 values [MONO_TYPEREF_SCOPE] = scope;
2674 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2675 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2677 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2678 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2680 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2685 * Despite the name, we handle also TypeSpec (with the above helper).
2688 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2690 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2693 #ifndef DISABLE_REFLECTION_EMIT
2695 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2697 MONO_REQ_GC_NEUTRAL_MODE;
2699 MonoDynamicTable *table;
2701 guint32 token, pclass;
2703 switch (parent & MONO_TYPEDEFORREF_MASK) {
2704 case MONO_TYPEDEFORREF_TYPEREF:
2705 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2707 case MONO_TYPEDEFORREF_TYPESPEC:
2708 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2710 case MONO_TYPEDEFORREF_TYPEDEF:
2711 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2714 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2717 /* extract the index */
2718 parent >>= MONO_TYPEDEFORREF_BITS;
2720 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2722 if (assembly->save) {
2723 alloc_table (table, table->rows + 1);
2724 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2725 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2726 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2727 values [MONO_MEMBERREF_SIGNATURE] = sig;
2730 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2737 * Insert a memberef row into the metadata: the token that point to the memberref
2738 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2739 * mono_image_get_fieldref_token()).
2740 * The sig param is an index to an already built signature.
2743 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2745 MONO_REQ_GC_NEUTRAL_MODE;
2747 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2748 return mono_image_add_memberef_row (assembly, parent, name, sig);
2753 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2755 MONO_REQ_GC_NEUTRAL_MODE;
2758 MonoMethodSignature *sig;
2760 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2762 if (create_typespec) {
2763 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2768 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2769 if (token && !create_typespec)
2772 g_assert (!method->is_inflated);
2775 * A methodref signature can't contain an unmanaged calling convention.
2777 sig = mono_metadata_signature_dup (mono_method_signature (method));
2778 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2779 sig->call_convention = MONO_CALL_DEFAULT;
2780 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2781 method->name, method_encode_signature (assembly, sig));
2783 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2786 if (create_typespec) {
2787 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2788 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2789 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2791 if (assembly->save) {
2794 alloc_table (table, table->rows + 1);
2795 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2796 values [MONO_METHODSPEC_METHOD] = token;
2797 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2800 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2802 /*methodspec and memberef tokens are diferent, */
2803 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2810 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2812 guint32 token, parent, sig;
2813 ReflectionMethodBuilder rmb;
2815 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2817 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2821 name = mono_string_to_utf8 (method->name);
2822 reflection_methodbuilder_from_method_builder (&rmb, method);
2825 * A methodref signature can't contain an unmanaged calling convention.
2826 * Since some flags are encoded as part of call_conv, we need to check against it.
2828 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2829 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2831 sig = method_builder_encode_signature (assembly, &rmb);
2833 if (tb->generic_params)
2834 parent = create_generic_typespec (assembly, tb);
2836 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2838 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2841 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2846 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2847 const gchar *name, guint32 sig)
2849 MonoDynamicTable *table;
2853 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2855 if (assembly->save) {
2856 alloc_table (table, table->rows + 1);
2857 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2858 values [MONO_MEMBERREF_CLASS] = original;
2859 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2860 values [MONO_MEMBERREF_SIGNATURE] = sig;
2863 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2870 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2874 guint32 nparams = mono_array_length (mb->generic_params);
2877 if (!assembly->save)
2880 sigbuffer_init (&buf, 32);
2882 sigbuffer_add_value (&buf, 0xa);
2883 sigbuffer_add_value (&buf, nparams);
2885 for (i = 0; i < nparams; i++) {
2886 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2887 sigbuffer_add_value (&buf, i);
2890 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2891 sigbuffer_free (&buf);
2896 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2898 MonoDynamicTable *table;
2900 guint32 token, mtoken = 0;
2902 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2906 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2908 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2909 switch (mono_metadata_token_table (mtoken)) {
2910 case MONO_TABLE_MEMBERREF:
2911 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2913 case MONO_TABLE_METHOD:
2914 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2917 g_assert_not_reached ();
2920 if (assembly->save) {
2921 alloc_table (table, table->rows + 1);
2922 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2923 values [MONO_METHODSPEC_METHOD] = mtoken;
2924 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2927 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2930 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2935 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2939 if (mb->generic_params && create_methodspec)
2940 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2942 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2946 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2947 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2952 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2954 guint32 token, parent, sig;
2955 ReflectionMethodBuilder rmb;
2957 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2959 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2963 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2965 if (tb->generic_params)
2966 parent = create_generic_typespec (assembly, tb);
2968 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2970 name = mono_string_to_utf8 (rmb.name);
2971 sig = method_builder_encode_signature (assembly, &rmb);
2973 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2976 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2982 is_field_on_inst (MonoClassField *field)
2984 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2988 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2991 get_field_on_inst_generic_type (MonoClassField *field)
2993 MonoClass *klass, *gtd;
2994 MonoDynamicGenericClass *dgclass;
2997 g_assert (is_field_on_inst (field));
2999 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3001 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3002 field_index = field - dgclass->fields;
3003 return dgclass->field_generic_types [field_index];
3006 klass = field->parent;
3007 gtd = klass->generic_class->container_class;
3009 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3010 field_index = field - klass->fields;
3011 return gtd->fields [field_index].type;
3014 g_assert_not_reached ();
3018 #ifndef DISABLE_REFLECTION_EMIT
3020 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3026 g_assert (field->parent);
3028 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3032 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3033 int index = field - field->parent->fields;
3034 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3036 if (is_field_on_inst (field))
3037 type = get_field_on_inst_generic_type (field);
3039 type = mono_field_get_type (field);
3041 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3042 mono_field_get_name (field),
3043 fieldref_encode_signature (assembly, field->parent->image, type));
3044 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3049 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3053 MonoGenericClass *gclass;
3057 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3060 if (is_sre_field_builder (mono_object_class (f->fb))) {
3061 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3062 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3063 klass = mono_class_from_mono_type (type);
3064 gclass = type->data.generic_class;
3065 g_assert (gclass->is_dynamic);
3067 name = mono_string_to_utf8 (fb->name);
3068 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3069 field_encode_signature (assembly, fb));
3071 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3073 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3075 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3076 klass = mono_class_from_mono_type (type);
3078 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3079 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3081 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3082 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3085 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3090 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3094 MonoGenericClass *gclass;
3097 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3099 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3103 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3104 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3105 ReflectionMethodBuilder rmb;
3108 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3109 klass = mono_class_from_mono_type (type);
3111 gclass = type->data.generic_class;
3112 g_assert (gclass->is_dynamic);
3114 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3116 name = mono_string_to_utf8 (rmb.name);
3118 sig = method_builder_encode_signature (assembly, &rmb);
3120 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3122 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3123 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3125 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3126 klass = mono_class_from_mono_type (type);
3128 sig = method_encode_signature (assembly, mono_method_signature (mm));
3129 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3131 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3132 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3136 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3141 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3145 MonoGenericContext tmp_context;
3146 MonoType **type_argv;
3147 MonoGenericInst *ginst;
3148 MonoMethod *method, *inflated;
3151 init_type_builder_generics ((MonoObject*)m->inst);
3153 method = inflate_method (m->inst, (MonoObject*)m->mb);
3155 klass = method->klass;
3157 if (m->method_args == NULL)
3160 if (method->is_inflated)
3161 method = ((MonoMethodInflated *) method)->declaring;
3163 count = mono_array_length (m->method_args);
3165 type_argv = g_new0 (MonoType *, count);
3166 for (i = 0; i < count; i++) {
3167 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3168 type_argv [i] = mono_reflection_type_get_handle (garg);
3170 ginst = mono_metadata_get_generic_inst (count, type_argv);
3173 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3174 tmp_context.method_inst = ginst;
3176 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3177 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3182 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3184 guint32 sig, token = 0;
3188 if (m->method_args) {
3189 MonoMethod *inflated;
3191 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3192 if (create_methodspec)
3193 token = mono_image_get_methodspec_token (assembly, inflated);
3195 token = mono_image_get_inflated_method_token (assembly, inflated);
3199 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3203 if (is_sre_method_builder (mono_object_class (m->mb))) {
3204 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3205 MonoGenericClass *gclass;
3206 ReflectionMethodBuilder rmb;
3209 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3210 klass = mono_class_from_mono_type (type);
3211 gclass = type->data.generic_class;
3212 g_assert (gclass->is_dynamic);
3214 reflection_methodbuilder_from_method_builder (&rmb, mb);
3216 name = mono_string_to_utf8 (rmb.name);
3218 sig = method_builder_encode_signature (assembly, &rmb);
3220 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3222 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3223 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3225 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3226 klass = mono_class_from_mono_type (type);
3228 sig = method_encode_signature (assembly, mono_method_signature (mm));
3229 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3231 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3232 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3235 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3240 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3244 guint32 nparams = context->method_inst->type_argc;
3247 if (!assembly->save)
3250 sigbuffer_init (&buf, 32);
3252 * FIXME: vararg, explicit_this, differenc call_conv values...
3254 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3255 sigbuffer_add_value (&buf, nparams);
3257 for (i = 0; i < nparams; i++)
3258 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3260 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261 sigbuffer_free (&buf);
3266 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3268 MonoDynamicTable *table;
3270 guint32 token, mtoken = 0, sig;
3271 MonoMethodInflated *imethod;
3272 MonoMethod *declaring;
3274 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3276 g_assert (method->is_inflated);
3277 imethod = (MonoMethodInflated *) method;
3278 declaring = imethod->declaring;
3280 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3281 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3283 if (!mono_method_signature (declaring)->generic_param_count)
3286 switch (mono_metadata_token_table (mtoken)) {
3287 case MONO_TABLE_MEMBERREF:
3288 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3290 case MONO_TABLE_METHOD:
3291 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3294 g_assert_not_reached ();
3297 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3299 if (assembly->save) {
3300 alloc_table (table, table->rows + 1);
3301 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3302 values [MONO_METHODSPEC_METHOD] = mtoken;
3303 values [MONO_METHODSPEC_SIGNATURE] = sig;
3306 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3313 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3315 MonoMethodInflated *imethod;
3318 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3322 g_assert (method->is_inflated);
3323 imethod = (MonoMethodInflated *) method;
3325 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3326 token = method_encode_methodspec (assembly, method);
3328 guint32 sig = method_encode_signature (
3329 assembly, mono_method_signature (imethod->declaring));
3330 token = mono_image_get_memberref_token (
3331 assembly, &method->klass->byval_arg, method->name, sig);
3334 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3339 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3341 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3344 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3345 token = mono_image_get_memberref_token (
3346 assembly, &m->klass->byval_arg, m->name, sig);
3352 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3354 MonoDynamicTable *table;
3363 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3364 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3365 * Because of this, we must not insert it into the `typeref' hash table.
3367 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3372 sigbuffer_init (&buf, 32);
3374 g_assert (tb->generic_params);
3375 klass = mono_class_from_mono_type (type);
3377 if (tb->generic_container)
3378 mono_reflection_create_generic_class (tb);
3380 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3381 g_assert (klass->generic_container);
3382 sigbuffer_add_value (&buf, klass->byval_arg.type);
3383 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3385 count = mono_array_length (tb->generic_params);
3386 sigbuffer_add_value (&buf, count);
3387 for (i = 0; i < count; i++) {
3388 MonoReflectionGenericParam *gparam;
3390 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3392 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3395 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3397 if (assembly->save) {
3398 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3399 alloc_table (table, table->rows + 1);
3400 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3401 values [MONO_TYPESPEC_SIGNATURE] = token;
3403 sigbuffer_free (&buf);
3405 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3406 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3412 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3415 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3417 int i, count, len, pos;
3422 count += mono_array_length (modreq);
3424 count += mono_array_length (modopt);
3427 return mono_metadata_type_dup (NULL, type);
3429 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3430 t = (MonoType *)g_malloc (len);
3431 memcpy (t, type, MONO_SIZEOF_TYPE);
3433 t->num_mods = count;
3436 for (i = 0; i < mono_array_length (modreq); ++i) {
3437 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3438 t->modifiers [pos].required = 1;
3439 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3444 for (i = 0; i < mono_array_length (modopt); ++i) {
3445 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3446 t->modifiers [pos].required = 0;
3447 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3456 init_type_builder_generics (MonoObject *type)
3458 MonoReflectionTypeBuilder *tb;
3460 if (!is_sre_type_builder(mono_object_class (type)))
3462 tb = (MonoReflectionTypeBuilder *)type;
3464 if (tb && tb->generic_container)
3465 mono_reflection_create_generic_class (tb);
3469 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3471 MonoDynamicTable *table;
3472 MonoType *custom = NULL, *type;
3474 guint32 token, pclass, parent, sig;
3477 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3481 /* FIXME: is this call necessary? */
3482 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3483 name = mono_string_to_utf8 (fb->name);
3485 /*FIXME this is one more layer of ugliness due how types are created.*/
3486 init_type_builder_generics (fb->type);
3488 /* fb->type does not include the custom modifiers */
3489 /* FIXME: We should do this in one place when a fieldbuilder is created */
3490 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3491 if (fb->modreq || fb->modopt)
3492 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3494 sig = fieldref_encode_signature (assembly, NULL, type);
3497 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3498 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3500 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3501 parent >>= MONO_TYPEDEFORREF_BITS;
3503 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3505 if (assembly->save) {
3506 alloc_table (table, table->rows + 1);
3507 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3508 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3509 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3510 values [MONO_MEMBERREF_SIGNATURE] = sig;
3513 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3515 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3521 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3527 if (!assembly->save)
3530 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3531 g_assert (helper->type == 2);
3533 if (helper->arguments)
3534 nargs = mono_array_length (helper->arguments);
3538 sigbuffer_init (&buf, 32);
3540 /* Encode calling convention */
3541 /* Change Any to Standard */
3542 if ((helper->call_conv & 0x03) == 0x03)
3543 helper->call_conv = 0x01;
3544 /* explicit_this implies has_this */
3545 if (helper->call_conv & 0x40)
3546 helper->call_conv &= 0x20;
3548 if (helper->call_conv == 0) { /* Unmanaged */
3549 idx = helper->unmanaged_call_conv - 1;
3552 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3553 if (helper->call_conv & 0x02) /* varargs */
3557 sigbuffer_add_byte (&buf, idx);
3558 sigbuffer_add_value (&buf, nargs);
3559 encode_reflection_type (assembly, helper->return_type, &buf);
3560 for (i = 0; i < nargs; ++i) {
3561 MonoArray *modreqs = NULL;
3562 MonoArray *modopts = NULL;
3563 MonoReflectionType *pt;
3565 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3566 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3567 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3568 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3570 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3571 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3572 encode_reflection_type (assembly, pt, &buf);
3574 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3575 sigbuffer_free (&buf);
3581 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3584 MonoDynamicTable *table;
3587 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3588 idx = table->next_idx ++;
3590 alloc_table (table, table->rows);
3591 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3593 values [MONO_STAND_ALONE_SIGNATURE] =
3594 mono_reflection_encode_sighelper (assembly, helper);
3600 reflection_cc_to_file (int call_conv) {
3601 switch (call_conv & 0x3) {
3603 case 1: return MONO_CALL_DEFAULT;
3604 case 2: return MONO_CALL_VARARG;
3606 g_assert_not_reached ();
3610 #endif /* !DISABLE_REFLECTION_EMIT */
3614 MonoMethodSignature *sig;
3619 #ifndef DISABLE_REFLECTION_EMIT
3621 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3626 MonoMethodSignature *sig;
3630 name = mono_string_to_utf8 (m->name);
3631 nparams = mono_array_length (m->parameters);
3632 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3634 sig->sentinelpos = -1;
3635 sig->call_convention = reflection_cc_to_file (m->call_conv);
3636 sig->param_count = nparams;
3637 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3638 mtype = mono_reflection_type_get_handle (m->parent);
3639 for (i = 0; i < nparams; ++i)
3640 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3642 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3643 am = (ArrayMethod *)tmp->data;
3644 if (strcmp (name, am->name) == 0 &&
3645 mono_metadata_type_equal (am->parent, mtype) &&
3646 mono_metadata_signature_equal (am->sig, sig)) {
3649 m->table_idx = am->token & 0xffffff;
3653 am = g_new0 (ArrayMethod, 1);
3657 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3658 method_encode_signature (assembly, sig));
3659 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3660 m->table_idx = am->token & 0xffffff;
3665 * Insert into the metadata tables all the info about the TypeBuilder tb.
3666 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3669 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3672 MonoDynamicTable *table;
3674 int i, is_object = 0, is_system = 0;
3677 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3678 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3679 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3680 n = mono_string_to_utf8 (tb->name);
3681 if (strcmp (n, "Object") == 0)
3683 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3685 n = mono_string_to_utf8 (tb->nspace);
3686 if (strcmp (n, "System") == 0)
3688 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3690 if (tb->parent && !(is_system && is_object) &&
3691 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3692 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3694 values [MONO_TYPEDEF_EXTENDS] = 0;
3696 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3697 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3700 * if we have explicitlayout or sequentiallayouts, output data in the
3701 * ClassLayout table.
3703 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3704 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3705 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3707 alloc_table (table, table->rows);
3708 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3709 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3710 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3711 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3714 /* handle interfaces */
3715 if (tb->interfaces) {
3716 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3718 table->rows += mono_array_length (tb->interfaces);
3719 alloc_table (table, table->rows);
3720 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3721 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3722 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3723 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3724 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3725 values += MONO_INTERFACEIMPL_SIZE;
3731 table = &assembly->tables [MONO_TABLE_FIELD];
3732 table->rows += tb->num_fields;
3733 alloc_table (table, table->rows);
3734 for (i = 0; i < tb->num_fields; ++i)
3735 mono_image_get_field_info (
3736 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3739 /* handle constructors */
3741 table = &assembly->tables [MONO_TABLE_METHOD];
3742 table->rows += mono_array_length (tb->ctors);
3743 alloc_table (table, table->rows);
3744 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3745 mono_image_get_ctor_info (domain,
3746 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3748 mono_error_raise_exception (&error); /* FIXME don't raise here */
3752 /* handle methods */
3754 table = &assembly->tables [MONO_TABLE_METHOD];
3755 table->rows += tb->num_methods;
3756 alloc_table (table, table->rows);
3757 for (i = 0; i < tb->num_methods; ++i)
3758 mono_image_get_method_info (
3759 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3762 /* Do the same with properties etc.. */
3763 if (tb->events && mono_array_length (tb->events)) {
3764 table = &assembly->tables [MONO_TABLE_EVENT];
3765 table->rows += mono_array_length (tb->events);
3766 alloc_table (table, table->rows);
3767 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3769 alloc_table (table, table->rows);
3770 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3771 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3772 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3773 for (i = 0; i < mono_array_length (tb->events); ++i)
3774 mono_image_get_event_info (
3775 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3777 if (tb->properties && mono_array_length (tb->properties)) {
3778 table = &assembly->tables [MONO_TABLE_PROPERTY];
3779 table->rows += mono_array_length (tb->properties);
3780 alloc_table (table, table->rows);
3781 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3783 alloc_table (table, table->rows);
3784 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3785 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3786 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3787 for (i = 0; i < mono_array_length (tb->properties); ++i)
3788 mono_image_get_property_info (
3789 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3792 /* handle generic parameters */
3793 if (tb->generic_params) {
3794 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3795 table->rows += mono_array_length (tb->generic_params);
3796 alloc_table (table, table->rows);
3797 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3798 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3800 mono_image_get_generic_param_info (
3801 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3805 mono_image_add_decl_security (assembly,
3806 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3809 MonoDynamicTable *ntable;
3811 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3812 ntable->rows += mono_array_length (tb->subtypes);
3813 alloc_table (ntable, ntable->rows);
3814 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3816 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3817 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3819 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3820 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3821 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3822 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3823 mono_string_to_utf8 (tb->name), tb->table_idx,
3824 ntable->next_idx, ntable->rows);*/
3825 values += MONO_NESTED_CLASS_SIZE;
3833 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3837 mono_ptr_array_append (*types, type);
3839 if (!type->subtypes)
3842 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3843 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3844 collect_types (types, subtype);
3849 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3851 if ((*type1)->table_idx < (*type2)->table_idx)
3854 if ((*type1)->table_idx > (*type2)->table_idx)
3861 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3864 mono_error_init (error);
3867 for (i = 0; i < mono_array_length (pinfo); ++i) {
3868 MonoReflectionParamBuilder *pb;
3869 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3872 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3880 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3883 mono_error_init (error);
3885 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3888 for (i = 0; i < tb->num_fields; ++i) {
3889 MonoReflectionFieldBuilder* fb;
3890 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3891 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3896 for (i = 0; i < mono_array_length (tb->events); ++i) {
3897 MonoReflectionEventBuilder* eb;
3898 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3899 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3903 if (tb->properties) {
3904 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3905 MonoReflectionPropertyBuilder* pb;
3906 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3907 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3912 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3913 MonoReflectionCtorBuilder* cb;
3914 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3915 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3916 !params_add_cattrs (assembly, cb->pinfo, error))
3922 for (i = 0; i < tb->num_methods; ++i) {
3923 MonoReflectionMethodBuilder* mb;
3924 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3925 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3926 !params_add_cattrs (assembly, mb->pinfo, error))
3932 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3933 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3942 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3946 mono_error_init (error);
3948 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3951 if (moduleb->global_methods) {
3952 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3953 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3954 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3955 !params_add_cattrs (assembly, mb->pinfo, error))
3960 if (moduleb->global_fields) {
3961 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3962 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3963 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3968 if (moduleb->types) {
3969 for (i = 0; i < moduleb->num_types; ++i) {
3970 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
3979 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3981 MonoDynamicTable *table;
3985 char *b = blob_size;
3988 table = &assembly->tables [MONO_TABLE_FILE];
3990 alloc_table (table, table->rows);
3991 values = table->values + table->next_idx * MONO_FILE_SIZE;
3992 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3993 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3994 if (image_is_dynamic (module->image)) {
3995 /* This depends on the fact that the main module is emitted last */
3996 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3997 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4000 path = g_strdup (module->image->name);
4002 mono_sha1_get_digest_from_file (path, hash);
4005 mono_metadata_encode_value (20, b, &b);
4006 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4007 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4012 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4014 MonoDynamicTable *table;
4017 table = &assembly->tables [MONO_TABLE_MODULE];
4018 mb->table_idx = table->next_idx ++;
4019 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4020 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4023 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4024 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4025 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4026 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4030 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4031 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4033 MonoDynamicTable *table;
4037 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4038 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4041 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4043 alloc_table (table, table->rows);
4044 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4046 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4047 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4048 if (klass->nested_in)
4049 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4051 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4052 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4053 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4055 res = table->next_idx;
4059 /* Emit nested types */
4060 if (klass->ext && klass->ext->nested_classes) {
4063 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4064 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4071 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4072 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4077 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4079 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4081 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4082 parent_index, assembly);
4086 * We need to do this ourselves since klass->nested_classes is not set up.
4089 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4090 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4095 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4096 guint32 module_index, MonoDynamicImage *assembly)
4098 MonoImage *image = module->image;
4102 t = &image->tables [MONO_TABLE_TYPEDEF];
4104 for (i = 0; i < t->rows; ++i) {
4106 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4107 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4109 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4110 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4115 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4117 MonoDynamicTable *table;
4119 guint32 scope, scope_idx, impl, current_idx;
4120 gboolean forwarder = TRUE;
4121 gpointer iter = NULL;
4124 if (klass->nested_in) {
4125 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4128 scope = resolution_scope_from_image (assembly, klass->image);
4129 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4130 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4131 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4134 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4137 alloc_table (table, table->rows);
4138 current_idx = table->next_idx;
4139 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4141 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4142 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4143 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4144 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4145 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4149 while ((nested = mono_class_get_nested_types (klass, &iter)))
4150 add_exported_type (assemblyb, assembly, nested, current_idx);
4154 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4159 if (!assemblyb->type_forwarders)
4162 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4163 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4168 type = mono_reflection_type_get_handle (t);
4171 klass = mono_class_from_mono_type (type);
4173 add_exported_type (assemblyb, assembly, klass, 0);
4177 #define align_pointer(base,p)\
4179 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4181 (p) += 4 - (__diff & 3);\
4185 compare_constants (const void *a, const void *b)
4187 const guint32 *a_values = (const guint32 *)a;
4188 const guint32 *b_values = (const guint32 *)b;
4189 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4193 compare_semantics (const void *a, const void *b)
4195 const guint32 *a_values = (const guint32 *)a;
4196 const guint32 *b_values = (const guint32 *)b;
4197 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4200 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4204 compare_custom_attrs (const void *a, const void *b)
4206 const guint32 *a_values = (const guint32 *)a;
4207 const guint32 *b_values = (const guint32 *)b;
4209 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4213 compare_field_marshal (const void *a, const void *b)
4215 const guint32 *a_values = (const guint32 *)a;
4216 const guint32 *b_values = (const guint32 *)b;
4218 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4222 compare_nested (const void *a, const void *b)
4224 const guint32 *a_values = (const guint32 *)a;
4225 const guint32 *b_values = (const guint32 *)b;
4227 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4231 compare_genericparam (const void *a, const void *b)
4233 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4234 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4236 if ((*b_entry)->owner == (*a_entry)->owner)
4238 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4239 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4241 return (*a_entry)->owner - (*b_entry)->owner;
4245 compare_declsecurity_attrs (const void *a, const void *b)
4247 const guint32 *a_values = (const guint32 *)a;
4248 const guint32 *b_values = (const guint32 *)b;
4250 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4254 compare_interface_impl (const void *a, const void *b)
4256 const guint32 *a_values = (const guint32 *)a;
4257 const guint32 *b_values = (const guint32 *)b;
4259 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4263 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4267 pad_heap (MonoDynamicStream *sh)
4269 if (sh->index & 3) {
4270 int sz = 4 - (sh->index & 3);
4271 memset (sh->data + sh->index, 0, sz);
4278 MonoDynamicStream *stream;
4282 * build_compressed_metadata() fills in the blob of data that represents the
4283 * raw metadata as it will be saved in the PE file. The five streams are output
4284 * and the metadata tables are comnpressed from the guint32 array representation,
4285 * to the compressed on-disk format.
4288 build_compressed_metadata (MonoDynamicImage *assembly)
4290 MonoDynamicTable *table;
4292 guint64 valid_mask = 0;
4293 guint64 sorted_mask;
4294 guint32 heapt_size = 0;
4295 guint32 meta_size = 256; /* allow for header and other stuff */
4296 guint32 table_offset;
4297 guint32 ntables = 0;
4303 struct StreamDesc stream_desc [5];
4305 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4306 for (i = 0; i < assembly->gen_params->len; i++){
4307 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4308 write_generic_param_entry (assembly, entry);
4311 stream_desc [0].name = "#~";
4312 stream_desc [0].stream = &assembly->tstream;
4313 stream_desc [1].name = "#Strings";
4314 stream_desc [1].stream = &assembly->sheap;
4315 stream_desc [2].name = "#US";
4316 stream_desc [2].stream = &assembly->us;
4317 stream_desc [3].name = "#Blob";
4318 stream_desc [3].stream = &assembly->blob;
4319 stream_desc [4].name = "#GUID";
4320 stream_desc [4].stream = &assembly->guid;
4322 /* tables that are sorted */
4323 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4324 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4325 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4326 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4327 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4328 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4329 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4331 /* Compute table sizes */
4332 /* the MonoImage has already been created in mono_image_basic_init() */
4333 meta = &assembly->image;
4335 /* sizes should be multiple of 4 */
4336 pad_heap (&assembly->blob);
4337 pad_heap (&assembly->guid);
4338 pad_heap (&assembly->sheap);
4339 pad_heap (&assembly->us);
4341 /* Setup the info used by compute_sizes () */
4342 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4343 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4344 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4346 meta_size += assembly->blob.index;
4347 meta_size += assembly->guid.index;
4348 meta_size += assembly->sheap.index;
4349 meta_size += assembly->us.index;
4351 for (i=0; i < MONO_TABLE_NUM; ++i)
4352 meta->tables [i].rows = assembly->tables [i].rows;
4354 for (i = 0; i < MONO_TABLE_NUM; i++){
4355 if (meta->tables [i].rows == 0)
4357 valid_mask |= (guint64)1 << i;
4359 meta->tables [i].row_size = mono_metadata_compute_size (
4360 meta, i, &meta->tables [i].size_bitfield);
4361 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4363 heapt_size += 24; /* #~ header size */
4364 heapt_size += ntables * 4;
4365 /* make multiple of 4 */
4368 meta_size += heapt_size;
4369 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4370 p = (unsigned char*)meta->raw_metadata;
4371 /* the metadata signature */
4372 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4373 /* version numbers and 4 bytes reserved */
4374 int16val = (guint16*)p;
4375 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4376 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4378 /* version string */
4379 int32val = (guint32*)p;
4380 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4382 memcpy (p, meta->version, strlen (meta->version));
4383 p += GUINT32_FROM_LE (*int32val);
4384 align_pointer (meta->raw_metadata, p);
4385 int16val = (guint16*)p;
4386 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4387 *int16val = GUINT16_TO_LE (5); /* number of streams */
4391 * write the stream info.
4393 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4394 table_offset += 3; table_offset &= ~3;
4396 assembly->tstream.index = heapt_size;
4397 for (i = 0; i < 5; ++i) {
4398 int32val = (guint32*)p;
4399 stream_desc [i].stream->offset = table_offset;
4400 *int32val++ = GUINT32_TO_LE (table_offset);
4401 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4402 table_offset += GUINT32_FROM_LE (*int32val);
4403 table_offset += 3; table_offset &= ~3;
4405 strcpy ((char*)p, stream_desc [i].name);
4406 p += strlen (stream_desc [i].name) + 1;
4407 align_pointer (meta->raw_metadata, p);
4410 * now copy the data, the table stream header and contents goes first.
4412 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4413 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4414 int32val = (guint32*)p;
4415 *int32val = GUINT32_TO_LE (0); /* reserved */
4418 *p++ = 2; /* version */
4421 if (meta->idx_string_wide)
4423 if (meta->idx_guid_wide)
4425 if (meta->idx_blob_wide)
4428 *p++ = 1; /* reserved */
4429 int64val = (guint64*)p;
4430 *int64val++ = GUINT64_TO_LE (valid_mask);
4431 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4433 int32val = (guint32*)p;
4434 for (i = 0; i < MONO_TABLE_NUM; i++){
4435 if (meta->tables [i].rows == 0)
4437 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4439 p = (unsigned char*)int32val;
4441 /* sort the tables that still need sorting */
4442 table = &assembly->tables [MONO_TABLE_CONSTANT];
4444 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4445 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4447 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4448 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4450 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4451 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4453 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4454 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4456 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4457 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4458 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4460 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4461 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4463 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4465 /* compress the tables */
4466 for (i = 0; i < MONO_TABLE_NUM; i++){
4469 guint32 bitfield = meta->tables [i].size_bitfield;
4470 if (!meta->tables [i].rows)
4472 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4473 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4474 meta->tables [i].base = (char*)p;
4475 for (row = 1; row <= meta->tables [i].rows; ++row) {
4476 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4477 for (col = 0; col < assembly->tables [i].columns; ++col) {
4478 switch (mono_metadata_table_size (bitfield, col)) {
4480 *p++ = values [col];
4483 *p++ = values [col] & 0xff;
4484 *p++ = (values [col] >> 8) & 0xff;
4487 *p++ = values [col] & 0xff;
4488 *p++ = (values [col] >> 8) & 0xff;
4489 *p++ = (values [col] >> 16) & 0xff;
4490 *p++ = (values [col] >> 24) & 0xff;
4493 g_assert_not_reached ();
4497 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4500 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4501 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4502 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4503 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4504 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4506 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4510 * Some tables in metadata need to be sorted according to some criteria, but
4511 * when methods and fields are first created with reflection, they may be assigned a token
4512 * that doesn't correspond to the final token they will get assigned after the sorting.
4513 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4514 * with the reflection objects that represent them. Once all the tables are set up, the
4515 * reflection objects will contains the correct table index. fixup_method() will fixup the
4516 * tokens for the method with ILGenerator @ilgen.
4519 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4521 guint32 code_idx = GPOINTER_TO_UINT (value);
4522 MonoReflectionILTokenInfo *iltoken;
4523 MonoReflectionFieldBuilder *field;
4524 MonoReflectionCtorBuilder *ctor;
4525 MonoReflectionMethodBuilder *method;
4526 MonoReflectionTypeBuilder *tb;
4527 MonoReflectionArrayMethod *am;
4529 unsigned char *target;
4531 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4532 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4533 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4534 switch (target [3]) {
4535 case MONO_TABLE_FIELD:
4536 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4537 field = (MonoReflectionFieldBuilder *)iltoken->member;
4538 idx = field->table_idx;
4539 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4540 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4541 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4543 g_assert_not_reached ();
4546 case MONO_TABLE_METHOD:
4547 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4548 method = (MonoReflectionMethodBuilder *)iltoken->member;
4549 idx = method->table_idx;
4550 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4551 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4552 idx = ctor->table_idx;
4553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4554 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4555 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4556 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4558 g_assert_not_reached ();
4561 case MONO_TABLE_TYPEDEF:
4562 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4563 g_assert_not_reached ();
4564 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4565 idx = tb->table_idx;
4567 case MONO_TABLE_MEMBERREF:
4568 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4569 am = (MonoReflectionArrayMethod*)iltoken->member;
4570 idx = am->table_idx;
4571 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4572 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4573 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4574 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4575 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4576 g_assert (m->klass->generic_class || m->klass->generic_container);
4578 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4580 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4581 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4582 g_assert (is_field_on_inst (f));
4584 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4585 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4587 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4589 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4591 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4594 g_assert_not_reached ();
4597 case MONO_TABLE_METHODSPEC:
4598 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4599 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4600 g_assert (mono_method_signature (m)->generic_param_count);
4602 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4604 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4607 g_assert_not_reached ();
4611 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4613 target [0] = idx & 0xff;
4614 target [1] = (idx >> 8) & 0xff;
4615 target [2] = (idx >> 16) & 0xff;
4622 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4623 * value is not known when the table is emitted.
4626 fixup_cattrs (MonoDynamicImage *assembly)
4628 MonoDynamicTable *table;
4630 guint32 type, i, idx, token;
4633 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4635 for (i = 0; i < table->rows; ++i) {
4636 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4638 type = values [MONO_CUSTOM_ATTR_TYPE];
4639 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4640 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4641 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4642 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4645 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4646 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4647 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4648 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4649 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4650 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4651 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4652 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4659 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4661 MonoDynamicTable *table;
4664 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4666 alloc_table (table, table->rows);
4667 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4668 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4669 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4670 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4671 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4676 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4678 MonoDynamicTable *table;
4682 char *b = blob_size;
4684 guint32 idx, offset;
4686 if (rsrc->filename) {
4687 name = mono_string_to_utf8 (rsrc->filename);
4688 sname = g_path_get_basename (name);
4690 table = &assembly->tables [MONO_TABLE_FILE];
4692 alloc_table (table, table->rows);
4693 values = table->values + table->next_idx * MONO_FILE_SIZE;
4694 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4695 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4698 mono_sha1_get_digest_from_file (name, hash);
4699 mono_metadata_encode_value (20, b, &b);
4700 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4701 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4703 idx = table->next_idx++;
4705 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4711 data = mono_array_addr (rsrc->data, char, 0);
4712 len = mono_array_length (rsrc->data);
4718 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4719 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4720 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4721 mono_image_add_stream_data (&assembly->resources, data, len);
4725 * The entry should be emitted into the MANIFESTRESOURCE table of
4726 * the main module, but that needs to reference the FILE table
4727 * which isn't emitted yet.
4734 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4738 set_version_from_string (MonoString *version, guint32 *values)
4740 gchar *ver, *p, *str;
4743 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4744 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4745 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4746 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4749 ver = str = mono_string_to_utf8 (version);
4750 for (i = 0; i < 4; ++i) {
4751 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4757 /* handle Revision and Build */
4767 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4771 char *b = blob_size;
4776 len = mono_array_length (pkey);
4777 mono_metadata_encode_value (len, b, &b);
4778 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4779 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4781 assembly->public_key = (guint8 *)g_malloc (len);
4782 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4783 assembly->public_key_len = len;
4785 /* Special case: check for ECMA key (16 bytes) */
4786 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4787 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4788 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4789 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4790 /* minimum key size (in 2.0) is 384 bits */
4791 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4793 /* FIXME - verifier */
4794 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4795 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4797 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4803 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4805 MonoDynamicTable *table;
4806 MonoDynamicImage *assembly;
4807 MonoReflectionAssemblyBuilder *assemblyb;
4811 guint32 module_index;
4813 assemblyb = moduleb->assemblyb;
4814 assembly = moduleb->dynamic_image;
4815 domain = mono_object_domain (assemblyb);
4817 /* Emit ASSEMBLY table */
4818 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4819 alloc_table (table, 1);
4820 values = table->values + MONO_ASSEMBLY_SIZE;
4821 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4822 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4823 if (assemblyb->culture) {
4824 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4826 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4828 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4829 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4830 set_version_from_string (assemblyb->version, values);
4832 /* Emit FILE + EXPORTED_TYPE table */
4834 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4836 MonoReflectionModuleBuilder *file_module =
4837 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4838 if (file_module != moduleb) {
4839 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4841 if (file_module->types) {
4842 for (j = 0; j < file_module->num_types; ++j) {
4843 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4844 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4849 if (assemblyb->loaded_modules) {
4850 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4851 MonoReflectionModule *file_module =
4852 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4853 mono_image_fill_file_table (domain, file_module, assembly);
4855 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4858 if (assemblyb->type_forwarders)
4859 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4861 /* Emit MANIFESTRESOURCE table */
4863 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4865 MonoReflectionModuleBuilder *file_module =
4866 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4867 /* The table for the main module is emitted later */
4868 if (file_module != moduleb) {
4870 if (file_module->resources) {
4871 int len = mono_array_length (file_module->resources);
4872 for (j = 0; j < len; ++j) {
4873 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4874 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4881 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4884 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4885 * for the modulebuilder @moduleb.
4886 * At the end of the process, method and field tokens are fixed up and the
4887 * on-disk compressed metadata representation is created.
4888 * Return TRUE on success, or FALSE on failure and sets @error
4891 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4893 MonoDynamicTable *table;
4894 MonoDynamicImage *assembly;
4895 MonoReflectionAssemblyBuilder *assemblyb;
4901 mono_error_init (error);
4903 assemblyb = moduleb->assemblyb;
4904 assembly = moduleb->dynamic_image;
4905 domain = mono_object_domain (assemblyb);
4907 if (assembly->text_rva)
4910 assembly->text_rva = START_TEXT_RVA;
4912 if (moduleb->is_main) {
4913 mono_image_emit_manifest (moduleb);
4916 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4917 table->rows = 1; /* .<Module> */
4919 alloc_table (table, table->rows);
4921 * Set the first entry.
4923 values = table->values + table->columns;
4924 values [MONO_TYPEDEF_FLAGS] = 0;
4925 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4926 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4927 values [MONO_TYPEDEF_EXTENDS] = 0;
4928 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4929 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4932 * handle global methods
4933 * FIXME: test what to do when global methods are defined in multiple modules.
4935 if (moduleb->global_methods) {
4936 table = &assembly->tables [MONO_TABLE_METHOD];
4937 table->rows += mono_array_length (moduleb->global_methods);
4938 alloc_table (table, table->rows);
4939 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4940 mono_image_get_method_info (
4941 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4943 if (moduleb->global_fields) {
4944 table = &assembly->tables [MONO_TABLE_FIELD];
4945 table->rows += mono_array_length (moduleb->global_fields);
4946 alloc_table (table, table->rows);
4947 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4948 mono_image_get_field_info (
4949 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4952 table = &assembly->tables [MONO_TABLE_MODULE];
4953 alloc_table (table, 1);
4954 mono_image_fill_module_table (domain, moduleb, assembly);
4956 /* Collect all types into a list sorted by their table_idx */
4957 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4960 for (i = 0; i < moduleb->num_types; ++i) {
4961 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4962 collect_types (&types, type);
4965 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4966 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4967 table->rows += mono_ptr_array_size (types);
4968 alloc_table (table, table->rows);
4971 * Emit type names + namespaces at one place inside the string heap,
4972 * so load_class_names () needs to touch fewer pages.
4974 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4975 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4976 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4978 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4979 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4980 string_heap_insert_mstring (&assembly->sheap, tb->name);
4983 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4984 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4985 mono_image_get_type_info (domain, type, assembly);
4989 * table->rows is already set above and in mono_image_fill_module_table.
4991 /* add all the custom attributes at the end, once all the indexes are stable */
4992 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
4995 /* CAS assembly permissions */
4996 if (assemblyb->permissions_minimum)
4997 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4998 if (assemblyb->permissions_optional)
4999 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5000 if (assemblyb->permissions_refused)
5001 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5003 if (!module_add_cattrs (assembly, moduleb, error))
5007 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5009 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5010 * the final tokens and don't need another fixup pass. */
5012 if (moduleb->global_methods) {
5013 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5014 MonoReflectionMethodBuilder *mb = mono_array_get (
5015 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5016 if (!mono_image_add_methodimpl (assembly, mb, error))
5021 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5022 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5023 if (type->methods) {
5024 for (j = 0; j < type->num_methods; ++j) {
5025 MonoReflectionMethodBuilder *mb = mono_array_get (
5026 type->methods, MonoReflectionMethodBuilder*, j);
5028 if (!mono_image_add_methodimpl (assembly, mb, error))
5034 fixup_cattrs (assembly);
5037 mono_ptr_array_destroy (types);
5040 return mono_error_ok (error);
5043 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5046 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5048 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5051 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5055 guint32 import_lookup_table;
5059 guint32 import_address_table_rva;
5067 #ifndef DISABLE_REFLECTION_EMIT
5070 * mono_image_insert_string:
5071 * @module: module builder object
5074 * Insert @str into the user string stream of @module.
5077 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5079 MonoDynamicImage *assembly;
5084 if (!module->dynamic_image)
5085 mono_image_module_basic_init (module);
5087 assembly = module->dynamic_image;
5089 if (assembly->save) {
5090 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5091 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5092 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5094 char *swapped = g_malloc (2 * mono_string_length (str));
5095 const char *p = (const char*)mono_string_chars (str);
5097 swap_with_size (swapped, p, 2, mono_string_length (str));
5098 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5102 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5104 mono_image_add_stream_data (&assembly->us, "", 1);
5106 idx = assembly->us.index ++;
5109 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5111 return MONO_TOKEN_STRING | idx;
5115 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5119 MonoMethodSignature *sig;
5121 mono_error_init (error);
5123 klass = obj->vtable->klass;
5124 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5125 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5126 MonoMethodSignature *old;
5127 guint32 sig_token, parent;
5130 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5132 nargs = mono_array_length (opt_param_types);
5133 old = mono_method_signature (method);
5134 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5136 sig->hasthis = old->hasthis;
5137 sig->explicit_this = old->explicit_this;
5138 sig->call_convention = old->call_convention;
5139 sig->generic_param_count = old->generic_param_count;
5140 sig->param_count = old->param_count + nargs;
5141 sig->sentinelpos = old->param_count;
5142 sig->ret = old->ret;
5144 for (i = 0; i < old->param_count; i++)
5145 sig->params [i] = old->params [i];
5147 for (i = 0; i < nargs; i++) {
5148 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5149 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5152 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5153 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5154 parent >>= MONO_TYPEDEFORREF_BITS;
5156 parent <<= MONO_MEMBERREF_PARENT_BITS;
5157 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5159 sig_token = method_encode_signature (assembly, sig);
5160 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5161 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5162 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5163 ReflectionMethodBuilder rmb;
5164 guint32 parent, sig_token;
5165 int nopt_args, nparams, ngparams, i;
5167 reflection_methodbuilder_from_method_builder (&rmb, mb);
5168 rmb.opt_types = opt_param_types;
5169 nopt_args = mono_array_length (opt_param_types);
5171 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5172 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5173 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5175 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5176 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5177 sig->call_convention = rmb.call_conv;
5178 sig->generic_param_count = ngparams;
5179 sig->param_count = nparams + nopt_args;
5180 sig->sentinelpos = nparams;
5181 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5183 for (i = 0; i < nparams; i++) {
5184 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5185 sig->params [i] = mono_reflection_type_get_handle (rt);
5188 for (i = 0; i < nopt_args; i++) {
5189 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5190 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5193 sig_token = method_builder_encode_signature (assembly, &rmb);
5195 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5196 if (!mono_error_ok (error))
5198 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5200 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5201 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5203 char *name = mono_string_to_utf8 (rmb.name);
5204 token = mono_image_get_varargs_method_token (
5205 assembly, parent, name, sig_token);
5208 g_error ("requested method token for %s\n", klass->name);
5211 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5212 register_dyn_token (assembly, token, obj);
5215 g_assert (!mono_error_ok (error));
5220 * mono_image_create_token:
5221 * @assembly: a dynamic assembly
5223 * @register_token: Whenever to register the token in the assembly->tokens hash.
5225 * Get a token to insert in the IL code stream for the given MemberInfo.
5226 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5227 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5231 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5232 gboolean create_open_instance, gboolean register_token,
5238 mono_error_init (error);
5240 klass = obj->vtable->klass;
5242 /* Check for user defined reflection objects */
5243 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5244 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5245 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5249 if (strcmp (klass->name, "MethodBuilder") == 0) {
5250 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5251 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5253 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5254 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5256 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5257 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5258 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5259 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5260 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5262 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5263 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5265 token = mono_image_get_ctorbuilder_token (assembly, mb);
5266 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5267 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5268 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5269 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5270 if (tb->generic_params) {
5271 token = mono_image_get_generic_field_token (assembly, fb);
5273 if (tb->module->dynamic_image == assembly) {
5274 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5276 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5279 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5280 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5281 if (create_open_instance && tb->generic_params) {
5283 init_type_builder_generics (obj);
5284 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5285 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5286 token = mono_metadata_token_from_dor (token);
5287 } else if (tb->module->dynamic_image == assembly) {
5288 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5291 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5292 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5294 } else if (strcmp (klass->name, "MonoType") == 0) {
5295 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5296 MonoClass *mc = mono_class_from_mono_type (type);
5297 token = mono_metadata_token_from_dor (
5298 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5299 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5300 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5301 token = mono_metadata_token_from_dor (
5302 mono_image_typedef_or_ref (assembly, type));
5303 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5304 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5305 token = mono_metadata_token_from_dor (
5306 mono_image_typedef_or_ref (assembly, type));
5307 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5308 strcmp (klass->name, "MonoMethod") == 0 ||
5309 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5310 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5311 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5312 if (m->method->is_inflated) {
5313 if (create_open_instance)
5314 token = mono_image_get_methodspec_token (assembly, m->method);
5316 token = mono_image_get_inflated_method_token (assembly, m->method);
5317 } else if ((m->method->klass->image == &assembly->image) &&
5318 !m->method->klass->generic_class) {
5319 static guint32 method_table_idx = 0xffffff;
5320 if (m->method->klass->wastypebuilder) {
5321 /* we use the same token as the one that was assigned
5322 * to the Methodbuilder.
5323 * FIXME: do the equivalent for Fields.
5325 token = m->method->token;
5328 * Each token should have a unique index, but the indexes are
5329 * assigned by managed code, so we don't know about them. An
5330 * easy solution is to count backwards...
5332 method_table_idx --;
5333 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5336 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5338 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5339 } else if (strcmp (klass->name, "MonoField") == 0) {
5340 MonoReflectionField *f = (MonoReflectionField *)obj;
5341 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5342 static guint32 field_table_idx = 0xffffff;
5344 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5346 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5348 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5349 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5350 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5351 token = mono_image_get_array_token (assembly, m);
5352 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5353 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5354 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5355 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5356 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5357 token = mono_metadata_token_from_dor (
5358 mono_image_typedef_or_ref (assembly, type));
5359 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5360 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5361 token = mono_image_get_field_on_inst_token (assembly, f);
5362 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5363 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5364 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5365 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5366 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5367 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5368 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5369 MonoReflectionType *type = (MonoReflectionType *)obj;
5370 token = mono_metadata_token_from_dor (
5371 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5373 g_error ("requested token for %s\n", klass->name);
5377 mono_image_register_token (assembly, token, obj);
5383 * mono_image_register_token:
5385 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5386 * the Module.ResolveXXXToken () methods to work.
5389 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5393 dynamic_image_lock (assembly);
5394 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5396 /* There could be multiple MethodInfo objects with the same token */
5397 //g_assert (prev == obj);
5399 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5401 dynamic_image_unlock (assembly);
5404 static MonoDynamicImage*
5405 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5407 static const guchar entrycode [16] = {0xff, 0x25, 0};
5408 MonoDynamicImage *image;
5411 const char *version;
5413 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5414 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5416 version = mono_get_runtime_info ()->runtime_version;
5419 /* The MonoGHashTable's need GC tracking */
5420 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5422 image = g_new0 (MonoDynamicImage, 1);
5425 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5427 /*g_print ("created image %p\n", image);*/
5428 /* keep in sync with image.c */
5429 image->image.name = assembly_name;
5430 image->image.assembly_name = image->image.name; /* they may be different */
5431 image->image.module_name = module_name;
5432 image->image.version = g_strdup (version);
5433 image->image.md_version_major = 1;
5434 image->image.md_version_minor = 1;
5435 image->image.dynamic = TRUE;
5437 image->image.references = g_new0 (MonoAssembly*, 1);
5438 image->image.references [0] = NULL;
5440 mono_image_init (&image->image);
5442 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");
5443 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5444 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5445 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5446 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5447 image->handleref = g_hash_table_new (NULL, NULL);
5448 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");
5449 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5450 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");
5451 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");
5452 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5453 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5454 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5455 image->gen_params = g_ptr_array_new ();
5456 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5458 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5459 string_heap_init (&image->sheap);
5460 mono_image_add_stream_data (&image->us, "", 1);
5461 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5462 /* import tables... */
5463 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5464 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5465 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5466 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5467 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5468 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5469 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5470 stream_data_align (&image->code);
5472 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5474 for (i=0; i < MONO_TABLE_NUM; ++i) {
5475 image->tables [i].next_idx = 1;
5476 image->tables [i].columns = table_sizes [i];
5479 image->image.assembly = (MonoAssembly*)assembly;
5480 image->run = assembly->run;
5481 image->save = assembly->save;
5482 image->pe_kind = 0x1; /* ILOnly */
5483 image->machine = 0x14c; /* I386 */
5485 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5487 dynamic_images_lock ();
5489 if (!dynamic_images)
5490 dynamic_images = g_ptr_array_new ();
5492 g_ptr_array_add (dynamic_images, image);
5494 dynamic_images_unlock ();
5501 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5507 release_hashtable (MonoGHashTable **hash)
5510 mono_g_hash_table_destroy (*hash);
5516 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5518 release_hashtable (&image->token_fixups);
5519 release_hashtable (&image->handleref_managed);
5520 release_hashtable (&image->tokens);
5521 release_hashtable (&image->remapped_tokens);
5522 release_hashtable (&image->generic_def_objects);
5523 release_hashtable (&image->methodspec);
5526 // Free dynamic image pass one: Free resources but not image itself
5528 mono_dynamic_image_free (MonoDynamicImage *image)
5530 MonoDynamicImage *di = image;
5535 mono_g_hash_table_destroy (di->methodspec);
5537 g_hash_table_destroy (di->typespec);
5539 g_hash_table_destroy (di->typeref);
5541 g_hash_table_destroy (di->handleref);
5542 if (di->handleref_managed)
5543 mono_g_hash_table_destroy (di->handleref_managed);
5545 mono_g_hash_table_destroy (di->tokens);
5546 if (di->remapped_tokens)
5547 mono_g_hash_table_destroy (di->remapped_tokens);
5548 if (di->generic_def_objects)
5549 mono_g_hash_table_destroy (di->generic_def_objects);
5550 if (di->blob_cache) {
5551 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5552 g_hash_table_destroy (di->blob_cache);
5554 if (di->standalonesig_cache)
5555 g_hash_table_destroy (di->standalonesig_cache);
5556 for (list = di->array_methods; list; list = list->next) {
5557 ArrayMethod *am = (ArrayMethod *)list->data;
5562 g_list_free (di->array_methods);
5563 if (di->gen_params) {
5564 for (i = 0; i < di->gen_params->len; i++) {
5565 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5566 mono_gc_deregister_root ((char*) &entry->gparam);
5569 g_ptr_array_free (di->gen_params, TRUE);
5571 if (di->token_fixups)
5572 mono_g_hash_table_destroy (di->token_fixups);
5573 if (di->method_to_table_idx)
5574 g_hash_table_destroy (di->method_to_table_idx);
5575 if (di->field_to_table_idx)
5576 g_hash_table_destroy (di->field_to_table_idx);
5577 if (di->method_aux_hash)
5578 g_hash_table_destroy (di->method_aux_hash);
5579 if (di->vararg_aux_hash)
5580 g_hash_table_destroy (di->vararg_aux_hash);
5581 g_free (di->strong_name);
5582 g_free (di->win32_res);
5584 g_free (di->public_key);
5586 /*g_print ("string heap destroy for image %p\n", di);*/
5587 mono_dynamic_stream_reset (&di->sheap);
5588 mono_dynamic_stream_reset (&di->code);
5589 mono_dynamic_stream_reset (&di->resources);
5590 mono_dynamic_stream_reset (&di->us);
5591 mono_dynamic_stream_reset (&di->blob);
5592 mono_dynamic_stream_reset (&di->tstream);
5593 mono_dynamic_stream_reset (&di->guid);
5594 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5595 g_free (di->tables [i].values);
5598 dynamic_images_lock ();
5601 g_ptr_array_remove (dynamic_images, di);
5603 dynamic_images_unlock ();
5606 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5608 mono_dynamic_image_free_image (MonoDynamicImage *image)
5610 /* See create_dynamic_mono_image () */
5612 /* Allocated using GC_MALLOC */
5618 #ifndef DISABLE_REFLECTION_EMIT
5621 * mono_image_basic_init:
5622 * @assembly: an assembly builder object
5624 * Create the MonoImage that represents the assembly builder and setup some
5625 * of the helper hash table and the basic metadata streams.
5628 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5630 MonoDynamicAssembly *assembly;
5631 MonoDynamicImage *image;
5632 MonoDomain *domain = mono_object_domain (assemblyb);
5634 if (assemblyb->dynamic_assembly)
5638 /* assembly->assembly.image might be GC allocated */
5639 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5641 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5644 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5646 assembly->assembly.ref_count = 1;
5647 assembly->assembly.dynamic = TRUE;
5648 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5649 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5650 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5651 if (assemblyb->culture)
5652 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5654 assembly->assembly.aname.culture = g_strdup ("");
5656 if (assemblyb->version) {
5657 char *vstr = mono_string_to_utf8 (assemblyb->version);
5658 char **version = g_strsplit (vstr, ".", 4);
5659 char **parts = version;
5660 assembly->assembly.aname.major = atoi (*parts++);
5661 assembly->assembly.aname.minor = atoi (*parts++);
5662 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5663 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5665 g_strfreev (version);
5668 assembly->assembly.aname.major = 0;
5669 assembly->assembly.aname.minor = 0;
5670 assembly->assembly.aname.build = 0;
5671 assembly->assembly.aname.revision = 0;
5674 assembly->run = assemblyb->access != 2;
5675 assembly->save = assemblyb->access != 1;
5676 assembly->domain = domain;
5678 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5679 image->initial_image = TRUE;
5680 assembly->assembly.aname.name = image->image.name;
5681 assembly->assembly.image = &image->image;
5682 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5683 /* -1 to correct for the trailing NULL byte */
5684 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5685 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5687 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5690 mono_domain_assemblies_lock (domain);
5691 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5692 mono_domain_assemblies_unlock (domain);
5694 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5696 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5698 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5701 #endif /* !DISABLE_REFLECTION_EMIT */
5703 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5706 calc_section_size (MonoDynamicImage *assembly)
5710 /* alignment constraints */
5711 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5712 g_assert ((assembly->code.index % 4) == 0);
5713 assembly->meta_size += 3;
5714 assembly->meta_size &= ~3;
5715 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5716 g_assert ((assembly->resources.index % 4) == 0);
5718 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5719 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5722 if (assembly->win32_res) {
5723 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5725 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5726 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5730 assembly->sections [MONO_SECTION_RELOC].size = 12;
5731 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5741 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5745 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5747 ResTreeNode *t1 = (ResTreeNode*)a;
5748 ResTreeNode *t2 = (ResTreeNode*)b;
5750 return t1->id - t2->id;
5754 * resource_tree_create:
5756 * Organize the resources into a resource tree.
5758 static ResTreeNode *
5759 resource_tree_create (MonoArray *win32_resources)
5761 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5765 tree = g_new0 (ResTreeNode, 1);
5767 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5768 MonoReflectionWin32Resource *win32_res =
5769 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5773 /* FIXME: BUG: this stores managed references in unmanaged memory */
5774 lang_node = g_new0 (ResTreeNode, 1);
5775 lang_node->id = win32_res->lang_id;
5776 lang_node->win32_res = win32_res;
5778 /* Create type node if neccesary */
5780 for (l = tree->children; l; l = l->next)
5781 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5782 type_node = (ResTreeNode*)l->data;
5787 type_node = g_new0 (ResTreeNode, 1);
5788 type_node->id = win32_res->res_type;
5791 * The resource types have to be sorted otherwise
5792 * Windows Explorer can't display the version information.
5794 tree->children = g_slist_insert_sorted (tree->children,
5795 type_node, resource_tree_compare_by_id);
5798 /* Create res node if neccesary */
5800 for (l = type_node->children; l; l = l->next)
5801 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5802 res_node = (ResTreeNode*)l->data;
5807 res_node = g_new0 (ResTreeNode, 1);
5808 res_node->id = win32_res->res_id;
5809 type_node->children = g_slist_append (type_node->children, res_node);
5812 res_node->children = g_slist_append (res_node->children, lang_node);
5819 * resource_tree_encode:
5821 * Encode the resource tree into the format used in the PE file.
5824 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5827 MonoPEResourceDir dir;
5828 MonoPEResourceDirEntry dir_entry;
5829 MonoPEResourceDataEntry data_entry;
5831 guint32 res_id_entries;
5834 * For the format of the resource directory, see the article
5835 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5839 memset (&dir, 0, sizeof (dir));
5840 memset (&dir_entry, 0, sizeof (dir_entry));
5841 memset (&data_entry, 0, sizeof (data_entry));
5843 g_assert (sizeof (dir) == 16);
5844 g_assert (sizeof (dir_entry) == 8);
5845 g_assert (sizeof (data_entry) == 16);
5847 node->offset = p - begin;
5849 /* IMAGE_RESOURCE_DIRECTORY */
5850 res_id_entries = g_slist_length (node->children);
5851 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5853 memcpy (p, &dir, sizeof (dir));
5856 /* Reserve space for entries */
5858 p += sizeof (dir_entry) * res_id_entries;
5860 /* Write children */
5861 for (l = node->children; l; l = l->next) {
5862 ResTreeNode *child = (ResTreeNode*)l->data;
5864 if (child->win32_res) {
5867 child->offset = p - begin;
5869 /* IMAGE_RESOURCE_DATA_ENTRY */
5870 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5871 size = mono_array_length (child->win32_res->res_data);
5872 data_entry.rde_size = GUINT32_TO_LE (size);
5874 memcpy (p, &data_entry, sizeof (data_entry));
5875 p += sizeof (data_entry);
5877 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5880 resource_tree_encode (child, begin, p, &p);
5884 /* IMAGE_RESOURCE_ENTRY */
5885 for (l = node->children; l; l = l->next) {
5886 ResTreeNode *child = (ResTreeNode*)l->data;
5888 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5889 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5891 memcpy (entries, &dir_entry, sizeof (dir_entry));
5892 entries += sizeof (dir_entry);
5899 resource_tree_free (ResTreeNode * node)
5902 for (list = node->children; list; list = list->next)
5903 resource_tree_free ((ResTreeNode*)list->data);
5904 g_slist_free(node->children);
5909 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5914 MonoReflectionWin32Resource *win32_res;
5917 if (!assemblyb->win32_resources)
5921 * Resources are stored in a three level tree inside the PE file.
5922 * - level one contains a node for each type of resource
5923 * - level two contains a node for each resource
5924 * - level three contains a node for each instance of a resource for a
5925 * specific language.
5928 tree = resource_tree_create (assemblyb->win32_resources);
5930 /* Estimate the size of the encoded tree */
5932 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5933 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5934 size += mono_array_length (win32_res->res_data);
5936 /* Directory structure */
5937 size += mono_array_length (assemblyb->win32_resources) * 256;
5938 p = buf = (char *)g_malloc (size);
5940 resource_tree_encode (tree, p, p, &p);
5942 g_assert (p - buf <= size);
5944 assembly->win32_res = (char *)g_malloc (p - buf);
5945 assembly->win32_res_size = p - buf;
5946 memcpy (assembly->win32_res, buf, p - buf);
5949 resource_tree_free (tree);
5953 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5955 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5958 p += sizeof (MonoPEResourceDir);
5959 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5960 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5961 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5962 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5963 fixup_resource_directory (res_section, child, rva);
5965 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5966 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5969 p += sizeof (MonoPEResourceDirEntry);
5974 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5977 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5978 g_error ("WriteFile returned %d\n", GetLastError ());
5982 * mono_image_create_pefile:
5983 * @mb: a module builder object
5985 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5986 * assembly->pefile where it can be easily retrieved later in chunks.
5989 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5992 MonoMSDOSHeader *msdos;
5993 MonoDotNetHeader *header;
5994 MonoSectionTable *section;
5995 MonoCLIHeader *cli_header;
5996 guint32 size, image_size, virtual_base, text_offset;
5997 guint32 header_start, section_start, file_offset, virtual_offset;
5998 MonoDynamicImage *assembly;
5999 MonoReflectionAssemblyBuilder *assemblyb;
6000 MonoDynamicStream pefile_stream = {0};
6001 MonoDynamicStream *pefile = &pefile_stream;
6003 guint32 *rva, value;
6005 static const unsigned char msheader[] = {
6006 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6007 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6010 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6011 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6012 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6013 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6016 assemblyb = mb->assemblyb;
6018 mono_image_basic_init (assemblyb);
6019 assembly = mb->dynamic_image;
6021 assembly->pe_kind = assemblyb->pe_kind;
6022 assembly->machine = assemblyb->machine;
6023 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6024 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6026 if (!mono_image_build_metadata (mb, &error))
6027 mono_error_raise_exception (&error); /* FIXME don't raise here */
6030 if (mb->is_main && assemblyb->resources) {
6031 int len = mono_array_length (assemblyb->resources);
6032 for (i = 0; i < len; ++i)
6033 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6036 if (mb->resources) {
6037 int len = mono_array_length (mb->resources);
6038 for (i = 0; i < len; ++i)
6039 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6042 build_compressed_metadata (assembly);
6045 assembly_add_win32_resources (assembly, assemblyb);
6047 nsections = calc_section_size (assembly);
6049 /* The DOS header and stub */
6050 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6051 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6053 /* the dotnet header */
6054 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6056 /* the section tables */
6057 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6059 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6060 virtual_offset = VIRT_ALIGN;
6063 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6064 if (!assembly->sections [i].size)
6067 file_offset += FILE_ALIGN - 1;
6068 file_offset &= ~(FILE_ALIGN - 1);
6069 virtual_offset += VIRT_ALIGN - 1;
6070 virtual_offset &= ~(VIRT_ALIGN - 1);
6072 assembly->sections [i].offset = file_offset;
6073 assembly->sections [i].rva = virtual_offset;
6075 file_offset += assembly->sections [i].size;
6076 virtual_offset += assembly->sections [i].size;
6077 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6080 file_offset += FILE_ALIGN - 1;
6081 file_offset &= ~(FILE_ALIGN - 1);
6083 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6085 /* back-patch info */
6086 msdos = (MonoMSDOSHeader*)pefile->data;
6087 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6089 header = (MonoDotNetHeader*)(pefile->data + header_start);
6090 header->pesig [0] = 'P';
6091 header->pesig [1] = 'E';
6093 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6094 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6095 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6096 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6097 if (assemblyb->pekind == 1) {
6099 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6102 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6105 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6107 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6108 header->pe.pe_major = 6;
6109 header->pe.pe_minor = 0;
6110 size = assembly->sections [MONO_SECTION_TEXT].size;
6111 size += FILE_ALIGN - 1;
6112 size &= ~(FILE_ALIGN - 1);
6113 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6114 size = assembly->sections [MONO_SECTION_RSRC].size;
6115 size += FILE_ALIGN - 1;
6116 size &= ~(FILE_ALIGN - 1);
6117 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6118 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6119 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6120 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6121 /* pe_rva_entry_point always at the beginning of the text section */
6122 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6124 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6125 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6126 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6127 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6128 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6129 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6130 size = section_start;
6131 size += FILE_ALIGN - 1;
6132 size &= ~(FILE_ALIGN - 1);
6133 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6135 size += VIRT_ALIGN - 1;
6136 size &= ~(VIRT_ALIGN - 1);
6137 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6140 // Translate the PEFileKind value to the value expected by the Windows loader
6146 // PEFileKinds.Dll == 1
6147 // PEFileKinds.ConsoleApplication == 2
6148 // PEFileKinds.WindowApplication == 3
6151 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6152 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6154 if (assemblyb->pekind == 3)
6159 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6161 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6162 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6163 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6164 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6165 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6166 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6168 /* fill data directory entries */
6170 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6171 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6173 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6174 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6176 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6177 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6178 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6179 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6180 /* patch entrypoint name */
6181 if (assemblyb->pekind == 1)
6182 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6184 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6185 /* patch imported function RVA name */
6186 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6187 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6189 /* the import table */
6190 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6191 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6192 /* patch imported dll RVA name and other entries in the dir */
6193 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6194 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6195 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6196 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6197 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6198 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6200 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6201 value = (assembly->text_rva + assembly->imp_names_offset);
6202 *p++ = (value) & 0xff;
6203 *p++ = (value >> 8) & (0xff);
6204 *p++ = (value >> 16) & (0xff);
6205 *p++ = (value >> 24) & (0xff);
6207 /* the CLI header info */
6208 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6209 cli_header->ch_size = GUINT32_FROM_LE (72);
6210 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6211 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6212 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6213 if (assemblyb->entry_point) {
6214 guint32 table_idx = 0;
6215 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6216 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6217 table_idx = methodb->table_idx;
6219 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6221 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6223 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6225 /* The embedded managed resources */
6226 text_offset = assembly->text_rva + assembly->code.index;
6227 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6228 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6229 text_offset += assembly->resources.index;
6230 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6231 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6232 text_offset += assembly->meta_size;
6233 if (assembly->strong_name_size) {
6234 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6235 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6236 text_offset += assembly->strong_name_size;
6239 /* write the section tables and section content */
6240 section = (MonoSectionTable*)(pefile->data + section_start);
6241 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6242 static const char section_names [][7] = {
6243 ".text", ".rsrc", ".reloc"
6245 if (!assembly->sections [i].size)
6247 strcpy (section->st_name, section_names [i]);
6248 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6249 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6250 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6251 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6252 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6253 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6254 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6258 checked_write_file (file, pefile->data, pefile->index);
6260 mono_dynamic_stream_reset (pefile);
6262 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6263 if (!assembly->sections [i].size)
6266 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6267 g_error ("SetFilePointer returned %d\n", GetLastError ());
6270 case MONO_SECTION_TEXT:
6271 /* patch entry point */
6272 p = (guchar*)(assembly->code.data + 2);
6273 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6274 *p++ = (value) & 0xff;
6275 *p++ = (value >> 8) & 0xff;
6276 *p++ = (value >> 16) & 0xff;
6277 *p++ = (value >> 24) & 0xff;
6279 checked_write_file (file, assembly->code.data, assembly->code.index);
6280 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6281 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6282 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6285 g_free (assembly->image.raw_metadata);
6287 case MONO_SECTION_RELOC: {
6291 guint16 type_and_offset;
6295 g_assert (sizeof (reloc) == 12);
6297 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6298 reloc.block_size = GUINT32_FROM_LE (12);
6301 * the entrypoint is always at the start of the text section
6302 * 3 is IMAGE_REL_BASED_HIGHLOW
6303 * 2 is patch_size_rva - text_rva
6305 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6308 checked_write_file (file, &reloc, sizeof (reloc));
6312 case MONO_SECTION_RSRC:
6313 if (assembly->win32_res) {
6315 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6316 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6317 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6321 g_assert_not_reached ();
6325 /* check that the file is properly padded */
6326 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6327 g_error ("SetFilePointer returned %d\n", GetLastError ());
6328 if (! SetEndOfFile (file))
6329 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6331 mono_dynamic_stream_reset (&assembly->code);
6332 mono_dynamic_stream_reset (&assembly->us);
6333 mono_dynamic_stream_reset (&assembly->blob);
6334 mono_dynamic_stream_reset (&assembly->guid);
6335 mono_dynamic_stream_reset (&assembly->sheap);
6337 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6338 g_hash_table_destroy (assembly->blob_cache);
6339 assembly->blob_cache = NULL;
6342 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6345 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6347 g_assert_not_reached ();
6350 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6352 #ifndef DISABLE_REFLECTION_EMIT
6354 MonoReflectionModule *
6355 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6359 MonoImageOpenStatus status;
6360 MonoDynamicAssembly *assembly;
6361 guint32 module_count;
6362 MonoImage **new_modules;
6363 gboolean *new_modules_loaded;
6365 name = mono_string_to_utf8 (fileName);
6367 image = mono_image_open (name, &status);
6370 if (status == MONO_IMAGE_ERROR_ERRNO)
6371 exc = mono_get_exception_file_not_found (fileName);
6373 exc = mono_get_exception_bad_image_format (name);
6375 mono_raise_exception (exc);
6380 assembly = ab->dynamic_assembly;
6381 image->assembly = (MonoAssembly*)assembly;
6383 module_count = image->assembly->image->module_count;
6384 new_modules = g_new0 (MonoImage *, module_count + 1);
6385 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6387 if (image->assembly->image->modules)
6388 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6389 if (image->assembly->image->modules_loaded)
6390 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6391 new_modules [module_count] = image;
6392 new_modules_loaded [module_count] = TRUE;
6393 mono_image_addref (image);
6395 g_free (image->assembly->image->modules);
6396 image->assembly->image->modules = new_modules;
6397 image->assembly->image->modules_loaded = new_modules_loaded;
6398 image->assembly->image->module_count ++;
6400 mono_assembly_load_references (image, &status);
6402 mono_image_close (image);
6403 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6406 return mono_module_get_object (mono_domain_get (), image);
6409 #endif /* DISABLE_REFLECTION_EMIT */
6412 * We need to return always the same object for MethodInfo, FieldInfo etc..
6413 * but we need to consider the reflected type.
6414 * type uses a different hash, since it uses custom hash/equal functions.
6419 MonoClass *refclass;
6423 reflected_equal (gconstpointer a, gconstpointer b) {
6424 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6425 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6427 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6431 reflected_hash (gconstpointer a) {
6432 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6433 return mono_aligned_addr_hash (ea->item);
6436 #define CHECK_OBJECT(t,p,k) \
6442 mono_domain_lock (domain); \
6443 if (!domain->refobject_hash) \
6444 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"); \
6445 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6446 mono_domain_unlock (domain); \
6449 mono_domain_unlock (domain); \
6452 #ifdef HAVE_BOEHM_GC
6453 /* ReflectedEntry doesn't need to be GC tracked */
6454 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6455 #define FREE_REFENTRY(entry) g_free ((entry))
6456 #define REFENTRY_REQUIRES_CLEANUP
6458 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6460 #define FREE_REFENTRY(entry)
6463 #define CACHE_OBJECT(t,p,o,k) \
6466 ReflectedEntry pe; \
6468 pe.refclass = (k); \
6469 mono_domain_lock (domain); \
6470 if (!domain->refobject_hash) \
6471 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"); \
6472 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6474 ReflectedEntry *e = ALLOC_REFENTRY; \
6476 e->refclass = (k); \
6477 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6480 mono_domain_unlock (domain); \
6485 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6487 mono_domain_lock (domain);
6488 if (domain->refobject_hash) {
6490 gpointer orig_pe, orig_value;
6493 pe.refclass = klass;
6494 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6495 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6496 FREE_REFENTRY (orig_pe);
6499 mono_domain_unlock (domain);
6502 #ifdef REFENTRY_REQUIRES_CLEANUP
6504 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6506 FREE_REFENTRY (key);
6511 mono_reflection_cleanup_domain (MonoDomain *domain)
6513 if (domain->refobject_hash) {
6514 /*let's avoid scanning the whole hashtable if not needed*/
6515 #ifdef REFENTRY_REQUIRES_CLEANUP
6516 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6518 mono_g_hash_table_destroy (domain->refobject_hash);
6519 domain->refobject_hash = NULL;
6523 #ifndef DISABLE_REFLECTION_EMIT
6525 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6527 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6531 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6533 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6537 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6539 MonoDynamicImage *image = moduleb->dynamic_image;
6540 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6544 MonoImage **new_modules;
6546 char *name, *fqname;
6548 * FIXME: we already created an image in mono_image_basic_init (), but
6549 * we don't know which module it belongs to, since that is only
6550 * determined at assembly save time.
6552 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6553 name = mono_string_to_utf8 (ab->name);
6554 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6555 if (!mono_error_ok (&error)) {
6557 mono_error_raise_exception (&error);
6559 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6561 moduleb->module.image = &image->image;
6562 moduleb->dynamic_image = image;
6563 register_module (mono_object_domain (moduleb), moduleb, image);
6565 /* register the module with the assembly */
6566 ass = ab->dynamic_assembly->assembly.image;
6567 module_count = ass->module_count;
6568 new_modules = g_new0 (MonoImage *, module_count + 1);
6571 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6572 new_modules [module_count] = &image->image;
6573 mono_image_addref (&image->image);
6575 g_free (ass->modules);
6576 ass->modules = new_modules;
6577 ass->module_count ++;
6582 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6584 MonoDynamicImage *image = moduleb->dynamic_image;
6586 g_assert (type->type);
6587 image->wrappers_type = mono_class_from_mono_type (type->type);
6593 * mono_assembly_get_object:
6594 * @domain: an app domain
6595 * @assembly: an assembly
6597 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6599 MonoReflectionAssembly*
6600 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6603 static MonoClass *assembly_type;
6604 MonoReflectionAssembly *res;
6606 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6607 if (!assembly_type) {
6608 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6610 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6612 assembly_type = klass;
6614 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6615 mono_error_raise_exception (&error); /* FIXME don't raise here */
6616 res->assembly = assembly;
6618 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6623 MonoReflectionModule*
6624 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6627 static MonoClass *module_type;
6628 MonoReflectionModule *res;
6631 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6633 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6635 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6637 module_type = klass;
6639 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6640 mono_error_raise_exception (&error); /* FIXME don't raise here */
6643 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6645 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6646 basename = g_path_get_basename (image->name);
6647 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6648 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6652 if (image->assembly->image == image) {
6653 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6657 if (image->assembly->image->modules) {
6658 for (i = 0; i < image->assembly->image->module_count; i++) {
6659 if (image->assembly->image->modules [i] == image)
6660 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6662 g_assert (res->token);
6666 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6669 MonoReflectionModule*
6670 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6673 static MonoClass *module_type;
6674 MonoReflectionModule *res;
6675 MonoTableInfo *table;
6676 guint32 cols [MONO_FILE_SIZE];
6678 guint32 i, name_idx;
6682 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6684 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6686 module_type = klass;
6688 res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6689 mono_error_raise_exception (&error); /* FIXME don't raise here */
6691 table = &image->tables [MONO_TABLE_FILE];
6692 g_assert (table_index < table->rows);
6693 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6696 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6697 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6699 /* Check whenever the row has a corresponding row in the moduleref table */
6700 table = &image->tables [MONO_TABLE_MODULEREF];
6701 for (i = 0; i < table->rows; ++i) {
6702 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6703 val = mono_metadata_string_heap (image, name_idx);
6704 if (strcmp (val, name) == 0)
6705 res->image = image->modules [i];
6708 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6709 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6710 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6711 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6712 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6718 verify_safe_for_managed_space (MonoType *type)
6720 switch (type->type) {
6722 case MONO_TYPE_ARRAY:
6723 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6725 return verify_safe_for_managed_space (type->data.type);
6726 case MONO_TYPE_SZARRAY:
6727 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6728 case MONO_TYPE_GENERICINST: {
6729 MonoGenericInst *inst = type->data.generic_class->inst;
6733 for (i = 0; i < inst->type_argc; ++i)
6734 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6740 case MONO_TYPE_MVAR:
6748 mono_type_normalize (MonoType *type)
6751 MonoGenericClass *gclass;
6752 MonoGenericInst *ginst;
6754 MonoGenericContainer *gcontainer;
6755 MonoType **argv = NULL;
6756 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6758 if (type->type != MONO_TYPE_GENERICINST)
6761 gclass = type->data.generic_class;
6762 ginst = gclass->context.class_inst;
6763 if (!ginst->is_open)
6766 gtd = gclass->container_class;
6767 gcontainer = gtd->generic_container;
6768 argv = g_newa (MonoType*, ginst->type_argc);
6770 for (i = 0; i < ginst->type_argc; ++i) {
6771 MonoType *t = ginst->type_argv [i], *norm;
6772 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6773 is_denorm_gtd = FALSE;
6774 norm = mono_type_normalize (t);
6777 requires_rebind = TRUE;
6781 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6783 if (requires_rebind) {
6784 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6785 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6791 * mono_type_get_object:
6792 * @domain: an app domain
6795 * Return an System.MonoType object representing the type @type.
6798 mono_type_get_object (MonoDomain *domain, MonoType *type)
6801 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6802 mono_error_raise_exception (&error);
6808 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6810 MonoType *norm_type;
6811 MonoReflectionType *res;
6814 mono_error_init (error);
6816 klass = mono_class_from_mono_type (type);
6818 /*we must avoid using @type as it might have come
6819 * from a mono_metadata_type_dup and the caller
6820 * expects that is can be freed.
6821 * Using the right type from
6823 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6825 /* void is very common */
6826 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6827 return (MonoReflectionType*)domain->typeof_void;
6830 * If the vtable of the given class was already created, we can use
6831 * the MonoType from there and avoid all locking and hash table lookups.
6833 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6834 * that the resulting object is different.
6836 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6837 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6838 if (vtable && vtable->type)
6839 return (MonoReflectionType *)vtable->type;
6842 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6843 mono_domain_lock (domain);
6844 if (!domain->type_hash)
6845 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6846 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6847 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6848 mono_domain_unlock (domain);
6849 mono_loader_unlock ();
6853 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6854 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6855 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6856 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6857 * artifact of how generics are encoded and should be transparent to managed code so we
6858 * need to weed out this diference when retrieving managed System.Type objects.
6860 norm_type = mono_type_normalize (type);
6861 if (norm_type != type) {
6862 res = mono_type_get_object_checked (domain, norm_type, error);
6863 if (!mono_error_ok (error))
6865 mono_g_hash_table_insert (domain->type_hash, type, res);
6866 mono_domain_unlock (domain);
6867 mono_loader_unlock ();
6871 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6872 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6875 if (!verify_safe_for_managed_space (type)) {
6876 mono_domain_unlock (domain);
6877 mono_loader_unlock ();
6878 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6882 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6883 gboolean is_type_done = TRUE;
6884 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6885 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6886 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6888 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6889 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6891 if (gparam->owner && gparam->owner->is_method) {
6892 MonoMethod *method = gparam->owner->owner.method;
6893 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6894 is_type_done = FALSE;
6895 } else if (gparam->owner && !gparam->owner->is_method) {
6896 MonoClass *klass = gparam->owner->owner.klass;
6897 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6898 is_type_done = FALSE;
6902 /* g_assert_not_reached (); */
6903 /* should this be considered an error condition? */
6904 if (is_type_done && !type->byref) {
6905 mono_domain_unlock (domain);
6906 mono_loader_unlock ();
6907 return (MonoReflectionType *)mono_class_get_ref_info (klass);
6910 /* This is stored in vtables/JITted code so it has to be pinned */
6911 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6912 if (!mono_error_ok (error))
6916 mono_g_hash_table_insert (domain->type_hash, type, res);
6918 if (type->type == MONO_TYPE_VOID)
6919 domain->typeof_void = (MonoObject*)res;
6921 mono_domain_unlock (domain);
6922 mono_loader_unlock ();
6927 * mono_method_get_object:
6928 * @domain: an app domain
6930 * @refclass: the reflected type (can be NULL)
6932 * Return an System.Reflection.MonoMethod object representing the method @method.
6934 MonoReflectionMethod*
6935 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6938 MonoReflectionMethod *ret = NULL;
6939 ret = mono_method_get_object_checked (domain, method, refclass, &error);
6940 mono_error_raise_exception (&error);
6945 * mono_method_get_object_checked:
6946 * @domain: an app domain
6948 * @refclass: the reflected type (can be NULL)
6949 * @error: set on error.
6951 * Return an System.Reflection.MonoMethod object representing the method @method.
6952 * Returns NULL and sets @error on error.
6954 MonoReflectionMethod*
6955 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6958 * We use the same C representation for methods and constructors, but the type
6959 * name in C# is different.
6961 static MonoClass *System_Reflection_MonoMethod = NULL;
6962 static MonoClass *System_Reflection_MonoCMethod = NULL;
6963 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6964 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6965 MonoReflectionType *rt;
6967 MonoReflectionMethod *ret;
6969 mono_error_init (error);
6971 if (method->is_inflated) {
6972 MonoReflectionGenericMethod *gret;
6975 refclass = method->klass;
6976 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6977 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6978 if (!System_Reflection_MonoGenericCMethod) {
6979 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6980 if (!mono_error_ok (error))
6983 klass = System_Reflection_MonoGenericCMethod;
6985 if (!System_Reflection_MonoGenericMethod) {
6986 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
6987 if (!mono_error_ok (error))
6990 klass = System_Reflection_MonoGenericMethod;
6992 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
6993 if (!mono_error_ok (error))
6995 gret->method.method = method;
6997 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6999 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7000 if (!mono_error_ok (error))
7003 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7005 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7009 refclass = method->klass;
7011 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7012 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7013 if (!System_Reflection_MonoCMethod) {
7014 System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7015 if (!mono_error_ok (error))
7018 klass = System_Reflection_MonoCMethod;
7021 if (!System_Reflection_MonoMethod) {
7022 System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7023 if (!mono_error_ok (error))
7026 klass = System_Reflection_MonoMethod;
7028 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7029 if (!mono_error_ok (error))
7031 ret->method = method;
7033 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7034 if (!mono_error_ok (error))
7037 MONO_OBJECT_SETREF (ret, reftype, rt);
7039 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7042 g_assert (!mono_error_ok (error));
7047 * mono_method_clear_object:
7049 * Clear the cached reflection objects for the dynamic method METHOD.
7052 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7055 g_assert (method_is_dynamic (method));
7057 klass = method->klass;
7059 clear_cached_object (domain, method, klass);
7060 klass = klass->parent;
7062 /* Added by mono_param_get_objects () */
7063 clear_cached_object (domain, &(method->signature), NULL);
7064 klass = method->klass;
7066 clear_cached_object (domain, &(method->signature), klass);
7067 klass = klass->parent;
7072 * mono_field_get_object:
7073 * @domain: an app domain
7077 * Return an System.Reflection.MonoField object representing the field @field
7080 MonoReflectionField*
7081 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7084 MonoReflectionField *result;
7085 result = mono_field_get_object_checked (domain, klass, field, &error);
7086 mono_error_raise_exception (&error);
7091 * mono_field_get_object_checked:
7092 * @domain: an app domain
7095 * @error: set on error
7097 * Return an System.Reflection.MonoField object representing the field @field
7098 * in class @klass. On error, returns NULL and sets @error.
7100 MonoReflectionField*
7101 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7103 MonoReflectionType *rt;
7104 MonoReflectionField *res;
7105 static MonoClass *monofield_klass;
7107 mono_error_init (error);
7109 CHECK_OBJECT (MonoReflectionField *, field, klass);
7110 if (!monofield_klass)
7111 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7112 res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7113 mono_error_raise_exception (error); /* FIXME don't raise here */
7116 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7118 if (is_field_on_inst (field)) {
7119 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7121 rt = mono_type_get_object_checked (domain, field->type, error);
7122 if (!mono_error_ok (error))
7125 MONO_OBJECT_SETREF (res, type, rt);
7128 rt = mono_type_get_object_checked (domain, field->type, error);
7129 if (!mono_error_ok (error))
7132 MONO_OBJECT_SETREF (res, type, rt);
7134 res->attrs = mono_field_get_flags (field);
7136 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7140 * mono_property_get_object:
7141 * @domain: an app domain
7143 * @property: a property
7145 * Return an System.Reflection.MonoProperty object representing the property @property
7148 MonoReflectionProperty*
7149 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7152 MonoReflectionProperty *res;
7153 static MonoClass *monoproperty_klass;
7155 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7156 if (!monoproperty_klass)
7157 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7158 res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7159 mono_error_raise_exception (&error); /* FIXME don't raise here */
7161 res->property = property;
7162 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7166 * mono_event_get_object:
7167 * @domain: an app domain
7171 * Return an System.Reflection.MonoEvent object representing the event @event
7174 MonoReflectionEvent*
7175 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7178 MonoReflectionEvent *res;
7179 MonoReflectionMonoEvent *mono_event;
7180 static MonoClass *monoevent_klass;
7182 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7183 if (!monoevent_klass)
7184 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7185 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7186 mono_error_raise_exception (&error); /* FIXME don't raise here */
7187 mono_event->klass = klass;
7188 mono_event->event = event;
7189 res = (MonoReflectionEvent*)mono_event;
7190 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7194 * mono_get_reflection_missing_object:
7195 * @domain: Domain where the object lives
7197 * Returns the System.Reflection.Missing.Value singleton object
7198 * (of type System.Reflection.Missing).
7200 * Used as the value for ParameterInfo.DefaultValue when Optional
7204 mono_get_reflection_missing_object (MonoDomain *domain)
7207 static MonoClassField *missing_value_field = NULL;
7209 if (!missing_value_field) {
7210 MonoClass *missing_klass;
7211 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7212 mono_class_init (missing_klass);
7213 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7214 g_assert (missing_value_field);
7216 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7222 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7225 *dbnull = mono_get_dbnull_object (domain);
7230 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7232 if (!*reflection_missing)
7233 *reflection_missing = mono_get_reflection_missing_object (domain);
7234 return *reflection_missing;
7238 * mono_param_get_objects:
7239 * @domain: an app domain
7242 * Return an System.Reflection.ParameterInfo array object representing the parameters
7243 * in the method @method.
7246 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7248 static MonoClass *System_Reflection_ParameterInfo;
7249 static MonoClass *System_Reflection_ParameterInfo_array;
7251 MonoArray *res = NULL;
7252 MonoReflectionMethod *member = NULL;
7253 MonoReflectionParameter *param = NULL;
7254 char **names, **blobs = NULL;
7255 guint32 *types = NULL;
7256 MonoType *type = NULL;
7257 MonoObject *dbnull = NULL;
7258 MonoObject *missing = NULL;
7259 MonoMarshalSpec **mspecs;
7260 MonoMethodSignature *sig;
7261 MonoVTable *pinfo_vtable;
7262 MonoReflectionType *rt;
7265 if (!System_Reflection_ParameterInfo_array) {
7268 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7270 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7272 mono_memory_barrier ();
7273 System_Reflection_ParameterInfo = klass;
7276 klass = mono_array_class_get (klass, 1);
7277 mono_memory_barrier ();
7278 System_Reflection_ParameterInfo_array = klass;
7281 sig = mono_method_signature_checked (method, &error);
7282 if (!mono_error_ok (&error))
7283 mono_error_raise_exception (&error);
7285 if (!sig->param_count) {
7286 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7287 mono_error_raise_exception (&error); /* FIXME don't raise here */
7292 /* Note: the cache is based on the address of the signature into the method
7293 * since we already cache MethodInfos with the method as keys.
7295 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7297 member = mono_method_get_object_checked (domain, method, refclass, &error);
7298 mono_error_raise_exception (&error); /* FIXME don't raise here */
7299 names = g_new (char *, sig->param_count);
7300 mono_method_get_param_names (method, (const char **) names);
7302 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7303 mono_method_get_marshal_info (method, mspecs);
7305 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7306 mono_error_raise_exception (&error); /* FIXME don't raise here */
7308 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7309 for (i = 0; i < sig->param_count; ++i) {
7310 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7311 mono_error_raise_exception (&error); /* FIXME don't raise here */
7313 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7314 mono_error_raise_exception (&error); /* FIXME don't raise here */
7316 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7318 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7320 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7322 param->PositionImpl = i;
7323 param->AttrsImpl = sig->params [i]->attrs;
7325 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7326 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7327 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7329 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7333 blobs = g_new0 (char *, sig->param_count);
7334 types = g_new0 (guint32, sig->param_count);
7335 get_default_param_value_blobs (method, blobs, types);
7338 /* Build MonoType for the type from the Constant Table */
7340 type = g_new0 (MonoType, 1);
7341 type->type = (MonoTypeEnum)types [i];
7342 type->data.klass = NULL;
7343 if (types [i] == MONO_TYPE_CLASS)
7344 type->data.klass = mono_defaults.object_class;
7345 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7346 /* For enums, types [i] contains the base type */
7348 type->type = MONO_TYPE_VALUETYPE;
7349 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7351 type->data.klass = mono_class_from_mono_type (type);
7353 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7355 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7356 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7357 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7358 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7360 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7366 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7368 mono_array_setref (res, i, param);
7375 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7377 mono_metadata_free_marshal_spec (mspecs [i]);
7380 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7384 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7386 return mono_param_get_objects_internal (domain, method, NULL);
7390 * mono_method_body_get_object:
7391 * @domain: an app domain
7394 * Return an System.Reflection.MethodBody object representing the method @method.
7396 MonoReflectionMethodBody*
7397 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7399 static MonoClass *System_Reflection_MethodBody = NULL;
7400 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7401 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7403 MonoReflectionMethodBody *ret;
7404 MonoMethodHeader *header;
7406 MonoReflectionType *rt;
7407 guint32 method_rva, local_var_sig_token;
7409 unsigned char format, flags;
7412 /* for compatibility with .net */
7413 if (method_is_dynamic (method))
7414 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7416 if (!System_Reflection_MethodBody)
7417 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7418 if (!System_Reflection_LocalVariableInfo)
7419 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7420 if (!System_Reflection_ExceptionHandlingClause)
7421 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7423 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7425 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7426 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7427 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7428 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7429 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7432 image = method->klass->image;
7433 header = mono_method_get_header (method);
7435 if (!image_is_dynamic (image)) {
7436 /* Obtain local vars signature token */
7437 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7438 ptr = mono_image_rva_map (image, method_rva);
7439 flags = *(const unsigned char *) ptr;
7440 format = flags & METHOD_HEADER_FORMAT_MASK;
7442 case METHOD_HEADER_TINY_FORMAT:
7443 local_var_sig_token = 0;
7445 case METHOD_HEADER_FAT_FORMAT:
7449 local_var_sig_token = read32 (ptr);
7452 g_assert_not_reached ();
7455 local_var_sig_token = 0; //FIXME
7457 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7458 mono_error_raise_exception (&error); /* FIXME don't raise here */
7460 ret->init_locals = header->init_locals;
7461 ret->max_stack = header->max_stack;
7462 ret->local_var_sig_token = local_var_sig_token;
7463 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7464 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7467 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7468 for (i = 0; i < header->num_locals; ++i) {
7469 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7470 mono_error_raise_exception (&error); /* FIXME don't raise here */
7472 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7473 mono_error_raise_exception (&error); /* FIXME don't raise here */
7475 MONO_OBJECT_SETREF (info, local_type, rt);
7477 info->is_pinned = header->locals [i]->pinned;
7478 info->local_index = i;
7479 mono_array_setref (ret->locals, i, info);
7483 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7484 for (i = 0; i < header->num_clauses; ++i) {
7485 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7486 mono_error_raise_exception (&error); /* FIXME don't raise here */
7487 MonoExceptionClause *clause = &header->clauses [i];
7489 info->flags = clause->flags;
7490 info->try_offset = clause->try_offset;
7491 info->try_length = clause->try_len;
7492 info->handler_offset = clause->handler_offset;
7493 info->handler_length = clause->handler_len;
7494 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7495 info->filter_offset = clause->data.filter_offset;
7496 else if (clause->data.catch_class) {
7497 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7498 mono_error_raise_exception (&error); /* FIXME don't raise here */
7500 MONO_OBJECT_SETREF (info, catch_type, rt);
7503 mono_array_setref (ret->clauses, i, info);
7506 mono_metadata_free_mh (header);
7507 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7512 * mono_get_dbnull_object:
7513 * @domain: Domain where the object lives
7515 * Returns the System.DBNull.Value singleton object
7517 * Used as the value for ParameterInfo.DefaultValue
7520 mono_get_dbnull_object (MonoDomain *domain)
7523 static MonoClassField *dbnull_value_field = NULL;
7525 if (!dbnull_value_field) {
7526 MonoClass *dbnull_klass;
7527 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7528 mono_class_init (dbnull_klass);
7529 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7530 g_assert (dbnull_value_field);
7532 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7538 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7540 guint32 param_index, i, lastp, crow = 0;
7541 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7544 MonoClass *klass = method->klass;
7545 MonoImage *image = klass->image;
7546 MonoMethodSignature *methodsig = mono_method_signature (method);
7548 MonoTableInfo *constt;
7549 MonoTableInfo *methodt;
7550 MonoTableInfo *paramt;
7552 if (!methodsig->param_count)
7555 mono_class_init (klass);
7557 if (image_is_dynamic (klass->image)) {
7558 MonoReflectionMethodAux *aux;
7559 if (method->is_inflated)
7560 method = ((MonoMethodInflated*)method)->declaring;
7561 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7562 if (aux && aux->param_defaults) {
7563 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7564 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7569 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7570 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7571 constt = &image->tables [MONO_TABLE_CONSTANT];
7573 idx = mono_method_get_index (method) - 1;
7574 g_assert (idx != -1);
7576 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7577 if (idx + 1 < methodt->rows)
7578 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7580 lastp = paramt->rows + 1;
7582 for (i = param_index; i < lastp; ++i) {
7585 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7586 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7588 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7591 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7596 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7597 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7598 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7605 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7611 MonoType *basetype = type;
7616 klass = mono_class_from_mono_type (type);
7617 if (klass->valuetype) {
7618 object = mono_object_new_checked (domain, klass, &error);
7619 mono_error_raise_exception (&error); /* FIXME don't raise here */
7620 retval = ((gchar *) object + sizeof (MonoObject));
7621 if (klass->enumtype)
7622 basetype = mono_class_enum_basetype (klass);
7627 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7634 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7637 gboolean quoted = FALSE;
7639 memset (assembly, 0, sizeof (MonoAssemblyName));
7640 assembly->culture = "";
7641 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7648 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7659 /* Remove trailing whitespace */
7661 while (*s && g_ascii_isspace (*s))
7664 while (g_ascii_isspace (*p))
7667 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7669 assembly->major = strtoul (p, &s, 10);
7670 if (s == p || *s != '.')
7673 assembly->minor = strtoul (p, &s, 10);
7674 if (s == p || *s != '.')
7677 assembly->build = strtoul (p, &s, 10);
7678 if (s == p || *s != '.')
7681 assembly->revision = strtoul (p, &s, 10);
7685 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7687 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7688 assembly->culture = "";
7691 assembly->culture = p;
7692 while (*p && *p != ',') {
7696 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7698 if (strncmp (p, "null", 4) == 0) {
7703 while (*p && *p != ',') {
7706 len = (p - start + 1);
7707 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7708 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7709 g_strlcpy ((char*)assembly->public_key_token, start, len);
7712 while (*p && *p != ',')
7716 while (g_ascii_isspace (*p) || *p == ',') {
7730 * mono_reflection_parse_type:
7733 * Parse a type name as accepted by the GetType () method and output the info
7734 * extracted in the info structure.
7735 * the name param will be mangled, so, make a copy before passing it to this function.
7736 * The fields in info will be valid until the memory pointed to by name is valid.
7738 * See also mono_type_get_name () below.
7740 * Returns: 0 on parse error.
7743 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7744 MonoTypeNameParse *info)
7746 char *start, *p, *w, *last_point, *startn;
7747 int in_modifiers = 0;
7748 int isbyref = 0, rank = 0, isptr = 0;
7750 start = p = w = name;
7752 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7753 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7754 info->name = info->name_space = NULL;
7755 info->nested = NULL;
7756 info->modifiers = NULL;
7757 info->type_arguments = NULL;
7759 /* last_point separates the namespace from the name */
7762 while (*p == ' ') p++, start++, w++, name++;
7767 *p = 0; /* NULL terminate the name */
7769 info->nested = g_list_append (info->nested, startn);
7770 /* we have parsed the nesting namespace + name */
7774 info->name_space = start;
7776 info->name = last_point + 1;
7778 info->name_space = (char *)"";
7806 info->name_space = start;
7808 info->name = last_point + 1;
7810 info->name_space = (char *)"";
7817 if (isbyref) /* only one level allowed by the spec */
7821 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7825 if (isbyref) /* pointer to ref not okay */
7827 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7832 if (isbyref) /* array of ref and generic ref are not okay */
7834 //Decide if it's an array of a generic argument list
7839 if (*p == ',' || *p == '*' || *p == ']') { //array
7847 else if (*p == '*') /* '*' means unknown lower bound */
7848 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7855 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7857 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7860 info->type_arguments = g_ptr_array_new ();
7862 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7863 gboolean fqname = FALSE;
7865 g_ptr_array_add (info->type_arguments, subinfo);
7867 while (*p == ' ') p++;
7873 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7876 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7877 if (fqname && (*p != ']')) {
7885 while (*p && (*p != ']'))
7893 if (g_ascii_isspace (*aname)) {
7900 !assembly_name_to_aname (&subinfo->assembly, aname))
7902 } else if (fqname && (*p == ']')) {
7924 if (g_ascii_isspace (*p)) {
7931 return 0; /* missing assembly name */
7932 if (!assembly_name_to_aname (&info->assembly, p))
7938 if (info->assembly.name)
7941 // *w = 0; /* terminate class name */
7943 if (!info->name || !*info->name)
7947 /* add other consistency checks */
7953 * mono_identifier_unescape_type_name_chars:
7954 * @identifier: the display name of a mono type
7957 * The name in internal form, that is without escaping backslashes.
7959 * The string is modified in place!
7962 mono_identifier_unescape_type_name_chars(char* identifier)
7967 for (w = r = identifier; *r != 0; r++)
7985 mono_identifier_unescape_info (MonoTypeNameParse* info);
7988 unescape_each_type_argument(void* data, void* user_data)
7990 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7991 mono_identifier_unescape_info (info);
7995 unescape_each_nested_name (void* data, void* user_data)
7997 char* nested_name = (char*) data;
7998 mono_identifier_unescape_type_name_chars(nested_name);
8002 * mono_identifier_unescape_info:
8004 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8008 * Destructively updates the info by unescaping the identifiers that
8009 * comprise the type namespace, name, nested types (if any) and
8010 * generic type arguments (if any).
8012 * The resulting info has the names in internal form.
8016 mono_identifier_unescape_info (MonoTypeNameParse *info)
8020 mono_identifier_unescape_type_name_chars(info->name_space);
8021 mono_identifier_unescape_type_name_chars(info->name);
8022 // but don't escape info->assembly
8023 if (info->type_arguments)
8024 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8026 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8030 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8032 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8034 mono_identifier_unescape_info (info);
8040 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8042 gboolean type_resolve = FALSE;
8044 MonoImage *rootimage = image;
8046 if (info->assembly.name) {
8047 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8048 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8050 * This could happen in the AOT compiler case when the search hook is not
8053 assembly = image->assembly;
8055 /* then we must load the assembly ourselve - see #60439 */
8056 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8060 image = assembly->image;
8061 } else if (!image) {
8062 image = mono_defaults.corlib;
8065 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8066 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8067 image = mono_defaults.corlib;
8068 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8075 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
8081 gboolean bounded = FALSE;
8084 image = mono_defaults.corlib;
8087 rootimage = mono_defaults.corlib;
8091 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
8092 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
8094 klass = mono_class_from_name (image, info->name_space, info->name);
8098 for (mod = info->nested; mod; mod = mod->next) {
8099 gpointer iter = NULL;
8103 mono_class_init (parent);
8105 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8107 char *nested_name, *nested_nspace;
8108 gboolean match = TRUE;
8110 lastp = strrchr ((const char *)mod->data, '.');
8112 /* Nested classes can have namespaces */
8115 nested_name = g_strdup (lastp + 1);
8116 nspace_len = lastp - (char*)mod->data;
8117 nested_nspace = (char *)g_malloc (nspace_len + 1);
8118 memcpy (nested_nspace, mod->data, nspace_len);
8119 nested_nspace [nspace_len] = '\0';
8122 nested_name = (char *)mod->data;
8123 nested_nspace = NULL;
8126 if (nested_nspace) {
8128 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8131 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8137 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8140 if (strcmp (klass->name, nested_name) != 0)
8145 g_free (nested_name);
8146 g_free (nested_nspace);
8158 if (info->type_arguments) {
8159 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8160 MonoReflectionType *the_type;
8164 for (i = 0; i < info->type_arguments->len; i++) {
8165 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8167 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8168 if (!type_args [i]) {
8174 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8175 mono_error_raise_exception (&error); /* FIXME don't raise here */
8177 instance = mono_reflection_bind_generic_parameters (
8178 the_type, info->type_arguments->len, type_args);
8184 klass = mono_class_from_mono_type (instance);
8187 for (mod = info->modifiers; mod; mod = mod->next) {
8188 modval = GPOINTER_TO_UINT (mod->data);
8189 if (!modval) { /* byref: must be last modifier */
8190 return &klass->this_arg;
8191 } else if (modval == -1) {
8192 klass = mono_ptr_class_get (&klass->byval_arg);
8193 } else if (modval == -2) {
8195 } else { /* array rank */
8196 klass = mono_bounded_array_class_get (klass, modval, bounded);
8200 return &klass->byval_arg;
8204 * mono_reflection_get_type:
8205 * @image: a metadata context
8206 * @info: type description structure
8207 * @ignorecase: flag for case-insensitive string compares
8208 * @type_resolve: whenever type resolve was already tried
8210 * Build a MonoType from the type description in @info.
8215 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8216 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8220 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8222 MonoReflectionAssemblyBuilder *abuilder;
8226 g_assert (assembly_is_dynamic (assembly));
8227 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8229 /* Enumerate all modules */
8232 if (abuilder->modules) {
8233 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8234 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8235 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8241 if (!type && abuilder->loaded_modules) {
8242 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8243 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8244 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8254 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8257 MonoReflectionAssembly *assembly;
8261 if (image && image_is_dynamic (image))
8262 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8264 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8267 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8274 *type_resolve = TRUE;
8277 /* Reconstruct the type name */
8278 fullName = g_string_new ("");
8279 if (info->name_space && (info->name_space [0] != '\0'))
8280 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8282 g_string_printf (fullName, "%s", info->name);
8283 for (mod = info->nested; mod; mod = mod->next)
8284 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8286 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8288 if (assembly_is_dynamic (assembly->assembly))
8289 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8291 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8294 g_string_free (fullName, TRUE);
8299 mono_reflection_free_type_info (MonoTypeNameParse *info)
8301 g_list_free (info->modifiers);
8302 g_list_free (info->nested);
8304 if (info->type_arguments) {
8307 for (i = 0; i < info->type_arguments->len; i++) {
8308 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8310 mono_reflection_free_type_info (subinfo);
8311 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8315 g_ptr_array_free (info->type_arguments, TRUE);
8320 * mono_reflection_type_from_name:
8322 * @image: a metadata context (can be NULL).
8324 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8325 * it defaults to get the type from @image or, if @image is NULL or loading
8326 * from it fails, uses corlib.
8330 mono_reflection_type_from_name (char *name, MonoImage *image)
8332 MonoType *type = NULL;
8333 MonoTypeNameParse info;
8336 /* Make a copy since parse_type modifies its argument */
8337 tmp = g_strdup (name);
8339 /*g_print ("requested type %s\n", str);*/
8340 if (mono_reflection_parse_type (tmp, &info)) {
8341 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8345 mono_reflection_free_type_info (&info);
8350 * mono_reflection_get_token:
8352 * Return the metadata token of OBJ which should be an object
8353 * representing a metadata element.
8356 mono_reflection_get_token (MonoObject *obj)
8361 klass = obj->vtable->klass;
8363 if (strcmp (klass->name, "MethodBuilder") == 0) {
8364 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8366 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8367 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8368 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8370 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8371 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8372 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8374 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8375 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8376 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8377 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8378 } else if (strcmp (klass->name, "MonoType") == 0) {
8379 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8380 MonoClass *mc = mono_class_from_mono_type (type);
8381 if (!mono_class_init (mc))
8382 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8384 token = mc->type_token;
8385 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8386 strcmp (klass->name, "MonoMethod") == 0 ||
8387 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8388 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8389 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8390 if (m->method->is_inflated) {
8391 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8392 return inflated->declaring->token;
8394 token = m->method->token;
8396 } else if (strcmp (klass->name, "MonoField") == 0) {
8397 MonoReflectionField *f = (MonoReflectionField*)obj;
8399 if (is_field_on_inst (f->field)) {
8400 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8402 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8403 int field_index = f->field - dgclass->fields;
8406 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8407 obj = dgclass->field_objects [field_index];
8408 return mono_reflection_get_token (obj);
8411 token = mono_class_get_field_token (f->field);
8412 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8413 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8415 token = mono_class_get_property_token (p->property);
8416 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8417 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8419 token = mono_class_get_event_token (p->event);
8420 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8421 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8422 MonoClass *member_class = mono_object_class (p->MemberImpl);
8423 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8425 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8426 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8427 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8430 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8431 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8433 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8434 MonoException *ex = mono_get_exception_not_implemented (msg);
8436 mono_raise_exception (ex);
8443 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8447 int slen = mono_metadata_decode_value (p, &p);
8449 mono_error_init (error);
8451 n = (char *)g_memdup (p, slen + 1);
8453 t = mono_reflection_type_from_name (n, image);
8455 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8456 /* We don't free n, it's consumed by mono_error */
8457 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8463 return mono_class_from_mono_type (t);
8467 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8469 int slen, type = t->type;
8470 MonoClass *tklass = t->data.klass;
8472 mono_error_init (error);
8478 case MONO_TYPE_BOOLEAN: {
8479 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8484 case MONO_TYPE_CHAR:
8486 case MONO_TYPE_I2: {
8487 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8492 #if SIZEOF_VOID_P == 4
8498 case MONO_TYPE_I4: {
8499 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8504 #if SIZEOF_VOID_P == 8
8505 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8509 case MONO_TYPE_I8: {
8510 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8515 case MONO_TYPE_R8: {
8516 double *val = (double *)g_malloc (sizeof (double));
8521 case MONO_TYPE_VALUETYPE:
8522 if (t->data.klass->enumtype) {
8523 type = mono_class_enum_basetype (t->data.klass)->type;
8526 MonoClass *k = t->data.klass;
8528 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8529 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8535 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8538 case MONO_TYPE_STRING:
8539 if (*p == (char)0xFF) {
8543 slen = mono_metadata_decode_value (p, &p);
8545 return mono_string_new_len (mono_domain_get (), p, slen);
8546 case MONO_TYPE_CLASS: {
8547 MonoReflectionType *rt;
8550 if (*p == (char)0xFF) {
8555 slen = mono_metadata_decode_value (p, &p);
8556 n = (char *)g_memdup (p, slen + 1);
8558 t = mono_reflection_type_from_name (n, image);
8560 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8561 /* We don't free n, it's consumed by mono_error */
8562 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8568 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8569 if (!mono_error_ok (error))
8574 case MONO_TYPE_OBJECT: {
8577 MonoClass *subc = NULL;
8582 } else if (subt == 0x0E) {
8583 type = MONO_TYPE_STRING;
8585 } else if (subt == 0x1D) {
8586 MonoType simple_type = {{0}};
8590 type = MONO_TYPE_SZARRAY;
8591 if (etype == 0x50) {
8592 tklass = mono_defaults.systemtype_class;
8593 } else if (etype == 0x55) {
8594 tklass = load_cattr_enum_type (image, p, &p, error);
8595 if (!mono_error_ok (error))
8599 /* See Partition II, Appendix B3 */
8600 etype = MONO_TYPE_OBJECT;
8601 simple_type.type = (MonoTypeEnum)etype;
8602 tklass = mono_class_from_mono_type (&simple_type);
8605 } else if (subt == 0x55) {
8608 slen = mono_metadata_decode_value (p, &p);
8609 n = (char *)g_memdup (p, slen + 1);
8611 t = mono_reflection_type_from_name (n, image);
8613 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8614 /* We don't free n, it's consumed by mono_error */
8615 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8620 subc = mono_class_from_mono_type (t);
8621 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8622 MonoType simple_type = {{0}};
8623 simple_type.type = (MonoTypeEnum)subt;
8624 subc = mono_class_from_mono_type (&simple_type);
8626 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8628 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8630 if (mono_error_ok (error)) {
8631 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8632 g_assert (!subc->has_references);
8633 if (mono_error_ok (error))
8634 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8640 case MONO_TYPE_SZARRAY: {
8642 guint32 i, alen, basetype;
8645 if (alen == 0xffffffff) {
8649 arr = mono_array_new (mono_domain_get(), tklass, alen);
8650 basetype = tklass->byval_arg.type;
8651 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8652 basetype = mono_class_enum_basetype (tklass)->type;
8657 case MONO_TYPE_BOOLEAN:
8658 for (i = 0; i < alen; i++) {
8659 MonoBoolean val = *p++;
8660 mono_array_set (arr, MonoBoolean, i, val);
8663 case MONO_TYPE_CHAR:
8666 for (i = 0; i < alen; i++) {
8667 guint16 val = read16 (p);
8668 mono_array_set (arr, guint16, i, val);
8675 for (i = 0; i < alen; i++) {
8676 guint32 val = read32 (p);
8677 mono_array_set (arr, guint32, i, val);
8682 for (i = 0; i < alen; i++) {
8685 mono_array_set (arr, double, i, val);
8691 for (i = 0; i < alen; i++) {
8692 guint64 val = read64 (p);
8693 mono_array_set (arr, guint64, i, val);
8697 case MONO_TYPE_CLASS:
8698 case MONO_TYPE_OBJECT:
8699 case MONO_TYPE_STRING:
8700 case MONO_TYPE_SZARRAY:
8701 for (i = 0; i < alen; i++) {
8702 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8703 if (!mono_error_ok (error))
8705 mono_array_setref (arr, i, item);
8709 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8715 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8721 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8723 static MonoClass *klass;
8724 static MonoMethod *ctor;
8727 void *params [2], *unboxed;
8730 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8732 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8734 params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8735 mono_error_raise_exception (&error); /* FIXME don't raise here */
8738 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8739 mono_error_raise_exception (&error); /* FIXME don't raise here */
8740 unboxed = mono_object_unbox (retval);
8741 mono_runtime_invoke (ctor, unboxed, params, NULL);
8747 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8749 static MonoClass *klass;
8750 static MonoMethod *ctor;
8753 void *unboxed, *params [2];
8756 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8758 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8761 params [1] = typedarg;
8762 retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8763 mono_error_raise_exception (&error); /* FIXME don't raise here */
8764 unboxed = mono_object_unbox (retval);
8765 mono_runtime_invoke (ctor, unboxed, params, NULL);
8771 type_is_reference (MonoType *type)
8773 switch (type->type) {
8774 case MONO_TYPE_BOOLEAN:
8775 case MONO_TYPE_CHAR:
8788 case MONO_TYPE_VALUETYPE:
8796 free_param_data (MonoMethodSignature *sig, void **params) {
8798 for (i = 0; i < sig->param_count; ++i) {
8799 if (!type_is_reference (sig->params [i]))
8800 g_free (params [i]);
8805 * Find the field index in the metadata FieldDef table.
8808 find_field_index (MonoClass *klass, MonoClassField *field) {
8811 for (i = 0; i < klass->field.count; ++i) {
8812 if (field == &klass->fields [i])
8813 return klass->field.first + 1 + i;
8819 * Find the property index in the metadata Property table.
8822 find_property_index (MonoClass *klass, MonoProperty *property) {
8825 for (i = 0; i < klass->ext->property.count; ++i) {
8826 if (property == &klass->ext->properties [i])
8827 return klass->ext->property.first + 1 + i;
8833 * Find the event index in the metadata Event table.
8836 find_event_index (MonoClass *klass, MonoEvent *event) {
8839 for (i = 0; i < klass->ext->event.count; ++i) {
8840 if (event == &klass->ext->events [i])
8841 return klass->ext->event.first + 1 + i;
8847 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8849 const char *p = (const char*)data;
8851 guint32 i, j, num_named;
8853 void *params_buf [32];
8854 void **params = NULL;
8855 MonoMethodSignature *sig;
8856 MonoObject *exc = NULL;
8858 mono_error_init (error);
8860 mono_class_init (method->klass);
8862 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8863 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8868 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8869 if (!mono_error_ok (error)) return NULL;
8870 mono_runtime_invoke (method, attr, NULL, NULL);
8874 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8877 /*g_print ("got attr %s\n", method->klass->name);*/
8879 sig = mono_method_signature (method);
8880 if (sig->param_count < 32) {
8881 params = params_buf;
8882 memset (params, 0, sizeof (void*) * sig->param_count);
8884 /* Allocate using GC so it gets GC tracking */
8885 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8890 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8891 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8892 if (!mono_error_ok (error))
8897 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8898 if (!mono_error_ok (error)) goto fail;
8900 mono_runtime_invoke (method, attr, params, &exc);
8903 num_named = read16 (named);
8905 for (j = 0; j < num_named; j++) {
8907 char *name, named_type, data_type;
8908 named_type = *named++;
8909 data_type = *named++; /* type of data */
8910 if (data_type == MONO_TYPE_SZARRAY)
8911 data_type = *named++;
8912 if (data_type == MONO_TYPE_ENUM) {
8915 type_len = mono_metadata_decode_blob_size (named, &named);
8916 type_name = (char *)g_malloc (type_len + 1);
8917 memcpy (type_name, named, type_len);
8918 type_name [type_len] = 0;
8920 /* FIXME: lookup the type and check type consistency */
8923 name_len = mono_metadata_decode_blob_size (named, &named);
8924 name = (char *)g_malloc (name_len + 1);
8925 memcpy (name, named, name_len);
8926 name [name_len] = 0;
8928 if (named_type == 0x53) {
8929 MonoClassField *field;
8932 /* how this fail is a blackbox */
8933 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8935 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8940 val = load_cattr_value (image, field->type, named, &named, error);
8941 if (!mono_error_ok (error)) {
8943 if (!type_is_reference (field->type))
8948 mono_field_set_value (attr, field, val);
8949 if (!type_is_reference (field->type))
8951 } else if (named_type == 0x54) {
8954 MonoType *prop_type;
8956 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8959 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8965 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8970 /* can we have more that 1 arg in a custom attr named property? */
8971 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8972 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8974 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8975 if (!mono_error_ok (error)) {
8977 if (!type_is_reference (prop_type))
8978 g_free (pparams [0]);
8983 mono_property_set_value (prop, attr, pparams, NULL);
8984 if (!type_is_reference (prop_type))
8985 g_free (pparams [0]);
8990 free_param_data (method->signature, params);
8991 if (params != params_buf)
8992 mono_gc_free_fixed (params);
8997 free_param_data (method->signature, params);
8998 if (params != params_buf)
8999 mono_gc_free_fixed (params);
9001 mono_raise_exception ((MonoException*)exc);
9006 * mono_reflection_create_custom_attr_data_args:
9008 * Create an array of typed and named arguments from the cattr blob given by DATA.
9009 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9010 * NAMED_ARG_INFO will contain information about the named arguments.
9013 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)
9015 MonoArray *typedargs, *namedargs;
9016 MonoClass *attrklass;
9018 const char *p = (const char*)data;
9020 guint32 i, j, num_named;
9021 CattrNamedArg *arginfo = NULL;
9025 *named_arg_info = NULL;
9027 mono_error_init (error);
9029 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9030 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9034 mono_class_init (method->klass);
9036 domain = mono_domain_get ();
9038 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9041 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9045 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9049 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9050 if (!mono_error_ok (error)) {
9051 if (!type_is_reference (mono_method_signature (method)->params [i]))
9056 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9057 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9058 mono_array_setref (typedargs, i, obj);
9060 if (!type_is_reference (mono_method_signature (method)->params [i]))
9065 num_named = read16 (named);
9066 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9068 attrklass = method->klass;
9070 arginfo = g_new0 (CattrNamedArg, num_named);
9071 *named_arg_info = arginfo;
9073 for (j = 0; j < num_named; j++) {
9075 char *name, named_type, data_type;
9076 named_type = *named++;
9077 data_type = *named++; /* type of data */
9078 if (data_type == MONO_TYPE_SZARRAY)
9079 data_type = *named++;
9080 if (data_type == MONO_TYPE_ENUM) {
9083 type_len = mono_metadata_decode_blob_size (named, &named);
9084 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9087 type_name = (char *)g_malloc (type_len + 1);
9088 memcpy (type_name, named, type_len);
9089 type_name [type_len] = 0;
9091 /* FIXME: lookup the type and check type consistency */
9094 name_len = mono_metadata_decode_blob_size (named, &named);
9095 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9097 name = (char *)g_malloc (name_len + 1);
9098 memcpy (name, named, name_len);
9099 name [name_len] = 0;
9101 if (named_type == 0x53) {
9103 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9111 arginfo [j].type = field->type;
9112 arginfo [j].field = field;
9114 val = load_cattr_value (image, field->type, named, &named, error);
9115 if (!mono_error_ok (error)) {
9116 if (!type_is_reference (field->type))
9122 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9123 mono_array_setref (namedargs, j, obj);
9124 if (!type_is_reference (field->type))
9126 } else if (named_type == 0x54) {
9128 MonoType *prop_type;
9129 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9132 if (!prop || !prop->set) {
9137 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9138 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9140 arginfo [j].type = prop_type;
9141 arginfo [j].prop = prop;
9143 val = load_cattr_value (image, prop_type, named, &named, error);
9144 if (!mono_error_ok (error)) {
9145 if (!type_is_reference (prop_type))
9151 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9152 mono_array_setref (namedargs, j, obj);
9153 if (!type_is_reference (prop_type))
9159 *typed_args = typedargs;
9160 *named_args = namedargs;
9163 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9165 *named_arg_info = NULL;
9169 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9172 MonoArray *typedargs, *namedargs;
9175 CattrNamedArg *arginfo = NULL;
9179 mono_error_init (&error);
9187 image = assembly->assembly->image;
9188 method = ref_method->method;
9189 domain = mono_object_domain (ref_method);
9191 if (!mono_class_init (method->klass))
9192 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9194 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9195 if (!mono_error_ok (&error))
9198 if (mono_loader_get_last_error ()) {
9199 mono_error_set_from_loader_error (&error);
9203 if (!typedargs || !namedargs)
9206 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9207 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9208 MonoObject *typedarg;
9210 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9211 mono_array_setref (typedargs, i, typedarg);
9214 for (i = 0; i < mono_array_length (namedargs); ++i) {
9215 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9216 MonoObject *typedarg, *namedarg, *minfo;
9218 if (arginfo [i].prop)
9219 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9221 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9222 if (!mono_error_ok (&error))
9226 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9227 namedarg = create_cattr_named_arg (minfo, typedarg);
9229 mono_array_setref (namedargs, i, namedarg);
9232 *ctor_args = typedargs;
9233 *named_args = namedargs;
9236 mono_error_raise_exception (&error);
9241 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9243 static MonoMethod *ctor;
9250 g_assert (image->assembly);
9253 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9255 domain = mono_domain_get ();
9256 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9257 mono_error_raise_exception (&error); /* FIXME don't raise here */
9258 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9259 mono_error_raise_exception (&error); /* FIXME don't raise here */
9260 params [1] = mono_assembly_get_object (domain, image->assembly);
9261 params [2] = (gpointer)&cattr->data;
9262 params [3] = &cattr->data_size;
9263 mono_runtime_invoke (ctor, attr, params, NULL);
9268 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9274 mono_error_init (error);
9277 for (i = 0; i < cinfo->num_attrs; ++i) {
9278 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9282 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9284 for (i = 0; i < cinfo->num_attrs; ++i) {
9285 if (!cinfo->attrs [i].ctor)
9286 /* The cattr type is not finished yet */
9287 /* We should include the type name but cinfo doesn't contain it */
9288 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9289 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9290 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9291 if (!mono_error_ok (error))
9293 mono_array_setref (result, n, attr);
9301 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9304 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9305 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9311 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9317 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9318 for (i = 0; i < cinfo->num_attrs; ++i) {
9319 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9320 mono_array_setref (result, i, attr);
9326 * mono_custom_attrs_from_index:
9328 * Returns: NULL if no attributes are found or if a loading error occurs.
9331 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9333 guint32 mtoken, i, len;
9334 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9336 MonoCustomAttrInfo *ainfo;
9337 GList *tmp, *list = NULL;
9339 MonoCustomAttrEntry* attr;
9341 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9343 i = mono_metadata_custom_attrs_from_index (image, idx);
9347 while (i < ca->rows) {
9348 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9350 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9353 len = g_list_length (list);
9356 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9357 ainfo->num_attrs = len;
9358 ainfo->image = image;
9359 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9361 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9362 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9363 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9364 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9365 mtoken |= MONO_TOKEN_METHOD_DEF;
9367 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9368 mtoken |= MONO_TOKEN_MEMBER_REF;
9371 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9374 attr = &ainfo->attrs [i - 1];
9375 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9377 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9378 mono_loader_set_error_from_mono_error (&error);
9384 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9385 /*FIXME raising an exception here doesn't make any sense*/
9386 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9391 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9392 attr->data_size = mono_metadata_decode_value (data, &data);
9393 attr->data = (guchar*)data;
9401 mono_custom_attrs_from_method (MonoMethod *method)
9406 * An instantiated method has the same cattrs as the generic method definition.
9408 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9409 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9411 if (method->is_inflated)
9412 method = ((MonoMethodInflated *) method)->declaring;
9414 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9415 return lookup_custom_attr (method->klass->image, method);
9418 /* Synthetic methods */
9421 idx = mono_method_get_index (method);
9422 idx <<= MONO_CUSTOM_ATTR_BITS;
9423 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9424 return mono_custom_attrs_from_index (method->klass->image, idx);
9428 mono_custom_attrs_from_class (MonoClass *klass)
9432 if (klass->generic_class)
9433 klass = klass->generic_class->container_class;
9435 if (image_is_dynamic (klass->image))
9436 return lookup_custom_attr (klass->image, klass);
9438 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9439 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9440 idx <<= MONO_CUSTOM_ATTR_BITS;
9441 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9443 idx = mono_metadata_token_index (klass->type_token);
9444 idx <<= MONO_CUSTOM_ATTR_BITS;
9445 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9447 return mono_custom_attrs_from_index (klass->image, idx);
9451 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9455 if (image_is_dynamic (assembly->image))
9456 return lookup_custom_attr (assembly->image, assembly);
9457 idx = 1; /* there is only one assembly */
9458 idx <<= MONO_CUSTOM_ATTR_BITS;
9459 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9460 return mono_custom_attrs_from_index (assembly->image, idx);
9463 static MonoCustomAttrInfo*
9464 mono_custom_attrs_from_module (MonoImage *image)
9468 if (image_is_dynamic (image))
9469 return lookup_custom_attr (image, image);
9470 idx = 1; /* there is only one module */
9471 idx <<= MONO_CUSTOM_ATTR_BITS;
9472 idx |= MONO_CUSTOM_ATTR_MODULE;
9473 return mono_custom_attrs_from_index (image, idx);
9477 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9481 if (image_is_dynamic (klass->image)) {
9482 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9483 return lookup_custom_attr (klass->image, property);
9485 idx = find_property_index (klass, property);
9486 idx <<= MONO_CUSTOM_ATTR_BITS;
9487 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9488 return mono_custom_attrs_from_index (klass->image, idx);
9492 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9496 if (image_is_dynamic (klass->image)) {
9497 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9498 return lookup_custom_attr (klass->image, event);
9500 idx = find_event_index (klass, event);
9501 idx <<= MONO_CUSTOM_ATTR_BITS;
9502 idx |= MONO_CUSTOM_ATTR_EVENT;
9503 return mono_custom_attrs_from_index (klass->image, idx);
9507 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9510 if (image_is_dynamic (klass->image)) {
9511 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9512 return lookup_custom_attr (klass->image, field);
9514 idx = find_field_index (klass, field);
9515 idx <<= MONO_CUSTOM_ATTR_BITS;
9516 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9517 return mono_custom_attrs_from_index (klass->image, idx);
9521 * mono_custom_attrs_from_param:
9522 * @method: handle to the method that we want to retrieve custom parameter information from
9523 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9525 * The result must be released with mono_custom_attrs_free().
9527 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9530 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9533 guint32 i, idx, method_index;
9534 guint32 param_list, param_last, param_pos, found;
9536 MonoReflectionMethodAux *aux;
9539 * An instantiated method has the same cattrs as the generic method definition.
9541 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9542 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9544 if (method->is_inflated)
9545 method = ((MonoMethodInflated *) method)->declaring;
9547 if (image_is_dynamic (method->klass->image)) {
9548 MonoCustomAttrInfo *res, *ainfo;
9551 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9552 if (!aux || !aux->param_cattr)
9555 /* Need to copy since it will be freed later */
9556 ainfo = aux->param_cattr [param];
9559 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9560 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9561 memcpy (res, ainfo, size);
9565 image = method->klass->image;
9566 method_index = mono_method_get_index (method);
9569 ca = &image->tables [MONO_TABLE_METHOD];
9571 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9572 if (method_index == ca->rows) {
9573 ca = &image->tables [MONO_TABLE_PARAM];
9574 param_last = ca->rows + 1;
9576 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9577 ca = &image->tables [MONO_TABLE_PARAM];
9580 for (i = param_list; i < param_last; ++i) {
9581 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9582 if (param_pos == param) {
9590 idx <<= MONO_CUSTOM_ATTR_BITS;
9591 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9592 return mono_custom_attrs_from_index (image, idx);
9596 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9600 for (i = 0; i < ainfo->num_attrs; ++i) {
9601 klass = ainfo->attrs [i].ctor->klass;
9602 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9609 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9612 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9613 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9618 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9624 mono_error_init (error);
9627 for (i = 0; i < ainfo->num_attrs; ++i) {
9628 klass = ainfo->attrs [i].ctor->klass;
9629 if (mono_class_has_parent (klass, attr_klass)) {
9634 if (attr_index == -1)
9637 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9638 if (!mono_error_ok (error))
9640 return mono_array_get (attrs, MonoObject*, attr_index);
9644 * mono_reflection_get_custom_attrs_info:
9645 * @obj: a reflection object handle
9647 * Return the custom attribute info for attributes defined for the
9648 * reflection handle @obj. The objects.
9650 * FIXME this function leaks like a sieve for SRE objects.
9653 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9656 MonoCustomAttrInfo *cinfo = NULL;
9658 klass = obj->vtable->klass;
9659 if (klass == mono_defaults.monotype_class) {
9660 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9661 klass = mono_class_from_mono_type (type);
9662 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9663 cinfo = mono_custom_attrs_from_class (klass);
9664 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9665 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9666 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9667 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9668 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9669 cinfo = mono_custom_attrs_from_module (module->image);
9670 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9671 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9672 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9673 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9674 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9675 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9676 } else if (strcmp ("MonoField", klass->name) == 0) {
9677 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9678 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9679 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9680 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9681 cinfo = mono_custom_attrs_from_method (rmethod->method);
9682 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9683 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9684 cinfo = mono_custom_attrs_from_method (rmethod->method);
9685 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9686 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9687 MonoClass *member_class = mono_object_class (param->MemberImpl);
9688 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9689 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9690 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9691 } else if (is_sr_mono_property (member_class)) {
9692 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9694 if (!(method = prop->property->get))
9695 method = prop->property->set;
9698 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9700 #ifndef DISABLE_REFLECTION_EMIT
9701 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9702 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9703 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9704 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9705 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9706 MonoMethod *method = NULL;
9707 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9708 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9709 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9710 method = ((MonoReflectionMethod *)c->cb)->method;
9712 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));
9714 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9718 char *type_name = mono_type_get_full_name (member_class);
9719 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9720 MonoException *ex = mono_get_exception_not_supported (msg);
9723 mono_raise_exception (ex);
9725 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9726 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9727 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9728 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9729 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9730 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9731 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9732 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9733 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9734 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9735 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9736 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9737 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9738 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9739 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9740 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9741 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9742 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9743 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9744 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9745 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9746 } else { /* handle other types here... */
9747 g_error ("get custom attrs not yet supported for %s", klass->name);
9754 * mono_reflection_get_custom_attrs_by_type:
9755 * @obj: a reflection object handle
9757 * Return an array with all the custom attributes defined of the
9758 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9759 * of that type are returned. The objects are fully build. Return NULL if a loading error
9763 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9766 MonoCustomAttrInfo *cinfo;
9768 mono_error_init (error);
9770 cinfo = mono_reflection_get_custom_attrs_info (obj);
9772 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9774 mono_custom_attrs_free (cinfo);
9776 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9777 if (mono_loader_get_last_error ())
9779 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9786 * mono_reflection_get_custom_attrs:
9787 * @obj: a reflection object handle
9789 * Return an array with all the custom attributes defined of the
9790 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9794 mono_reflection_get_custom_attrs (MonoObject *obj)
9798 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9802 * mono_reflection_get_custom_attrs_data:
9803 * @obj: a reflection obj handle
9805 * Returns an array of System.Reflection.CustomAttributeData,
9806 * which include information about attributes reflected on
9807 * types loaded using the Reflection Only methods
9810 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9813 MonoCustomAttrInfo *cinfo;
9815 cinfo = mono_reflection_get_custom_attrs_info (obj);
9817 result = mono_custom_attrs_data_construct (cinfo);
9819 mono_custom_attrs_free (cinfo);
9821 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9826 static MonoReflectionType*
9827 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9829 static MonoMethod *method_get_underlying_system_type = NULL;
9830 MonoMethod *usertype_method;
9832 if (!method_get_underlying_system_type)
9833 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9834 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9835 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9840 is_corlib_type (MonoClass *klass)
9842 return klass->image == mono_defaults.corlib;
9845 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9846 static MonoClass *cached_class; \
9848 return cached_class == _class; \
9849 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9850 cached_class = _class; \
9857 #ifndef DISABLE_REFLECTION_EMIT
9859 is_sre_array (MonoClass *klass)
9861 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9865 is_sre_byref (MonoClass *klass)
9867 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9871 is_sre_pointer (MonoClass *klass)
9873 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9877 is_sre_generic_instance (MonoClass *klass)
9879 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9883 is_sre_type_builder (MonoClass *klass)
9885 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9889 is_sre_method_builder (MonoClass *klass)
9891 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9895 is_sre_ctor_builder (MonoClass *klass)
9897 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9901 is_sre_field_builder (MonoClass *klass)
9903 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9907 is_sre_method_on_tb_inst (MonoClass *klass)
9909 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9913 is_sre_ctor_on_tb_inst (MonoClass *klass)
9915 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9919 mono_reflection_type_get_handle (MonoReflectionType* ref)
9927 if (is_usertype (ref)) {
9928 ref = mono_reflection_type_get_underlying_system_type (ref);
9929 if (ref == NULL || is_usertype (ref))
9935 klass = mono_object_class (ref);
9937 if (is_sre_array (klass)) {
9939 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9940 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9942 if (sre_array->rank == 0) //single dimentional array
9943 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9945 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9946 sre_array->type.type = res;
9948 } else if (is_sre_byref (klass)) {
9950 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9951 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9953 res = &mono_class_from_mono_type (base)->this_arg;
9954 sre_byref->type.type = res;
9956 } else if (is_sre_pointer (klass)) {
9958 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9959 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9961 res = &mono_ptr_class_get (base)->byval_arg;
9962 sre_pointer->type.type = res;
9964 } else if (is_sre_generic_instance (klass)) {
9965 MonoType *res, **types;
9966 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9969 count = mono_array_length (gclass->type_arguments);
9970 types = g_new0 (MonoType*, count);
9971 for (i = 0; i < count; ++i) {
9972 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9973 types [i] = mono_reflection_type_get_handle (t);
9980 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9983 gclass->type.type = res;
9987 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9994 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9996 mono_reflection_type_get_handle (type);
10000 mono_reflection_register_with_runtime (MonoReflectionType *type)
10002 MonoType *res = mono_reflection_type_get_handle (type);
10003 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10007 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10009 klass = mono_class_from_mono_type (res);
10011 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10012 mono_domain_lock (domain);
10014 if (!image_is_dynamic (klass->image)) {
10015 mono_class_setup_supertypes (klass);
10017 if (!domain->type_hash)
10018 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10019 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10020 mono_g_hash_table_insert (domain->type_hash, res, type);
10022 mono_domain_unlock (domain);
10023 mono_loader_unlock ();
10027 * LOCKING: Assumes the loader lock is held.
10029 static MonoMethodSignature*
10030 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10031 MonoMethodSignature *sig;
10034 count = parameters? mono_array_length (parameters): 0;
10036 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10037 sig->param_count = count;
10038 sig->sentinelpos = -1; /* FIXME */
10039 for (i = 0; i < count; ++i)
10040 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10045 * LOCKING: Assumes the loader lock is held.
10047 static MonoMethodSignature*
10048 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10049 MonoMethodSignature *sig;
10051 sig = parameters_to_signature (image, ctor->parameters);
10052 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10053 sig->ret = &mono_defaults.void_class->byval_arg;
10058 * LOCKING: Assumes the loader lock is held.
10060 static MonoMethodSignature*
10061 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10062 MonoMethodSignature *sig;
10064 sig = parameters_to_signature (image, method->parameters);
10065 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10066 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10067 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10071 static MonoMethodSignature*
10072 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10073 MonoMethodSignature *sig;
10075 sig = parameters_to_signature (NULL, method->parameters);
10076 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10077 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10078 sig->generic_param_count = 0;
10083 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10085 MonoClass *klass = mono_object_class (prop);
10086 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10087 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10088 *name = mono_string_to_utf8 (pb->name);
10089 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10091 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10092 *name = g_strdup (p->property->name);
10093 if (p->property->get)
10094 *type = mono_method_signature (p->property->get)->ret;
10096 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10101 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10103 MonoClass *klass = mono_object_class (field);
10104 if (strcmp (klass->name, "FieldBuilder") == 0) {
10105 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10106 *name = mono_string_to_utf8 (fb->name);
10107 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10109 MonoReflectionField *f = (MonoReflectionField *)field;
10110 *name = g_strdup (mono_field_get_name (f->field));
10111 *type = f->field->type;
10115 #else /* DISABLE_REFLECTION_EMIT */
10118 mono_reflection_register_with_runtime (MonoReflectionType *type)
10120 /* This is empty */
10124 is_sre_type_builder (MonoClass *klass)
10130 is_sre_generic_instance (MonoClass *klass)
10136 init_type_builder_generics (MonoObject *type)
10140 #endif /* !DISABLE_REFLECTION_EMIT */
10144 is_sr_mono_field (MonoClass *klass)
10146 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10150 is_sr_mono_property (MonoClass *klass)
10152 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10156 is_sr_mono_method (MonoClass *klass)
10158 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10162 is_sr_mono_cmethod (MonoClass *klass)
10164 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10168 is_sr_mono_generic_method (MonoClass *klass)
10170 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10174 is_sr_mono_generic_cmethod (MonoClass *klass)
10176 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10180 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10182 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10186 is_usertype (MonoReflectionType *ref)
10188 MonoClass *klass = mono_object_class (ref);
10189 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10192 static MonoReflectionType*
10193 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10195 mono_error_init (error);
10196 if (!type || type->type)
10199 if (is_usertype (type)) {
10200 type = mono_reflection_type_get_underlying_system_type (type);
10201 if (is_usertype (type)) {
10202 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10210 * Encode a value in a custom attribute stream of bytes.
10211 * The value to encode is either supplied as an object in argument val
10212 * (valuetypes are boxed), or as a pointer to the data in the
10214 * @type represents the type of the value
10215 * @buffer is the start of the buffer
10216 * @p the current position in the buffer
10217 * @buflen contains the size of the buffer and is used to return the new buffer size
10218 * if this needs to be realloced.
10219 * @retbuffer and @retp return the start and the position of the buffer
10222 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10224 MonoTypeEnum simple_type;
10226 if ((p-buffer) + 10 >= *buflen) {
10229 newbuf = (char *)g_realloc (buffer, *buflen);
10230 p = newbuf + (p-buffer);
10234 argval = ((char*)arg + sizeof (MonoObject));
10235 simple_type = type->type;
10237 switch (simple_type) {
10238 case MONO_TYPE_BOOLEAN:
10243 case MONO_TYPE_CHAR:
10246 swap_with_size (p, argval, 2, 1);
10252 swap_with_size (p, argval, 4, 1);
10256 swap_with_size (p, argval, 8, 1);
10261 swap_with_size (p, argval, 8, 1);
10264 case MONO_TYPE_VALUETYPE:
10265 if (type->data.klass->enumtype) {
10266 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10269 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10272 case MONO_TYPE_STRING: {
10279 str = mono_string_to_utf8 ((MonoString*)arg);
10280 slen = strlen (str);
10281 if ((p-buffer) + 10 + slen >= *buflen) {
10285 newbuf = (char *)g_realloc (buffer, *buflen);
10286 p = newbuf + (p-buffer);
10289 mono_metadata_encode_value (slen, p, &p);
10290 memcpy (p, str, slen);
10295 case MONO_TYPE_CLASS: {
10303 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10304 slen = strlen (str);
10305 if ((p-buffer) + 10 + slen >= *buflen) {
10309 newbuf = (char *)g_realloc (buffer, *buflen);
10310 p = newbuf + (p-buffer);
10313 mono_metadata_encode_value (slen, p, &p);
10314 memcpy (p, str, slen);
10319 case MONO_TYPE_SZARRAY: {
10321 MonoClass *eclass, *arg_eclass;
10324 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10327 len = mono_array_length ((MonoArray*)arg);
10329 *p++ = (len >> 8) & 0xff;
10330 *p++ = (len >> 16) & 0xff;
10331 *p++ = (len >> 24) & 0xff;
10333 *retbuffer = buffer;
10334 eclass = type->data.klass;
10335 arg_eclass = mono_object_class (arg)->element_class;
10338 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10339 eclass = mono_defaults.object_class;
10341 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10342 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10343 int elsize = mono_class_array_element_size (arg_eclass);
10344 for (i = 0; i < len; ++i) {
10345 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10348 } else if (eclass->valuetype && arg_eclass->valuetype) {
10349 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10350 int elsize = mono_class_array_element_size (eclass);
10351 for (i = 0; i < len; ++i) {
10352 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10356 for (i = 0; i < len; ++i) {
10357 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10362 case MONO_TYPE_OBJECT: {
10368 * The parameter type is 'object' but the type of the actual
10369 * argument is not. So we have to add type information to the blob
10370 * too. This is completely undocumented in the spec.
10374 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10379 klass = mono_object_class (arg);
10381 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10384 } else if (klass->enumtype) {
10386 } else if (klass == mono_defaults.string_class) {
10387 simple_type = MONO_TYPE_STRING;
10390 } else if (klass->rank == 1) {
10392 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10393 /* See Partition II, Appendix B3 */
10396 *p++ = klass->element_class->byval_arg.type;
10397 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10399 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10400 *p++ = simple_type = klass->byval_arg.type;
10403 g_error ("unhandled type in custom attr");
10405 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10406 slen = strlen (str);
10407 if ((p-buffer) + 10 + slen >= *buflen) {
10411 newbuf = (char *)g_realloc (buffer, *buflen);
10412 p = newbuf + (p-buffer);
10415 mono_metadata_encode_value (slen, p, &p);
10416 memcpy (p, str, slen);
10419 simple_type = mono_class_enum_basetype (klass)->type;
10423 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10426 *retbuffer = buffer;
10430 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10432 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10433 char *str = type_get_qualified_name (type, NULL);
10434 int slen = strlen (str);
10438 * This seems to be optional...
10441 mono_metadata_encode_value (slen, p, &p);
10442 memcpy (p, str, slen);
10445 } else if (type->type == MONO_TYPE_OBJECT) {
10447 } else if (type->type == MONO_TYPE_CLASS) {
10448 /* it should be a type: encode_cattr_value () has the check */
10451 mono_metadata_encode_value (type->type, p, &p);
10452 if (type->type == MONO_TYPE_SZARRAY)
10453 /* See the examples in Partition VI, Annex B */
10454 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10460 #ifndef DISABLE_REFLECTION_EMIT
10462 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10465 /* Preallocate a large enough buffer */
10466 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10467 char *str = type_get_qualified_name (type, NULL);
10468 len = strlen (str);
10470 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10471 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10472 len = strlen (str);
10477 len += strlen (name);
10479 if ((p-buffer) + 20 + len >= *buflen) {
10483 newbuf = (char *)g_realloc (buffer, *buflen);
10484 p = newbuf + (p-buffer);
10488 encode_field_or_prop_type (type, p, &p);
10490 len = strlen (name);
10491 mono_metadata_encode_value (len, p, &p);
10492 memcpy (p, name, len);
10494 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10496 *retbuffer = buffer;
10500 * mono_reflection_get_custom_attrs_blob:
10501 * @ctor: custom attribute constructor
10502 * @ctorArgs: arguments o the constructor
10508 * Creates the blob of data that needs to be saved in the metadata and that represents
10509 * the custom attributed described by @ctor, @ctorArgs etc.
10510 * Returns: a Byte array representing the blob of data.
10513 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10516 MonoMethodSignature *sig;
10521 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10522 /* sig is freed later so allocate it in the heap */
10523 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10525 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10528 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10530 p = buffer = (char *)g_malloc (buflen);
10531 /* write the prolog */
10534 for (i = 0; i < sig->param_count; ++i) {
10535 arg = mono_array_get (ctorArgs, MonoObject*, i);
10536 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10540 i += mono_array_length (properties);
10542 i += mono_array_length (fields);
10544 *p++ = (i >> 8) & 0xff;
10547 for (i = 0; i < mono_array_length (properties); ++i) {
10551 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10552 get_prop_name_and_type (prop, &pname, &ptype);
10553 *p++ = 0x54; /* PROPERTY signature */
10554 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10561 for (i = 0; i < mono_array_length (fields); ++i) {
10565 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10566 get_field_name_and_type (field, &fname, &ftype);
10567 *p++ = 0x53; /* FIELD signature */
10568 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10573 g_assert (p - buffer <= buflen);
10574 buflen = p - buffer;
10575 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10576 p = mono_array_addr (result, char, 0);
10577 memcpy (p, buffer, buflen);
10579 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10585 * mono_reflection_setup_internal_class:
10586 * @tb: a TypeBuilder object
10588 * Creates a MonoClass that represents the TypeBuilder.
10589 * This is a trick that lets us simplify a lot of reflection code
10590 * (and will allow us to support Build and Run assemblies easier).
10593 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10596 MonoClass *klass, *parent;
10598 RESOLVE_TYPE (tb->parent, &error);
10599 mono_error_raise_exception (&error); /* FIXME don't raise here */
10601 mono_loader_lock ();
10604 /* check so we can compile corlib correctly */
10605 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10606 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10607 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10609 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10615 /* the type has already being created: it means we just have to change the parent */
10616 if (tb->type.type) {
10617 klass = mono_class_from_mono_type (tb->type.type);
10618 klass->parent = NULL;
10619 /* fool mono_class_setup_parent */
10620 klass->supertypes = NULL;
10621 mono_class_setup_parent (klass, parent);
10622 mono_class_setup_mono_type (klass);
10623 mono_loader_unlock ();
10627 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10629 klass->image = &tb->module->dynamic_image->image;
10631 klass->inited = 1; /* we lie to the runtime */
10632 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10633 if (!mono_error_ok (&error))
10635 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10636 if (!mono_error_ok (&error))
10638 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10639 klass->flags = tb->attrs;
10641 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10643 klass->element_class = klass;
10645 if (mono_class_get_ref_info (klass) == NULL) {
10647 mono_class_set_ref_info (klass, tb);
10649 /* Put into cache so mono_class_get_checked () will find it.
10650 Skip nested types as those should not be available on the global scope. */
10651 if (!tb->nesting_type)
10652 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10655 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10656 by performing a mono_class_get which does the full resolution.
10658 Working around this semantics would require us to write a lot of code for no clear advantage.
10660 mono_image_append_class_to_reflection_info_set (klass);
10662 g_assert (mono_class_get_ref_info (klass) == tb);
10665 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10667 if (parent != NULL) {
10668 mono_class_setup_parent (klass, parent);
10669 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10670 const char *old_n = klass->name;
10671 /* trick to get relative numbering right when compiling corlib */
10672 klass->name = "BuildingObject";
10673 mono_class_setup_parent (klass, mono_defaults.object_class);
10674 klass->name = old_n;
10677 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10678 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10679 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10680 klass->instance_size = sizeof (MonoObject);
10681 klass->size_inited = 1;
10682 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10685 mono_class_setup_mono_type (klass);
10687 mono_class_setup_supertypes (klass);
10690 * FIXME: handle interfaces.
10693 tb->type.type = &klass->byval_arg;
10695 if (tb->nesting_type) {
10696 g_assert (tb->nesting_type->type);
10697 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10700 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10702 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10704 mono_loader_unlock ();
10708 mono_loader_unlock ();
10709 mono_error_raise_exception (&error);
10713 * mono_reflection_setup_generic_class:
10714 * @tb: a TypeBuilder object
10716 * Setup the generic class before adding the first generic parameter.
10719 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10724 * mono_reflection_create_generic_class:
10725 * @tb: a TypeBuilder object
10727 * Creates the generic class after all generic parameters have been added.
10730 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10735 klass = mono_class_from_mono_type (tb->type.type);
10737 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10739 if (klass->generic_container || (count == 0))
10742 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10744 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10746 klass->generic_container->owner.klass = klass;
10747 klass->generic_container->type_argc = count;
10748 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10750 klass->is_generic = 1;
10752 for (i = 0; i < count; i++) {
10753 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10754 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10755 klass->generic_container->type_params [i] = *param;
10756 /*Make sure we are a diferent type instance */
10757 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10758 klass->generic_container->type_params [i].info.pklass = NULL;
10759 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10761 g_assert (klass->generic_container->type_params [i].param.owner);
10764 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10768 * mono_reflection_create_internal_class:
10769 * @tb: a TypeBuilder object
10771 * Actually create the MonoClass that is associated with the TypeBuilder.
10774 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10778 klass = mono_class_from_mono_type (tb->type.type);
10780 mono_loader_lock ();
10781 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10782 MonoReflectionFieldBuilder *fb;
10784 MonoType *enum_basetype;
10786 g_assert (tb->fields != NULL);
10787 g_assert (mono_array_length (tb->fields) >= 1);
10789 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10791 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10792 mono_loader_unlock ();
10796 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10797 klass->element_class = mono_class_from_mono_type (enum_basetype);
10798 if (!klass->element_class)
10799 klass->element_class = mono_class_from_mono_type (enum_basetype);
10802 * get the element_class from the current corlib.
10804 ec = default_class_from_mono_type (enum_basetype);
10805 klass->instance_size = ec->instance_size;
10806 klass->size_inited = 1;
10808 * this is almost safe to do with enums and it's needed to be able
10809 * to create objects of the enum type (for use in SetConstant).
10811 /* FIXME: Does this mean enums can't have method overrides ? */
10812 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10814 mono_loader_unlock ();
10817 static MonoMarshalSpec*
10818 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10819 MonoReflectionMarshal *minfo)
10821 MonoMarshalSpec *res;
10823 res = image_g_new0 (image, MonoMarshalSpec, 1);
10824 res->native = (MonoMarshalNative)minfo->type;
10826 switch (minfo->type) {
10827 case MONO_NATIVE_LPARRAY:
10828 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10829 if (minfo->has_size) {
10830 res->data.array_data.param_num = minfo->param_num;
10831 res->data.array_data.num_elem = minfo->count;
10832 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10835 res->data.array_data.param_num = -1;
10836 res->data.array_data.num_elem = -1;
10837 res->data.array_data.elem_mult = -1;
10841 case MONO_NATIVE_BYVALTSTR:
10842 case MONO_NATIVE_BYVALARRAY:
10843 res->data.array_data.num_elem = minfo->count;
10846 case MONO_NATIVE_CUSTOM:
10847 if (minfo->marshaltyperef)
10848 res->data.custom_data.custom_name =
10849 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10850 if (minfo->mcookie)
10851 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10860 #endif /* !DISABLE_REFLECTION_EMIT */
10862 MonoReflectionMarshalAsAttribute*
10863 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10864 MonoMarshalSpec *spec)
10866 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10868 MonoReflectionType *rt;
10869 MonoReflectionMarshalAsAttribute *minfo;
10872 if (!System_Reflection_Emit_MarshalAsAttribute) {
10873 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10874 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10875 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10878 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10879 mono_error_raise_exception (&error); /* FIXME don't raise here */
10880 minfo->utype = spec->native;
10882 switch (minfo->utype) {
10883 case MONO_NATIVE_LPARRAY:
10884 minfo->array_subtype = spec->data.array_data.elem_type;
10885 minfo->size_const = spec->data.array_data.num_elem;
10886 if (spec->data.array_data.param_num != -1)
10887 minfo->size_param_index = spec->data.array_data.param_num;
10890 case MONO_NATIVE_BYVALTSTR:
10891 case MONO_NATIVE_BYVALARRAY:
10892 minfo->size_const = spec->data.array_data.num_elem;
10895 case MONO_NATIVE_CUSTOM:
10896 if (spec->data.custom_data.custom_name) {
10897 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10899 rt = mono_type_get_object_checked (domain, mtype, &error);
10900 mono_error_raise_exception (&error); /* FIXME don't raise here */
10902 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10905 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10907 if (spec->data.custom_data.cookie)
10908 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10918 #ifndef DISABLE_REFLECTION_EMIT
10920 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10921 ReflectionMethodBuilder *rmb,
10922 MonoMethodSignature *sig)
10926 MonoMethodWrapper *wrapperm;
10927 MonoMarshalSpec **specs;
10928 MonoReflectionMethodAux *method_aux;
10933 mono_error_init (&error);
10935 * Methods created using a MethodBuilder should have their memory allocated
10936 * inside the image mempool, while dynamic methods should have their memory
10939 dynamic = rmb->refs != NULL;
10940 image = dynamic ? NULL : klass->image;
10943 g_assert (!klass->generic_class);
10945 mono_loader_lock ();
10947 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10948 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10949 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10951 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10953 wrapperm = (MonoMethodWrapper*)m;
10955 m->dynamic = dynamic;
10957 m->flags = rmb->attrs;
10958 m->iflags = rmb->iattrs;
10959 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10961 m->signature = sig;
10962 m->sre_method = TRUE;
10963 m->skip_visibility = rmb->skip_visibility;
10964 if (rmb->table_idx)
10965 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10967 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10968 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10969 m->string_ctor = 1;
10971 m->signature->pinvoke = 1;
10972 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10973 m->signature->pinvoke = 1;
10975 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10977 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10978 g_assert (mono_error_ok (&error));
10979 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10980 g_assert (mono_error_ok (&error));
10982 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10984 if (image_is_dynamic (klass->image))
10985 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10987 mono_loader_unlock ();
10990 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10991 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10992 MonoMethodHeader *header;
10994 gint32 max_stack, i;
10995 gint32 num_locals = 0;
10996 gint32 num_clauses = 0;
11000 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11001 code_size = rmb->ilgen->code_len;
11002 max_stack = rmb->ilgen->max_stack;
11003 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11004 if (rmb->ilgen->ex_handlers)
11005 num_clauses = method_count_clauses (rmb->ilgen);
11008 code = mono_array_addr (rmb->code, guint8, 0);
11009 code_size = mono_array_length (rmb->code);
11010 /* we probably need to run a verifier on the code... */
11020 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11021 header->code_size = code_size;
11022 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11023 memcpy ((char*)header->code, code, code_size);
11024 header->max_stack = max_stack;
11025 header->init_locals = rmb->init_locals;
11026 header->num_locals = num_locals;
11028 for (i = 0; i < num_locals; ++i) {
11029 MonoReflectionLocalBuilder *lb =
11030 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11032 header->locals [i] = image_g_new0 (image, MonoType, 1);
11033 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11036 header->num_clauses = num_clauses;
11038 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11039 rmb->ilgen, num_clauses);
11042 wrapperm->header = header;
11045 if (rmb->generic_params) {
11046 int count = mono_array_length (rmb->generic_params);
11047 MonoGenericContainer *container = rmb->generic_container;
11049 g_assert (container);
11051 container->type_argc = count;
11052 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11053 container->owner.method = m;
11054 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11056 m->is_generic = TRUE;
11057 mono_method_set_generic_container (m, container);
11059 for (i = 0; i < count; i++) {
11060 MonoReflectionGenericParam *gp =
11061 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11062 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11063 container->type_params [i] = *param;
11067 * The method signature might have pointers to generic parameters that belong to other methods.
11068 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11069 * generic parameters.
11071 for (i = 0; i < m->signature->param_count; ++i) {
11072 MonoType *t = m->signature->params [i];
11073 if (t->type == MONO_TYPE_MVAR) {
11074 MonoGenericParam *gparam = t->data.generic_param;
11075 if (gparam->num < count) {
11076 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11077 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11083 if (klass->generic_container) {
11084 container->parent = klass->generic_container;
11085 container->context.class_inst = klass->generic_container->context.class_inst;
11087 container->context.method_inst = mono_get_shared_generic_inst (container);
11091 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11095 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11097 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11098 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11099 for (i = 0; i < rmb->nrefs; ++i)
11100 data [i + 1] = rmb->refs [i];
11105 /* Parameter info */
11108 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11109 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11110 for (i = 0; i <= m->signature->param_count; ++i) {
11111 MonoReflectionParamBuilder *pb;
11112 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11113 if ((i > 0) && (pb->attrs)) {
11114 /* Make a copy since it might point to a shared type structure */
11115 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11116 m->signature->params [i - 1]->attrs = pb->attrs;
11119 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11120 MonoDynamicImage *assembly;
11122 MonoTypeEnum def_type;
11126 if (!method_aux->param_defaults) {
11127 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11128 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11130 assembly = (MonoDynamicImage*)klass->image;
11131 idx = encode_constant (assembly, pb->def_value, &def_type);
11132 /* Copy the data from the blob since it might get realloc-ed */
11133 p = assembly->blob.data + idx;
11134 len = mono_metadata_decode_blob_size (p, &p2);
11136 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11137 method_aux->param_default_types [i] = def_type;
11138 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11142 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11143 g_assert (mono_error_ok (&error));
11146 if (!method_aux->param_cattr)
11147 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11148 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11154 /* Parameter marshalling */
11157 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11158 MonoReflectionParamBuilder *pb;
11159 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11160 if (pb->marshal_info) {
11162 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11163 specs [pb->position] =
11164 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11168 if (specs != NULL) {
11170 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11171 method_aux->param_marshall = specs;
11174 if (image_is_dynamic (klass->image) && method_aux)
11175 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11177 mono_loader_unlock ();
11183 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11185 ReflectionMethodBuilder rmb;
11186 MonoMethodSignature *sig;
11188 mono_loader_lock ();
11189 sig = ctor_builder_to_signature (klass->image, mb);
11190 mono_loader_unlock ();
11192 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11194 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11195 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11197 /* If we are in a generic class, we might be called multiple times from inflate_method */
11198 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11199 /* ilgen is no longer needed */
11203 return mb->mhandle;
11207 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11209 ReflectionMethodBuilder rmb;
11210 MonoMethodSignature *sig;
11212 mono_loader_lock ();
11213 sig = method_builder_to_signature (klass->image, mb);
11214 mono_loader_unlock ();
11216 reflection_methodbuilder_from_method_builder (&rmb, mb);
11218 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11219 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11221 /* If we are in a generic class, we might be called multiple times from inflate_method */
11222 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11223 /* ilgen is no longer needed */
11226 return mb->mhandle;
11229 static MonoClassField*
11230 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11232 MonoClassField *field;
11236 field = g_new0 (MonoClassField, 1);
11238 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11239 g_assert (mono_error_ok (&error));
11240 if (fb->attrs || fb->modreq || fb->modopt) {
11241 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11242 field->type->attrs = fb->attrs;
11244 g_assert (image_is_dynamic (klass->image));
11245 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11246 g_free (field->type);
11247 field->type = mono_metadata_type_dup (klass->image, custom);
11250 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11252 if (fb->offset != -1)
11253 field->offset = fb->offset;
11254 field->parent = klass;
11255 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11257 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11264 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11267 MonoReflectionTypeBuilder *tb = NULL;
11268 gboolean is_dynamic = FALSE;
11269 MonoClass *geninst;
11271 mono_loader_lock ();
11273 if (is_sre_type_builder (mono_object_class (type))) {
11274 tb = (MonoReflectionTypeBuilder *) type;
11277 } else if (is_sre_generic_instance (mono_object_class (type))) {
11278 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11279 MonoReflectionType *gtd = rgi->generic_type;
11281 if (is_sre_type_builder (mono_object_class (gtd))) {
11282 tb = (MonoReflectionTypeBuilder *)gtd;
11287 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11288 if (tb && tb->generic_container)
11289 mono_reflection_create_generic_class (tb);
11291 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11292 if (!klass->generic_container) {
11293 mono_loader_unlock ();
11297 if (klass->wastypebuilder) {
11298 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11303 mono_loader_unlock ();
11305 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11307 return &geninst->byval_arg;
11311 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11313 MonoGenericClass *gclass;
11314 MonoGenericInst *inst;
11316 g_assert (klass->generic_container);
11318 inst = mono_metadata_get_generic_inst (type_argc, types);
11319 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11321 return mono_generic_class_get_class (gclass);
11324 MonoReflectionMethod*
11325 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11329 MonoMethod *method, *inflated;
11330 MonoMethodInflated *imethod;
11331 MonoGenericContext tmp_context;
11332 MonoGenericInst *ginst;
11333 MonoType **type_argv;
11336 /*FIXME but this no longer should happen*/
11337 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11338 #ifndef DISABLE_REFLECTION_EMIT
11339 MonoReflectionMethodBuilder *mb = NULL;
11340 MonoReflectionTypeBuilder *tb;
11343 mb = (MonoReflectionMethodBuilder *) rmethod;
11344 tb = (MonoReflectionTypeBuilder *) mb->type;
11345 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11347 method = methodbuilder_to_mono_method (klass, mb);
11349 g_assert_not_reached ();
11353 method = rmethod->method;
11356 klass = method->klass;
11358 if (method->is_inflated)
11359 method = ((MonoMethodInflated *) method)->declaring;
11361 count = mono_method_signature (method)->generic_param_count;
11362 if (count != mono_array_length (types))
11365 type_argv = g_new0 (MonoType *, count);
11366 for (i = 0; i < count; i++) {
11367 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11368 type_argv [i] = mono_reflection_type_get_handle (garg);
11370 ginst = mono_metadata_get_generic_inst (count, type_argv);
11371 g_free (type_argv);
11373 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11374 tmp_context.method_inst = ginst;
11376 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11377 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11378 imethod = (MonoMethodInflated *) inflated;
11380 /*FIXME but I think this is no longer necessary*/
11381 if (image_is_dynamic (method->klass->image)) {
11382 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11384 * This table maps metadata structures representing inflated methods/fields
11385 * to the reflection objects representing their generic definitions.
11387 mono_image_lock ((MonoImage*)image);
11388 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11389 mono_image_unlock ((MonoImage*)image);
11392 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11393 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11395 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11396 mono_error_raise_exception (&error); /* FIXME don't raise here */
11400 #ifndef DISABLE_REFLECTION_EMIT
11402 static MonoMethod *
11403 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11405 MonoMethodInflated *imethod;
11406 MonoGenericContext *context;
11410 * With generic code sharing the klass might not be inflated.
11411 * This can happen because classes inflated with their own
11412 * type arguments are "normalized" to the uninflated class.
11414 if (!klass->generic_class)
11417 context = mono_class_get_context (klass);
11419 if (klass->method.count && klass->methods) {
11420 /* Find the already created inflated method */
11421 for (i = 0; i < klass->method.count; ++i) {
11422 g_assert (klass->methods [i]->is_inflated);
11423 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11426 g_assert (i < klass->method.count);
11427 imethod = (MonoMethodInflated*)klass->methods [i];
11430 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11431 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11434 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11435 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11437 mono_image_lock ((MonoImage*)image);
11438 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11439 mono_image_unlock ((MonoImage*)image);
11441 return (MonoMethod *) imethod;
11444 static MonoMethod *
11445 inflate_method (MonoReflectionType *type, MonoObject *obj)
11447 MonoMethod *method;
11450 MonoClass *type_class = mono_object_class (type);
11452 if (is_sre_generic_instance (type_class)) {
11453 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11454 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11455 } else if (is_sre_type_builder (type_class)) {
11456 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11457 } else if (type->type) {
11458 gklass = mono_class_from_mono_type (type->type);
11459 gklass = mono_class_get_generic_type_definition (gklass);
11461 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11464 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11465 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11466 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11468 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11469 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11470 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11471 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11472 method = ((MonoReflectionMethod *) obj)->method;
11474 method = NULL; /* prevent compiler warning */
11475 g_error ("can't handle type %s", obj->vtable->klass->name);
11478 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11481 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11483 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11485 MonoGenericClass *gclass;
11486 MonoDynamicGenericClass *dgclass;
11487 MonoClass *klass, *gklass;
11491 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11492 klass = mono_class_from_mono_type (gtype);
11493 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11494 gclass = gtype->data.generic_class;
11496 if (!gclass->is_dynamic)
11499 dgclass = (MonoDynamicGenericClass *) gclass;
11501 if (dgclass->initialized)
11504 gklass = gclass->container_class;
11505 mono_class_init (gklass);
11507 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11509 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11510 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11511 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11513 for (i = 0; i < dgclass->count_fields; i++) {
11514 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11515 MonoClassField *field, *inflated_field = NULL;
11517 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11518 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11519 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11520 field = ((MonoReflectionField *) obj)->field;
11522 field = NULL; /* prevent compiler warning */
11523 g_assert_not_reached ();
11526 dgclass->fields [i] = *field;
11527 dgclass->fields [i].parent = klass;
11528 dgclass->fields [i].type = mono_class_inflate_generic_type (
11529 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11530 dgclass->field_generic_types [i] = field->type;
11531 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11532 dgclass->field_objects [i] = obj;
11534 if (inflated_field) {
11535 g_free (inflated_field);
11537 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11541 dgclass->initialized = TRUE;
11545 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11547 MonoDynamicGenericClass *dgclass;
11550 g_assert (gclass->is_dynamic);
11552 dgclass = (MonoDynamicGenericClass *)gclass;
11554 for (i = 0; i < dgclass->count_fields; ++i) {
11555 MonoClassField *field = dgclass->fields + i;
11556 mono_metadata_free_type (field->type);
11557 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11562 fix_partial_generic_class (MonoClass *klass)
11564 MonoClass *gklass = klass->generic_class->container_class;
11565 MonoDynamicGenericClass *dgclass;
11568 if (klass->wastypebuilder)
11571 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11572 if (klass->parent != gklass->parent) {
11574 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11575 if (mono_error_ok (&error)) {
11576 MonoClass *parent = mono_class_from_mono_type (parent_type);
11577 mono_metadata_free_type (parent_type);
11578 if (parent != klass->parent) {
11579 /*fool mono_class_setup_parent*/
11580 klass->supertypes = NULL;
11581 mono_class_setup_parent (klass, parent);
11584 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11585 mono_error_cleanup (&error);
11586 if (gklass->wastypebuilder)
11587 klass->wastypebuilder = TRUE;
11592 if (!dgclass->initialized)
11595 if (klass->method.count != gklass->method.count) {
11596 klass->method.count = gklass->method.count;
11597 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11599 for (i = 0; i < klass->method.count; i++) {
11601 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11602 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11603 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11607 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11608 klass->interface_count = gklass->interface_count;
11609 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11610 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11612 for (i = 0; i < gklass->interface_count; ++i) {
11613 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11614 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11615 mono_metadata_free_type (iface_type);
11617 ensure_runtime_vtable (klass->interfaces [i]);
11619 klass->interfaces_inited = 1;
11622 if (klass->field.count != gklass->field.count) {
11623 klass->field.count = gklass->field.count;
11624 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11626 for (i = 0; i < klass->field.count; i++) {
11627 klass->fields [i] = gklass->fields [i];
11628 klass->fields [i].parent = klass;
11629 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11633 /*We can only finish with this klass once it's parent has as well*/
11634 if (gklass->wastypebuilder)
11635 klass->wastypebuilder = TRUE;
11640 ensure_generic_class_runtime_vtable (MonoClass *klass)
11642 MonoClass *gklass = klass->generic_class->container_class;
11644 ensure_runtime_vtable (gklass);
11646 fix_partial_generic_class (klass);
11650 ensure_runtime_vtable (MonoClass *klass)
11652 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11655 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11658 ensure_runtime_vtable (klass->parent);
11661 num = tb->ctors? mono_array_length (tb->ctors): 0;
11662 num += tb->num_methods;
11663 klass->method.count = num;
11664 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11665 num = tb->ctors? mono_array_length (tb->ctors): 0;
11666 for (i = 0; i < num; ++i)
11667 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11668 num = tb->num_methods;
11670 for (i = 0; i < num; ++i)
11671 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11673 if (tb->interfaces) {
11674 klass->interface_count = mono_array_length (tb->interfaces);
11675 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11676 for (i = 0; i < klass->interface_count; ++i) {
11677 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11678 klass->interfaces [i] = mono_class_from_mono_type (iface);
11679 ensure_runtime_vtable (klass->interfaces [i]);
11681 klass->interfaces_inited = 1;
11683 } else if (klass->generic_class){
11684 ensure_generic_class_runtime_vtable (klass);
11687 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11689 for (i = 0; i < klass->method.count; ++i) {
11690 MonoMethod *im = klass->methods [i];
11691 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11692 im->slot = slot_num++;
11695 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11696 mono_class_setup_interface_offsets (klass);
11697 mono_class_setup_interface_id (klass);
11701 * The generic vtable is needed even if image->run is not set since some
11702 * runtime code like ves_icall_Type_GetMethodsByName depends on
11703 * method->slot being defined.
11707 * tb->methods could not be freed since it is used for determining
11708 * overrides during dynamic vtable construction.
11713 mono_reflection_method_get_handle (MonoObject *method)
11715 MonoClass *klass = mono_object_class (method);
11716 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11717 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11718 return sr_method->method;
11720 if (is_sre_method_builder (klass)) {
11721 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11722 return mb->mhandle;
11724 if (is_sre_method_on_tb_inst (klass)) {
11725 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11726 MonoMethod *result;
11727 /*FIXME move this to a proper method and unify with resolve_object*/
11728 if (m->method_args) {
11729 result = mono_reflection_method_on_tb_inst_get_handle (m);
11731 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11732 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11733 MonoMethod *mono_method;
11735 if (is_sre_method_builder (mono_object_class (m->mb)))
11736 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11737 else if (is_sr_mono_method (mono_object_class (m->mb)))
11738 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11740 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)));
11742 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11747 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11752 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11754 MonoReflectionTypeBuilder *tb;
11756 MonoReflectionMethod *m;
11759 *num_overrides = 0;
11761 g_assert (image_is_dynamic (klass->image));
11763 if (!mono_class_get_ref_info (klass))
11766 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11768 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11772 for (i = 0; i < tb->num_methods; ++i) {
11773 MonoReflectionMethodBuilder *mb =
11774 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11775 if (mb->override_methods)
11776 onum += mono_array_length (mb->override_methods);
11781 *overrides = g_new0 (MonoMethod*, onum * 2);
11784 for (i = 0; i < tb->num_methods; ++i) {
11785 MonoReflectionMethodBuilder *mb =
11786 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11787 if (mb->override_methods) {
11788 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11789 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11791 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11792 (*overrides) [onum * 2 + 1] = mb->mhandle;
11794 g_assert (mb->mhandle);
11802 *num_overrides = onum;
11806 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11808 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11809 MonoReflectionFieldBuilder *fb;
11810 MonoClassField *field;
11811 MonoImage *image = klass->image;
11812 const char *p, *p2;
11814 guint32 len, idx, real_size = 0;
11816 klass->field.count = tb->num_fields;
11817 klass->field.first = 0;
11819 mono_error_init (error);
11821 if (tb->class_size) {
11822 if ((tb->packing_size & 0xffffff00) != 0) {
11823 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11824 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11827 klass->packing_size = tb->packing_size;
11828 real_size = klass->instance_size + tb->class_size;
11831 if (!klass->field.count) {
11832 klass->instance_size = MAX (klass->instance_size, real_size);
11836 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11837 mono_class_alloc_ext (klass);
11838 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11840 This is, guess what, a hack.
11841 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11842 On the static path no field class is resolved, only types are built. This is the right thing to do
11844 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11846 klass->size_inited = 1;
11848 for (i = 0; i < klass->field.count; ++i) {
11849 MonoArray *rva_data;
11850 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11851 field = &klass->fields [i];
11852 field->name = mono_string_to_utf8_image (image, fb->name, error);
11853 if (!mono_error_ok (error))
11856 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11857 field->type->attrs = fb->attrs;
11859 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11862 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11863 char *base = mono_array_addr (rva_data, char, 0);
11864 size_t size = mono_array_length (rva_data);
11865 char *data = (char *)mono_image_alloc (klass->image, size);
11866 memcpy (data, base, size);
11867 klass->ext->field_def_values [i].data = data;
11869 if (fb->offset != -1)
11870 field->offset = fb->offset;
11871 field->parent = klass;
11872 fb->handle = field;
11873 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11875 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11876 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11878 if (fb->def_value) {
11879 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11880 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11881 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11882 /* Copy the data from the blob since it might get realloc-ed */
11883 p = assembly->blob.data + idx;
11884 len = mono_metadata_decode_blob_size (p, &p2);
11886 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11887 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11891 klass->instance_size = MAX (klass->instance_size, real_size);
11892 mono_class_layout_fields (klass);
11896 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11898 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11899 MonoReflectionPropertyBuilder *pb;
11900 MonoImage *image = klass->image;
11901 MonoProperty *properties;
11904 mono_error_init (error);
11907 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11909 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11910 klass->ext->property.first = 0;
11912 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11913 klass->ext->properties = properties;
11914 for (i = 0; i < klass->ext->property.count; ++i) {
11915 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11916 properties [i].parent = klass;
11917 properties [i].attrs = pb->attrs;
11918 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11919 if (!mono_error_ok (error))
11921 if (pb->get_method)
11922 properties [i].get = pb->get_method->mhandle;
11923 if (pb->set_method)
11924 properties [i].set = pb->set_method->mhandle;
11926 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11927 if (pb->def_value) {
11929 const char *p, *p2;
11930 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11931 if (!klass->ext->prop_def_values)
11932 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11933 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11934 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11935 /* Copy the data from the blob since it might get realloc-ed */
11936 p = assembly->blob.data + idx;
11937 len = mono_metadata_decode_blob_size (p, &p2);
11939 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11940 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11945 MonoReflectionEvent *
11946 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11948 MonoEvent *event = g_new0 (MonoEvent, 1);
11951 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11953 event->parent = klass;
11954 event->attrs = eb->attrs;
11955 event->name = mono_string_to_utf8 (eb->name);
11956 if (eb->add_method)
11957 event->add = eb->add_method->mhandle;
11958 if (eb->remove_method)
11959 event->remove = eb->remove_method->mhandle;
11960 if (eb->raise_method)
11961 event->raise = eb->raise_method->mhandle;
11963 #ifndef MONO_SMALL_CONFIG
11964 if (eb->other_methods) {
11966 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11967 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11968 MonoReflectionMethodBuilder *mb =
11969 mono_array_get (eb->other_methods,
11970 MonoReflectionMethodBuilder*, j);
11971 event->other [j] = mb->mhandle;
11976 return mono_event_get_object (mono_object_domain (tb), klass, event);
11980 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11982 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11983 MonoReflectionEventBuilder *eb;
11984 MonoImage *image = klass->image;
11988 mono_error_init (error);
11991 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11993 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11994 klass->ext->event.first = 0;
11996 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11997 klass->ext->events = events;
11998 for (i = 0; i < klass->ext->event.count; ++i) {
11999 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12000 events [i].parent = klass;
12001 events [i].attrs = eb->attrs;
12002 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12003 if (!mono_error_ok (error))
12005 if (eb->add_method)
12006 events [i].add = eb->add_method->mhandle;
12007 if (eb->remove_method)
12008 events [i].remove = eb->remove_method->mhandle;
12009 if (eb->raise_method)
12010 events [i].raise = eb->raise_method->mhandle;
12012 #ifndef MONO_SMALL_CONFIG
12013 if (eb->other_methods) {
12015 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12016 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12017 MonoReflectionMethodBuilder *mb =
12018 mono_array_get (eb->other_methods,
12019 MonoReflectionMethodBuilder*, j);
12020 events [i].other [j] = mb->mhandle;
12024 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12029 remove_instantiations_of_and_ensure_contents (gpointer key,
12031 gpointer user_data)
12033 MonoType *type = (MonoType*)key;
12034 MonoClass *klass = (MonoClass*)user_data;
12036 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12037 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12044 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12046 mono_error_init (error);
12052 for (i = 0; i < mono_array_length (arr); ++i) {
12053 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12054 if (!mono_error_ok (error))
12059 MonoReflectionType*
12060 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12064 MonoDomain* domain;
12065 MonoReflectionType* res;
12068 domain = mono_object_domain (tb);
12069 klass = mono_class_from_mono_type (tb->type.type);
12072 * Check for user defined Type subclasses.
12074 RESOLVE_TYPE (tb->parent, &error);
12075 mono_error_raise_exception (&error); /* FIXME don't raise here */
12076 check_array_for_usertypes (tb->interfaces, &error);
12077 mono_error_raise_exception (&error); /*FIXME don't raise here */
12079 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12080 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12082 RESOLVE_TYPE (fb->type, &error);
12083 mono_error_raise_exception (&error); /* FIXME don't raise here */
12084 check_array_for_usertypes (fb->modreq, &error);
12085 mono_error_raise_exception (&error); /*FIXME don't raise here */
12086 check_array_for_usertypes (fb->modopt, &error);
12087 mono_error_raise_exception (&error); /*FIXME don't raise here */
12088 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12089 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12090 mono_error_raise_exception (&error); /* FIXME don't raise here */
12096 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12097 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12099 RESOLVE_TYPE (mb->rtype, &error);
12100 mono_error_raise_exception (&error); /* FIXME don't raise here */
12101 check_array_for_usertypes (mb->return_modreq, &error);
12102 mono_error_raise_exception (&error); /*FIXME don't raise here */
12103 check_array_for_usertypes (mb->return_modopt, &error);
12104 mono_error_raise_exception (&error); /*FIXME don't raise here */
12105 check_array_for_usertypes (mb->parameters, &error);
12106 mono_error_raise_exception (&error); /*FIXME don't raise here */
12107 if (mb->param_modreq)
12108 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12109 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12110 mono_error_raise_exception (&error); /*FIXME don't raise here */
12112 if (mb->param_modopt)
12113 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12114 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12115 mono_error_raise_exception (&error); /*FIXME don't raise here */
12121 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12122 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12124 check_array_for_usertypes (mb->parameters, &error);
12125 mono_error_raise_exception (&error); /*FIXME don't raise here */
12126 if (mb->param_modreq)
12127 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12128 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12129 mono_error_raise_exception (&error); /*FIXME don't raise here */
12131 if (mb->param_modopt)
12132 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12133 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12134 mono_error_raise_exception (&error); /*FIXME don't raise here */
12140 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12143 * we need to lock the domain because the lock will be taken inside
12144 * So, we need to keep the locking order correct.
12146 mono_loader_lock ();
12147 mono_domain_lock (domain);
12148 if (klass->wastypebuilder) {
12149 mono_domain_unlock (domain);
12150 mono_loader_unlock ();
12152 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12153 mono_error_raise_exception (&error); /* FIXME don't raise here */
12158 * Fields to set in klass:
12159 * the various flags: delegate/unicode/contextbound etc.
12161 klass->flags = tb->attrs;
12162 klass->has_cctor = 1;
12163 klass->has_finalize = 1;
12164 klass->has_finalize_inited = 1;
12166 mono_class_setup_parent (klass, klass->parent);
12167 /* fool mono_class_setup_supertypes */
12168 klass->supertypes = NULL;
12169 mono_class_setup_supertypes (klass);
12170 mono_class_setup_mono_type (klass);
12173 if (!((MonoDynamicImage*)klass->image)->run) {
12174 if (klass->generic_container) {
12175 /* FIXME: The code below can't handle generic classes */
12176 klass->wastypebuilder = TRUE;
12177 mono_loader_unlock ();
12178 mono_domain_unlock (domain);
12180 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12181 mono_error_raise_exception (&error); /* FIXME don't raise here */
12188 /* enums are done right away */
12189 if (!klass->enumtype)
12190 ensure_runtime_vtable (klass);
12192 if (tb->subtypes) {
12193 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12194 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12195 mono_class_alloc_ext (klass);
12196 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)));
12200 klass->nested_classes_inited = TRUE;
12202 /* fields and object layout */
12203 if (klass->parent) {
12204 if (!klass->parent->size_inited)
12205 mono_class_init (klass->parent);
12206 klass->instance_size = klass->parent->instance_size;
12207 klass->sizes.class_size = 0;
12208 klass->min_align = klass->parent->min_align;
12209 /* if the type has no fields we won't call the field_setup
12210 * routine which sets up klass->has_references.
12212 klass->has_references |= klass->parent->has_references;
12214 klass->instance_size = sizeof (MonoObject);
12215 klass->min_align = 1;
12218 /* FIXME: handle packing_size and instance_size */
12219 typebuilder_setup_fields (klass, &error);
12220 if (!mono_error_ok (&error))
12222 typebuilder_setup_properties (klass, &error);
12223 if (!mono_error_ok (&error))
12226 typebuilder_setup_events (klass, &error);
12227 if (!mono_error_ok (&error))
12230 klass->wastypebuilder = TRUE;
12233 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12234 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12235 * we want to return normal System.MonoType objects, so clear these out from the cache.
12237 * Together with this we must ensure the contents of all instances to match the created type.
12239 if (domain->type_hash && klass->generic_container)
12240 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12242 mono_domain_unlock (domain);
12243 mono_loader_unlock ();
12245 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12246 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12247 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12250 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12251 mono_error_raise_exception (&error); /* FIXME don't raise here */
12253 g_assert (res != (MonoReflectionType*)tb);
12258 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12259 klass->wastypebuilder = TRUE;
12260 mono_domain_unlock (domain);
12261 mono_loader_unlock ();
12262 mono_error_raise_exception (&error);
12267 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12269 MonoGenericParamFull *param;
12274 image = &gparam->tbuilder->module->dynamic_image->image;
12276 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12278 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12279 g_assert (mono_error_ok (&error));
12280 param->param.num = gparam->index;
12282 if (gparam->mbuilder) {
12283 if (!gparam->mbuilder->generic_container) {
12284 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12285 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12286 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12287 gparam->mbuilder->generic_container->is_method = TRUE;
12289 * Cannot set owner.method, since the MonoMethod is not created yet.
12290 * Set the image field instead, so type_in_image () works.
12292 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12293 gparam->mbuilder->generic_container->owner.image = klass->image;
12295 param->param.owner = gparam->mbuilder->generic_container;
12296 } else if (gparam->tbuilder) {
12297 if (!gparam->tbuilder->generic_container) {
12298 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12299 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12300 gparam->tbuilder->generic_container->owner.klass = klass;
12302 param->param.owner = gparam->tbuilder->generic_container;
12305 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12307 gparam->type.type = &pklass->byval_arg;
12309 mono_class_set_ref_info (pklass, gparam);
12310 mono_image_append_class_to_reflection_info_set (pklass);
12314 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12317 MonoReflectionModuleBuilder *module = sig->module;
12318 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12319 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12324 check_array_for_usertypes (sig->arguments, &error);
12325 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12327 sigbuffer_init (&buf, 32);
12329 sigbuffer_add_value (&buf, 0x07);
12330 sigbuffer_add_value (&buf, na);
12331 if (assembly != NULL){
12332 for (i = 0; i < na; ++i) {
12333 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12334 encode_reflection_type (assembly, type, &buf);
12338 buflen = buf.p - buf.buf;
12339 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12340 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12341 sigbuffer_free (&buf);
12347 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12350 MonoDynamicImage *assembly = sig->module->dynamic_image;
12351 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12356 check_array_for_usertypes (sig->arguments, &error);
12357 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12359 sigbuffer_init (&buf, 32);
12361 sigbuffer_add_value (&buf, 0x06);
12362 for (i = 0; i < na; ++i) {
12363 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12364 encode_reflection_type (assembly, type, &buf);
12367 buflen = buf.p - buf.buf;
12368 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12369 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12370 sigbuffer_free (&buf);
12376 MonoMethod *handle;
12377 MonoDomain *domain;
12378 } DynamicMethodReleaseData;
12381 * The runtime automatically clean up those after finalization.
12383 static MonoReferenceQueue *dynamic_method_queue;
12386 free_dynamic_method (void *dynamic_method)
12388 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12389 MonoDomain *domain = data->domain;
12390 MonoMethod *method = data->handle;
12393 mono_domain_lock (domain);
12394 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12395 g_hash_table_remove (domain->method_to_dyn_method, method);
12396 mono_domain_unlock (domain);
12397 g_assert (dis_link);
12398 mono_gchandle_free (dis_link);
12400 mono_runtime_free_method (domain, method);
12405 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12407 MonoReferenceQueue *queue;
12408 MonoMethod *handle;
12409 DynamicMethodReleaseData *release_data;
12410 ReflectionMethodBuilder rmb;
12411 MonoMethodSignature *sig;
12413 MonoDomain *domain;
12417 if (mono_runtime_is_shutting_down ())
12418 mono_raise_exception (mono_get_exception_invalid_operation (""));
12420 if (!(queue = dynamic_method_queue)) {
12421 mono_loader_lock ();
12422 if (!(queue = dynamic_method_queue))
12423 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12424 mono_loader_unlock ();
12427 sig = dynamic_method_to_signature (mb);
12429 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12432 * Resolve references.
12435 * Every second entry in the refs array is reserved for storing handle_class,
12436 * which is needed by the ldtoken implementation in the JIT.
12438 rmb.nrefs = mb->nrefs;
12439 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12440 for (i = 0; i < mb->nrefs; i += 2) {
12441 MonoClass *handle_class;
12443 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12445 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12446 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12448 * The referenced DynamicMethod should already be created by the managed
12449 * code, except in the case of circular references. In that case, we store
12450 * method in the refs array, and fix it up later when the referenced
12451 * DynamicMethod is created.
12453 if (method->mhandle) {
12454 ref = method->mhandle;
12456 /* FIXME: GC object stored in unmanaged memory */
12459 /* FIXME: GC object stored in unmanaged memory */
12460 method->referenced_by = g_slist_append (method->referenced_by, mb);
12462 handle_class = mono_defaults.methodhandle_class;
12464 MonoException *ex = NULL;
12465 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12467 ex = mono_get_exception_type_load (NULL, NULL);
12468 else if (mono_security_core_clr_enabled ())
12469 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12473 mono_raise_exception (ex);
12478 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12479 rmb.refs [i + 1] = handle_class;
12482 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12484 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12485 release_data = g_new (DynamicMethodReleaseData, 1);
12486 release_data->handle = handle;
12487 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12488 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12489 g_free (release_data);
12491 /* Fix up refs entries pointing at us */
12492 for (l = mb->referenced_by; l; l = l->next) {
12493 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12494 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12497 g_assert (method->mhandle);
12499 data = (gpointer*)wrapper->method_data;
12500 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12501 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12502 data [i + 1] = mb->mhandle;
12505 g_slist_free (mb->referenced_by);
12509 /* ilgen is no longer needed */
12512 domain = mono_domain_get ();
12513 mono_domain_lock (domain);
12514 if (!domain->method_to_dyn_method)
12515 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12516 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12517 mono_domain_unlock (domain);
12520 #endif /* DISABLE_REFLECTION_EMIT */
12524 * mono_reflection_is_valid_dynamic_token:
12526 * Returns TRUE if token is valid.
12530 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12532 return lookup_dyn_token (image, token) != NULL;
12535 MonoMethodSignature *
12536 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12538 MonoMethodSignature *sig;
12539 g_assert (image_is_dynamic (image));
12541 mono_error_init (error);
12543 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12547 return mono_method_signature_checked (method, error);
12550 #ifndef DISABLE_REFLECTION_EMIT
12553 * mono_reflection_lookup_dynamic_token:
12555 * Finish the Builder object pointed to by TOKEN and return the corresponding
12556 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12557 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12560 * LOCKING: Take the loader lock
12563 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12565 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12569 obj = lookup_dyn_token (assembly, token);
12572 g_error ("Could not find required dynamic token 0x%08x", token);
12578 handle_class = &klass;
12579 return resolve_object (image, obj, handle_class, context);
12583 * ensure_complete_type:
12585 * Ensure that KLASS is completed if it is a dynamic type, or references
12589 ensure_complete_type (MonoClass *klass)
12591 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12592 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12594 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12596 // Asserting here could break a lot of code
12597 //g_assert (klass->wastypebuilder);
12600 if (klass->generic_class) {
12601 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12604 for (i = 0; i < inst->type_argc; ++i) {
12605 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12611 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12613 gpointer result = NULL;
12615 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12616 result = mono_string_intern ((MonoString*)obj);
12617 *handle_class = mono_defaults.string_class;
12619 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12620 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12621 MonoClass *mc = mono_class_from_mono_type (type);
12622 if (!mono_class_init (mc))
12623 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12626 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12627 result = mono_class_from_mono_type (inflated);
12628 mono_metadata_free_type (inflated);
12630 result = mono_class_from_mono_type (type);
12632 *handle_class = mono_defaults.typehandle_class;
12634 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12635 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12636 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12637 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12638 result = ((MonoReflectionMethod*)obj)->method;
12641 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12642 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12644 *handle_class = mono_defaults.methodhandle_class;
12646 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12647 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12648 result = mb->mhandle;
12650 /* Type is not yet created */
12651 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12653 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12656 * Hopefully this has been filled in by calling CreateType() on the
12660 * TODO: This won't work if the application finishes another
12661 * TypeBuilder instance instead of this one.
12663 result = mb->mhandle;
12667 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12668 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12670 *handle_class = mono_defaults.methodhandle_class;
12671 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12672 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12674 result = cb->mhandle;
12676 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12678 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12679 result = cb->mhandle;
12683 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12684 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12686 *handle_class = mono_defaults.methodhandle_class;
12687 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12688 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12690 ensure_complete_type (field->parent);
12692 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12693 MonoClass *klass = mono_class_from_mono_type (inflated);
12694 MonoClassField *inflated_field;
12695 gpointer iter = NULL;
12696 mono_metadata_free_type (inflated);
12697 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12698 if (!strcmp (field->name, inflated_field->name))
12701 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12702 result = inflated_field;
12706 *handle_class = mono_defaults.fieldhandle_class;
12708 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12709 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12710 result = fb->handle;
12713 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12715 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12716 result = fb->handle;
12719 if (fb->handle && fb->handle->parent->generic_container) {
12720 MonoClass *klass = fb->handle->parent;
12721 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12722 MonoClass *inflated = mono_class_from_mono_type (type);
12724 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12726 mono_metadata_free_type (type);
12728 *handle_class = mono_defaults.fieldhandle_class;
12729 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12730 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12731 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12734 klass = type->data.klass;
12735 if (klass->wastypebuilder) {
12736 /* Already created */
12740 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12741 result = type->data.klass;
12744 *handle_class = mono_defaults.typehandle_class;
12745 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12746 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12747 MonoMethodSignature *sig;
12750 if (helper->arguments)
12751 nargs = mono_array_length (helper->arguments);
12755 sig = mono_metadata_signature_alloc (image, nargs);
12756 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12757 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12759 if (helper->unmanaged_call_conv) { /* unmanaged */
12760 sig->call_convention = helper->unmanaged_call_conv - 1;
12761 sig->pinvoke = TRUE;
12762 } else if (helper->call_conv & 0x02) {
12763 sig->call_convention = MONO_CALL_VARARG;
12765 sig->call_convention = MONO_CALL_DEFAULT;
12768 sig->param_count = nargs;
12769 /* TODO: Copy type ? */
12770 sig->ret = helper->return_type->type;
12771 for (i = 0; i < nargs; ++i)
12772 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12775 *handle_class = NULL;
12776 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12777 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12778 /* Already created by the managed code */
12779 g_assert (method->mhandle);
12780 result = method->mhandle;
12781 *handle_class = mono_defaults.methodhandle_class;
12782 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12783 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12784 type = mono_class_inflate_generic_type (type, context);
12785 result = mono_class_from_mono_type (type);
12786 *handle_class = mono_defaults.typehandle_class;
12788 mono_metadata_free_type (type);
12789 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12790 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12791 type = mono_class_inflate_generic_type (type, context);
12792 result = mono_class_from_mono_type (type);
12793 *handle_class = mono_defaults.typehandle_class;
12795 mono_metadata_free_type (type);
12796 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12797 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12798 MonoClass *inflated;
12800 MonoClassField *field;
12802 if (is_sre_field_builder (mono_object_class (f->fb)))
12803 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12804 else if (is_sr_mono_field (mono_object_class (f->fb)))
12805 field = ((MonoReflectionField*)f->fb)->field;
12807 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)));
12809 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12810 inflated = mono_class_from_mono_type (type);
12812 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12813 ensure_complete_type (field->parent);
12815 mono_metadata_free_type (type);
12816 *handle_class = mono_defaults.fieldhandle_class;
12817 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12818 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12819 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12820 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12821 MonoMethod *method;
12823 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12824 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12825 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12826 method = ((MonoReflectionMethod *)c->cb)->method;
12828 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)));
12830 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12831 *handle_class = mono_defaults.methodhandle_class;
12832 mono_metadata_free_type (type);
12833 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12834 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12835 if (m->method_args) {
12836 result = mono_reflection_method_on_tb_inst_get_handle (m);
12839 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12840 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12843 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12844 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12845 MonoMethod *method;
12847 if (is_sre_method_builder (mono_object_class (m->mb)))
12848 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12849 else if (is_sr_mono_method (mono_object_class (m->mb)))
12850 method = ((MonoReflectionMethod *)m->mb)->method;
12852 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)));
12854 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12855 mono_metadata_free_type (type);
12857 *handle_class = mono_defaults.methodhandle_class;
12858 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12859 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12862 MonoMethod *method;
12866 mtype = mono_reflection_type_get_handle (m->parent);
12867 klass = mono_class_from_mono_type (mtype);
12869 /* Find the method */
12871 name = mono_string_to_utf8 (m->name);
12873 while ((method = mono_class_get_methods (klass, &iter))) {
12874 if (!strcmp (method->name, name))
12881 // FIXME: Check parameters/return value etc. match
12884 *handle_class = mono_defaults.methodhandle_class;
12885 } else if (is_sre_array (mono_object_get_class(obj)) ||
12886 is_sre_byref (mono_object_get_class(obj)) ||
12887 is_sre_pointer (mono_object_get_class(obj))) {
12888 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12889 MonoType *type = mono_reflection_type_get_handle (ref_type);
12892 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12893 result = mono_class_from_mono_type (inflated);
12894 mono_metadata_free_type (inflated);
12896 result = mono_class_from_mono_type (type);
12898 *handle_class = mono_defaults.typehandle_class;
12900 g_print ("%s\n", obj->vtable->klass->name);
12901 g_assert_not_reached ();
12906 #else /* DISABLE_REFLECTION_EMIT */
12909 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12911 g_assert_not_reached ();
12916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12918 g_assert_not_reached ();
12922 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12924 g_assert_not_reached ();
12928 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12930 g_assert_not_reached ();
12934 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12936 g_assert_not_reached ();
12940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12942 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12946 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12948 g_assert_not_reached ();
12952 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12954 g_assert_not_reached ();
12957 MonoReflectionModule *
12958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12960 g_assert_not_reached ();
12965 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12967 g_assert_not_reached ();
12972 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
12974 g_assert_not_reached ();
12979 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12980 gboolean create_open_instance, gboolean register_token)
12982 g_assert_not_reached ();
12987 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12992 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12994 g_assert_not_reached ();
12998 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13001 *num_overrides = 0;
13004 MonoReflectionEvent *
13005 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13007 g_assert_not_reached ();
13011 MonoReflectionType*
13012 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13014 g_assert_not_reached ();
13019 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13021 g_assert_not_reached ();
13025 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13027 g_assert_not_reached ();
13032 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13034 g_assert_not_reached ();
13039 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13044 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13050 mono_reflection_type_get_handle (MonoReflectionType* ref)
13058 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13060 g_assert_not_reached ();
13063 #endif /* DISABLE_REFLECTION_EMIT */
13065 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13066 const static guint32 declsec_flags_map[] = {
13067 0x00000000, /* empty */
13068 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13069 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13070 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13071 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13072 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13073 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13074 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13075 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13076 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13077 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13078 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13079 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13080 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13081 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13082 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13083 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13084 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13085 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13089 * Returns flags that includes all available security action associated to the handle.
13090 * @token: metadata token (either for a class or a method)
13091 * @image: image where resides the metadata.
13094 mono_declsec_get_flags (MonoImage *image, guint32 token)
13096 int index = mono_metadata_declsec_from_index (image, token);
13097 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13098 guint32 result = 0;
13102 /* HasSecurity can be present for other, not specially encoded, attributes,
13103 e.g. SuppressUnmanagedCodeSecurityAttribute */
13107 for (i = index; i < t->rows; i++) {
13108 guint32 cols [MONO_DECL_SECURITY_SIZE];
13110 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13111 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13114 action = cols [MONO_DECL_SECURITY_ACTION];
13115 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13116 result |= declsec_flags_map [action];
13118 g_assert_not_reached ();
13125 * Get the security actions (in the form of flags) associated with the specified method.
13127 * @method: The method for which we want the declarative security flags.
13128 * Return the declarative security flags for the method (only).
13130 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13131 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13134 mono_declsec_flags_from_method (MonoMethod *method)
13136 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13137 /* FIXME: No cache (for the moment) */
13138 guint32 idx = mono_method_get_index (method);
13139 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13140 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13141 return mono_declsec_get_flags (method->klass->image, idx);
13147 * Get the security actions (in the form of flags) associated with the specified class.
13149 * @klass: The class for which we want the declarative security flags.
13150 * Return the declarative security flags for the class.
13152 * Note: We cache the flags inside the MonoClass structure as this will get
13153 * called very often (at least for each method).
13156 mono_declsec_flags_from_class (MonoClass *klass)
13158 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13159 if (!klass->ext || !klass->ext->declsec_flags) {
13162 idx = mono_metadata_token_index (klass->type_token);
13163 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13164 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13165 mono_loader_lock ();
13166 mono_class_alloc_ext (klass);
13167 mono_loader_unlock ();
13168 /* we cache the flags on classes */
13169 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13171 return klass->ext->declsec_flags;
13177 * Get the security actions (in the form of flags) associated with the specified assembly.
13179 * @assembly: The assembly for which we want the declarative security flags.
13180 * Return the declarative security flags for the assembly.
13183 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13185 guint32 idx = 1; /* there is only one assembly */
13186 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13187 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13188 return mono_declsec_get_flags (assembly->image, idx);
13193 * Fill actions for the specific index (which may either be an encoded class token or
13194 * an encoded method token) from the metadata image.
13195 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13198 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13199 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13201 MonoBoolean result = FALSE;
13203 guint32 cols [MONO_DECL_SECURITY_SIZE];
13204 int index = mono_metadata_declsec_from_index (image, token);
13207 t = &image->tables [MONO_TABLE_DECLSECURITY];
13208 for (i = index; i < t->rows; i++) {
13209 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13211 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13214 /* if present only replace (class) permissions with method permissions */
13215 /* if empty accept either class or method permissions */
13216 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13217 if (!actions->demand.blob) {
13218 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13219 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13220 actions->demand.blob = (char*) (blob + 2);
13221 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13224 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13225 if (!actions->noncasdemand.blob) {
13226 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13227 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13228 actions->noncasdemand.blob = (char*) (blob + 2);
13229 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13232 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13233 if (!actions->demandchoice.blob) {
13234 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13235 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13236 actions->demandchoice.blob = (char*) (blob + 2);
13237 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13247 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13248 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13250 guint32 idx = mono_metadata_token_index (klass->type_token);
13251 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13252 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13253 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13257 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13258 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13260 guint32 idx = mono_method_get_index (method);
13261 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13262 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13263 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13267 * Collect all actions (that requires to generate code in mini) assigned for
13268 * the specified method.
13269 * Note: Don't use the content of actions if the function return FALSE.
13272 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13274 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13275 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13276 MonoBoolean result = FALSE;
13279 /* quick exit if no declarative security is present in the metadata */
13280 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13283 /* we want the original as the wrapper is "free" of the security informations */
13284 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13285 method = mono_marshal_method_from_wrapper (method);
13290 /* First we look for method-level attributes */
13291 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13292 mono_class_init (method->klass);
13293 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13295 result = mono_declsec_get_method_demands_params (method, demands,
13296 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13299 /* Here we use (or create) the class declarative cache to look for demands */
13300 flags = mono_declsec_flags_from_class (method->klass);
13301 if (flags & mask) {
13303 mono_class_init (method->klass);
13304 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13306 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13307 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13310 /* The boolean return value is used as a shortcut in case nothing needs to
13311 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13317 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13319 * Note: Don't use the content of actions if the function return FALSE.
13322 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13324 MonoBoolean result = FALSE;
13327 /* quick exit if no declarative security is present in the metadata */
13328 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13331 /* we want the original as the wrapper is "free" of the security informations */
13332 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13333 method = mono_marshal_method_from_wrapper (method);
13338 /* results are independant - zeroize both */
13339 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13340 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13342 /* First we look for method-level attributes */
13343 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13344 mono_class_init (method->klass);
13346 result = mono_declsec_get_method_demands_params (method, cmethod,
13347 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13350 /* Here we use (or create) the class declarative cache to look for demands */
13351 flags = mono_declsec_flags_from_class (method->klass);
13352 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13353 mono_class_init (method->klass);
13355 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13356 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13363 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13365 * @klass The inherited class - this is the class that provides the security check (attributes)
13367 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13369 * Note: Don't use the content of actions if the function return FALSE.
13372 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13374 MonoBoolean result = FALSE;
13377 /* quick exit if no declarative security is present in the metadata */
13378 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13381 /* Here we use (or create) the class declarative cache to look for demands */
13382 flags = mono_declsec_flags_from_class (klass);
13383 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13384 mono_class_init (klass);
13385 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13387 result |= mono_declsec_get_class_demands_params (klass, demands,
13388 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13395 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13397 * Note: Don't use the content of actions if the function return FALSE.
13400 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13402 /* quick exit if no declarative security is present in the metadata */
13403 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13406 /* we want the original as the wrapper is "free" of the security informations */
13407 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13408 method = mono_marshal_method_from_wrapper (method);
13413 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13414 mono_class_init (method->klass);
13415 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13417 return mono_declsec_get_method_demands_params (method, demands,
13418 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13425 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13427 guint32 cols [MONO_DECL_SECURITY_SIZE];
13431 int index = mono_metadata_declsec_from_index (image, token);
13435 t = &image->tables [MONO_TABLE_DECLSECURITY];
13436 for (i = index; i < t->rows; i++) {
13437 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13439 /* shortcut - index are ordered */
13440 if (token != cols [MONO_DECL_SECURITY_PARENT])
13443 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13444 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13445 entry->blob = (char*) (metadata + 2);
13446 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13455 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13457 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13458 guint32 idx = mono_method_get_index (method);
13459 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13460 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13461 return get_declsec_action (method->klass->image, idx, action, entry);
13467 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13470 guint32 flags = mono_declsec_flags_from_class (klass);
13471 if (declsec_flags_map [action] & flags) {
13472 guint32 idx = mono_metadata_token_index (klass->type_token);
13473 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13474 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13475 return get_declsec_action (klass->image, idx, action, entry);
13481 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13483 guint32 idx = 1; /* there is only one assembly */
13484 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13485 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13487 return get_declsec_action (assembly->image, idx, action, entry);
13491 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13494 MonoObject *res, *exc;
13496 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13497 static MonoMethod *method = NULL;
13499 if (!System_Reflection_Emit_TypeBuilder) {
13500 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13501 g_assert (System_Reflection_Emit_TypeBuilder);
13503 if (method == NULL) {
13504 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13509 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13510 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13512 g_assert (mono_class_get_ref_info (klass));
13513 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13515 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13516 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13522 return *(MonoBoolean*)mono_object_unbox (res);
13526 * mono_reflection_type_get_type:
13527 * @reftype: the System.Type object
13529 * Returns the MonoType* associated with the C# System.Type object @reftype.
13532 mono_reflection_type_get_type (MonoReflectionType *reftype)
13534 g_assert (reftype);
13536 return mono_reflection_type_get_handle (reftype);
13540 * mono_reflection_assembly_get_assembly:
13541 * @refassembly: the System.Reflection.Assembly object
13543 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13546 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13548 g_assert (refassembly);
13550 return refassembly->assembly;