2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
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 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
247 dynamic_images_lock (void)
249 mono_os_mutex_lock (&dynamic_images_mutex);
253 dynamic_images_unlock (void)
255 mono_os_mutex_unlock (&dynamic_images_mutex);
259 * mono_find_dynamic_image_owner:
261 * Find the dynamic image, if any, which a given pointer is located in the memory of.
264 mono_find_dynamic_image_owner (void *ptr)
266 MonoImage *owner = NULL;
269 dynamic_images_lock ();
273 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275 if (mono_mempool_contains_addr (image->mempool, ptr))
280 dynamic_images_unlock ();
286 mono_reflection_init (void)
288 mono_os_mutex_init (&dynamic_images_mutex);
292 dynamic_image_lock (MonoDynamicImage *image)
294 MONO_PREPARE_BLOCKING;
295 mono_image_lock ((MonoImage*)image);
296 MONO_FINISH_BLOCKING;
300 dynamic_image_unlock (MonoDynamicImage *image)
302 mono_image_unlock ((MonoImage*)image);
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
308 MONO_REQ_GC_UNSAFE_MODE;
310 dynamic_image_lock (assembly);
311 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312 dynamic_image_unlock (assembly);
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
318 MONO_REQ_GC_UNSAFE_MODE;
322 dynamic_image_lock (assembly);
323 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324 dynamic_image_unlock (assembly);
330 sigbuffer_init (SigBuffer *buf, int size)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 buf->buf = (char *)g_malloc (size);
336 buf->end = buf->buf + size;
340 sigbuffer_make_room (SigBuffer *buf, int size)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 if (buf->end - buf->p < size) {
345 int new_size = buf->end - buf->buf + size + 32;
346 char *p = (char *)g_realloc (buf->buf, new_size);
347 size = buf->p - buf->buf;
350 buf->end = buf->buf + new_size;
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
357 MONO_REQ_GC_NEUTRAL_MODE;
359 sigbuffer_make_room (buf, 6);
360 mono_metadata_encode_value (val, buf->p, &buf->p);
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
366 MONO_REQ_GC_NEUTRAL_MODE;
368 sigbuffer_make_room (buf, 1);
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
376 MONO_REQ_GC_NEUTRAL_MODE;
378 sigbuffer_make_room (buf, size);
379 memcpy (buf->p, p, size);
384 sigbuffer_free (SigBuffer *buf)
386 MONO_REQ_GC_NEUTRAL_MODE;
391 #ifndef DISABLE_REFLECTION_EMIT
395 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399 image_g_malloc (MonoImage *image, guint size)
401 MONO_REQ_GC_NEUTRAL_MODE;
404 return mono_image_alloc (image, size);
406 return g_malloc (size);
408 #endif /* !DISABLE_REFLECTION_EMIT */
413 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417 image_g_malloc0 (MonoImage *image, guint size)
419 MONO_REQ_GC_NEUTRAL_MODE;
422 return mono_image_alloc0 (image, size);
424 return g_malloc0 (size);
427 #ifndef DISABLE_REFLECTION_EMIT
429 image_strdup (MonoImage *image, const char *s)
431 MONO_REQ_GC_NEUTRAL_MODE;
434 return mono_image_strdup (image, s);
440 #define image_g_new(image,struct_type, n_structs) \
441 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
443 #define image_g_new0(image,struct_type, n_structs) \
444 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
448 alloc_table (MonoDynamicTable *table, guint nrows)
450 MONO_REQ_GC_NEUTRAL_MODE;
453 g_assert (table->columns);
454 if (nrows + 1 >= table->alloc_rows) {
455 while (nrows + 1 >= table->alloc_rows) {
456 if (table->alloc_rows == 0)
457 table->alloc_rows = 16;
459 table->alloc_rows *= 2;
462 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
467 make_room_in_stream (MonoDynamicStream *stream, int size)
469 MONO_REQ_GC_NEUTRAL_MODE;
471 if (size <= stream->alloc_size)
474 while (stream->alloc_size <= size) {
475 if (stream->alloc_size < 4096)
476 stream->alloc_size = 4096;
478 stream->alloc_size *= 2;
481 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
487 MONO_REQ_GC_NEUTRAL_MODE;
491 gpointer oldkey, oldval;
493 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494 return GPOINTER_TO_UINT (oldval);
496 len = strlen (str) + 1;
499 make_room_in_stream (sh, idx + len);
502 * We strdup the string even if we already copy them in sh->data
503 * so that the string pointers in the hash remain valid even if
504 * we need to realloc sh->data. We may want to avoid that later.
506 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507 memcpy (sh->data + idx, str, len);
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
515 MONO_REQ_GC_UNSAFE_MODE;
517 char *name = mono_string_to_utf8 (str);
519 idx = string_heap_insert (sh, name);
524 #ifndef DISABLE_REFLECTION_EMIT
526 string_heap_init (MonoDynamicStream *sh)
528 MONO_REQ_GC_NEUTRAL_MODE;
531 sh->alloc_size = 4096;
532 sh->data = (char *)g_malloc (4096);
533 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534 string_heap_insert (sh, "");
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
541 MONO_REQ_GC_NEUTRAL_MODE;
545 make_room_in_stream (stream, stream->index + len);
546 memcpy (stream->data + stream->index, data, len);
548 stream->index += len;
550 * align index? Not without adding an additional param that controls it since
551 * we may store a blob value in pieces.
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
559 MONO_REQ_GC_NEUTRAL_MODE;
563 make_room_in_stream (stream, stream->index + len);
564 memset (stream->data + stream->index, 0, len);
566 stream->index += len;
571 stream_data_align (MonoDynamicStream *stream)
573 MONO_REQ_GC_NEUTRAL_MODE;
576 guint32 count = stream->index % 4;
578 /* we assume the stream data will be aligned */
580 mono_image_add_stream_data (stream, buf, 4 - count);
583 #ifndef DISABLE_REFLECTION_EMIT
585 mono_blob_entry_hash (const char* str)
587 MONO_REQ_GC_NEUTRAL_MODE;
591 len = mono_metadata_decode_blob_size (str, &str);
595 for (str += 1; str < end; str++)
596 h = (h << 5) - h + *str;
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605 MONO_REQ_GC_NEUTRAL_MODE;
610 len = mono_metadata_decode_blob_size (str1, &end1);
611 len2 = mono_metadata_decode_blob_size (str2, &end2);
614 return memcmp (end1, end2, len) == 0;
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
620 MONO_REQ_GC_NEUTRAL_MODE;
624 gpointer oldkey, oldval;
626 copy = (char *)g_malloc (s1+s2);
627 memcpy (copy, b1, s1);
628 memcpy (copy + s1, b2, s2);
629 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
631 idx = GPOINTER_TO_UINT (oldval);
633 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634 mono_image_add_stream_data (&assembly->blob, b2, s2);
635 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
643 MONO_REQ_GC_NEUTRAL_MODE;
647 guint32 size = buf->p - buf->buf;
649 g_assert (size <= (buf->end - buf->buf));
650 mono_metadata_encode_value (size, b, &b);
651 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
655 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656 * dest may be misaligned.
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660 MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
664 for (elem = 0; elem < nelem; ++elem) {
690 g_assert_not_reached ();
696 memcpy (dest, val, len * nelem);
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
703 MONO_REQ_GC_UNSAFE_MODE;
707 guint32 idx = 0, len;
709 len = str->length * 2;
710 mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
713 char *swapped = g_malloc (2 * mono_string_length (str));
714 const char *p = (const char*)mono_string_chars (str);
716 swap_with_size (swapped, p, 2, mono_string_length (str));
717 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
726 #ifndef DISABLE_REFLECTION_EMIT
728 default_class_from_mono_type (MonoType *type)
730 MONO_REQ_GC_NEUTRAL_MODE;
732 switch (type->type) {
733 case MONO_TYPE_OBJECT:
734 return mono_defaults.object_class;
736 return mono_defaults.void_class;
737 case MONO_TYPE_BOOLEAN:
738 return mono_defaults.boolean_class;
740 return mono_defaults.char_class;
742 return mono_defaults.sbyte_class;
744 return mono_defaults.byte_class;
746 return mono_defaults.int16_class;
748 return mono_defaults.uint16_class;
750 return mono_defaults.int32_class;
752 return mono_defaults.uint32_class;
754 return mono_defaults.int_class;
756 return mono_defaults.uint_class;
758 return mono_defaults.int64_class;
760 return mono_defaults.uint64_class;
762 return mono_defaults.single_class;
764 return mono_defaults.double_class;
765 case MONO_TYPE_STRING:
766 return mono_defaults.string_class;
768 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769 g_assert_not_reached ();
777 * mono_class_get_ref_info:
779 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
782 mono_class_get_ref_info (MonoClass *klass)
784 MONO_REQ_GC_UNSAFE_MODE;
786 if (klass->ref_info_handle == 0)
789 return mono_gchandle_get_target (klass->ref_info_handle);
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
795 MONO_REQ_GC_UNSAFE_MODE;
797 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798 g_assert (klass->ref_info_handle != 0);
802 mono_class_free_ref_info (MonoClass *klass)
804 MONO_REQ_GC_NEUTRAL_MODE;
806 if (klass->ref_info_handle) {
807 mono_gchandle_free (klass->ref_info_handle);
808 klass->ref_info_handle = 0;
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
815 MONO_REQ_GC_NEUTRAL_MODE;
818 MonoGenericInst *class_inst;
823 class_inst = gclass->context.class_inst;
825 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826 klass = gclass->container_class;
827 sigbuffer_add_value (buf, klass->byval_arg.type);
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
830 sigbuffer_add_value (buf, class_inst->type_argc);
831 for (i = 0; i < class_inst->type_argc; ++i)
832 encode_type (assembly, class_inst->type_argv [i], buf);
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
839 MONO_REQ_GC_NEUTRAL_MODE;
842 g_assert_not_reached ();
847 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
851 case MONO_TYPE_BOOLEAN:
865 case MONO_TYPE_STRING:
866 case MONO_TYPE_OBJECT:
867 case MONO_TYPE_TYPEDBYREF:
868 sigbuffer_add_value (buf, type->type);
871 sigbuffer_add_value (buf, type->type);
872 encode_type (assembly, type->data.type, buf);
874 case MONO_TYPE_SZARRAY:
875 sigbuffer_add_value (buf, type->type);
876 encode_type (assembly, &type->data.klass->byval_arg, buf);
878 case MONO_TYPE_VALUETYPE:
879 case MONO_TYPE_CLASS: {
880 MonoClass *k = mono_class_from_mono_type (type);
882 if (k->generic_container) {
883 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884 encode_generic_class (assembly, gclass, buf);
887 * Make sure we use the correct type.
889 sigbuffer_add_value (buf, k->byval_arg.type);
891 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892 * otherwise two typerefs could point to the same type, leading to
893 * verification errors.
895 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
899 case MONO_TYPE_ARRAY:
900 sigbuffer_add_value (buf, type->type);
901 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902 sigbuffer_add_value (buf, type->data.array->rank);
903 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904 sigbuffer_add_value (buf, 0);
906 case MONO_TYPE_GENERICINST:
907 encode_generic_class (assembly, type->data.generic_class, buf);
911 sigbuffer_add_value (buf, type->type);
912 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
915 g_error ("need to encode type %x", type->type);
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
922 MONO_REQ_GC_UNSAFE_MODE;
927 sigbuffer_add_value (buf, MONO_TYPE_VOID);
931 MonoType *t = mono_reflection_type_get_handle (type, &error);
932 mono_error_raise_exception (&error); /* FIXME don't raise ehre */
933 encode_type (assembly, t, buf);
937 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
939 MONO_REQ_GC_UNSAFE_MODE;
945 for (i = 0; i < mono_array_length (modreq); ++i) {
946 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
947 mono_error_raise_exception (&error); /* FIXME don't raise here */
948 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
949 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
953 for (i = 0; i < mono_array_length (modopt); ++i) {
954 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
955 mono_error_raise_exception (&error); /* FIXME don't raise here */
956 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
957 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
962 #ifndef DISABLE_REFLECTION_EMIT
964 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
966 MONO_REQ_GC_UNSAFE_MODE;
970 guint32 nparams = sig->param_count;
976 sigbuffer_init (&buf, 32);
978 * FIXME: vararg, explicit_this, differenc call_conv values...
980 idx = sig->call_convention;
982 idx |= 0x20; /* hasthis */
983 if (sig->generic_param_count)
984 idx |= 0x10; /* generic */
985 sigbuffer_add_byte (&buf, idx);
986 if (sig->generic_param_count)
987 sigbuffer_add_value (&buf, sig->generic_param_count);
988 sigbuffer_add_value (&buf, nparams);
989 encode_type (assembly, sig->ret, &buf);
990 for (i = 0; i < nparams; ++i) {
991 if (i == sig->sentinelpos)
992 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
993 encode_type (assembly, sig->params [i], &buf);
995 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
996 sigbuffer_free (&buf);
1002 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1004 MONO_REQ_GC_UNSAFE_MODE;
1007 * FIXME: reuse code from method_encode_signature().
1011 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1012 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1013 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1016 sigbuffer_init (&buf, 32);
1017 /* LAMESPEC: all the call conv spec is foobared */
1018 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1019 if (mb->call_conv & 2)
1020 idx |= 0x5; /* vararg */
1021 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1022 idx |= 0x20; /* hasthis */
1024 idx |= 0x10; /* generic */
1025 sigbuffer_add_byte (&buf, idx);
1027 sigbuffer_add_value (&buf, ngparams);
1028 sigbuffer_add_value (&buf, nparams + notypes);
1029 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1030 encode_reflection_type (assembly, mb->rtype, &buf);
1031 for (i = 0; i < nparams; ++i) {
1032 MonoArray *modreq = NULL;
1033 MonoArray *modopt = NULL;
1034 MonoReflectionType *pt;
1036 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1037 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1038 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1039 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1040 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1041 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1042 encode_reflection_type (assembly, pt, &buf);
1045 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1046 for (i = 0; i < notypes; ++i) {
1047 MonoReflectionType *pt;
1049 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1050 encode_reflection_type (assembly, pt, &buf);
1053 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054 sigbuffer_free (&buf);
1059 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1061 MONO_REQ_GC_UNSAFE_MODE;
1063 MonoDynamicTable *table;
1065 guint32 idx, sig_idx;
1066 guint nl = mono_array_length (ilgen->locals);
1070 sigbuffer_init (&buf, 32);
1071 sigbuffer_add_value (&buf, 0x07);
1072 sigbuffer_add_value (&buf, nl);
1073 for (i = 0; i < nl; ++i) {
1074 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1077 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1079 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1081 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1082 sigbuffer_free (&buf);
1084 if (assembly->standalonesig_cache == NULL)
1085 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1086 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1090 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1091 idx = table->next_idx ++;
1093 alloc_table (table, table->rows);
1094 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1096 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1098 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1104 method_count_clauses (MonoReflectionILGen *ilgen)
1106 MONO_REQ_GC_UNSAFE_MODE;
1108 guint32 num_clauses = 0;
1111 MonoILExceptionInfo *ex_info;
1112 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1113 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1114 if (ex_info->handlers)
1115 num_clauses += mono_array_length (ex_info->handlers);
1123 #ifndef DISABLE_REFLECTION_EMIT
1124 static MonoExceptionClause*
1125 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1127 MONO_REQ_GC_UNSAFE_MODE;
1130 MonoExceptionClause *clauses;
1131 MonoExceptionClause *clause;
1132 MonoILExceptionInfo *ex_info;
1133 MonoILExceptionBlock *ex_block;
1134 guint32 finally_start;
1135 int i, j, clause_index;;
1137 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1140 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1141 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1142 finally_start = ex_info->start + ex_info->len;
1143 if (!ex_info->handlers)
1145 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1146 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1147 clause = &(clauses [clause_index]);
1149 clause->flags = ex_block->type;
1150 clause->try_offset = ex_info->start;
1152 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1153 clause->try_len = finally_start - ex_info->start;
1155 clause->try_len = ex_info->len;
1156 clause->handler_offset = ex_block->start;
1157 clause->handler_len = ex_block->len;
1158 if (ex_block->extype) {
1159 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, &error);
1160 mono_error_raise_exception (&error); /* FIXME don't raise here */
1161 clause->data.catch_class = mono_class_from_mono_type (extype);
1163 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1164 clause->data.filter_offset = ex_block->filter_offset;
1166 clause->data.filter_offset = 0;
1168 finally_start = ex_block->start + ex_block->len;
1176 #endif /* !DISABLE_REFLECTION_EMIT */
1179 * method_encode_code:
1181 * @assembly the assembly
1182 * @mb the managed MethodBuilder
1183 * @error set on error
1185 * Note that the return value is not sensible if @error is set.
1188 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1190 MONO_REQ_GC_UNSAFE_MODE;
1195 gint32 max_stack, i;
1196 gint32 num_locals = 0;
1197 gint32 num_exception = 0;
1200 char fat_header [12];
1202 guint16 short_value;
1203 guint32 local_sig = 0;
1204 guint32 header_size = 12;
1207 mono_error_init (error);
1209 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1210 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1214 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1216 code = mb->ilgen->code;
1217 code_size = mb->ilgen->code_len;
1218 max_stack = mb->ilgen->max_stack;
1219 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1220 if (mb->ilgen->ex_handlers)
1221 num_exception = method_count_clauses (mb->ilgen);
1225 char *name = mono_string_to_utf8 (mb->name);
1226 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1227 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1233 code_size = mono_array_length (code);
1234 max_stack = 8; /* we probably need to run a verifier on the code... */
1237 stream_data_align (&assembly->code);
1239 /* check for exceptions, maxstack, locals */
1240 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1242 if (code_size < 64 && !(code_size & 1)) {
1243 flags = (code_size << 2) | 0x2;
1244 } else if (code_size < 32 && (code_size & 1)) {
1245 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1249 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1250 /* add to the fixup todo list */
1251 if (mb->ilgen && mb->ilgen->num_token_fixups)
1252 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1253 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1254 return assembly->text_rva + idx;
1258 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1260 * FIXME: need to set also the header size in fat_flags.
1261 * (and more sects and init locals flags)
1265 fat_flags |= METHOD_HEADER_MORE_SECTS;
1266 if (mb->init_locals)
1267 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1268 fat_header [0] = fat_flags;
1269 fat_header [1] = (header_size / 4 ) << 4;
1270 short_value = GUINT16_TO_LE (max_stack);
1271 memcpy (fat_header + 2, &short_value, 2);
1272 int_value = GUINT32_TO_LE (code_size);
1273 memcpy (fat_header + 4, &int_value, 4);
1274 int_value = GUINT32_TO_LE (local_sig);
1275 memcpy (fat_header + 8, &int_value, 4);
1276 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1277 /* add to the fixup todo list */
1278 if (mb->ilgen && mb->ilgen->num_token_fixups)
1279 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1281 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1282 if (num_exception) {
1283 unsigned char sheader [4];
1284 MonoILExceptionInfo * ex_info;
1285 MonoILExceptionBlock * ex_block;
1288 stream_data_align (&assembly->code);
1289 /* always use fat format for now */
1290 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1291 num_exception *= 6 * sizeof (guint32);
1292 num_exception += 4; /* include the size of the header */
1293 sheader [1] = num_exception & 0xff;
1294 sheader [2] = (num_exception >> 8) & 0xff;
1295 sheader [3] = (num_exception >> 16) & 0xff;
1296 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1297 /* fat header, so we are already aligned */
1299 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1300 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1301 if (ex_info->handlers) {
1302 int finally_start = ex_info->start + ex_info->len;
1303 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1305 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1307 val = GUINT32_TO_LE (ex_block->type);
1308 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1310 val = GUINT32_TO_LE (ex_info->start);
1311 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1312 /* need fault, too, probably */
1313 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1314 val = GUINT32_TO_LE (finally_start - ex_info->start);
1316 val = GUINT32_TO_LE (ex_info->len);
1317 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1318 /* handler offset */
1319 val = GUINT32_TO_LE (ex_block->start);
1320 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1322 val = GUINT32_TO_LE (ex_block->len);
1323 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1324 finally_start = ex_block->start + ex_block->len;
1325 if (ex_block->extype) {
1326 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1327 return_val_if_nok (error, 0);
1329 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1331 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1332 val = ex_block->filter_offset;
1336 val = GUINT32_TO_LE (val);
1337 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1338 /*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",
1339 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);*/
1342 g_error ("No clauses for ex info block %d", i);
1346 return assembly->text_rva + idx;
1350 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1352 MONO_REQ_GC_NEUTRAL_MODE;
1355 MonoDynamicTable *table;
1358 table = &assembly->tables [table_idx];
1360 g_assert (col < table->columns);
1362 values = table->values + table->columns;
1363 for (i = 1; i <= table->rows; ++i) {
1364 if (values [col] == token)
1366 values += table->columns;
1372 * LOCKING: Acquires the loader lock.
1374 static MonoCustomAttrInfo*
1375 lookup_custom_attr (MonoImage *image, gpointer member)
1377 MONO_REQ_GC_NEUTRAL_MODE;
1379 MonoCustomAttrInfo* res;
1381 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1386 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1392 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1394 MONO_REQ_GC_UNSAFE_MODE;
1396 /* FIXME: Need to do more checks */
1397 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1398 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1400 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1407 static MonoCustomAttrInfo*
1408 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1410 MONO_REQ_GC_UNSAFE_MODE;
1412 int i, index, count, not_visible;
1413 MonoCustomAttrInfo *ainfo;
1414 MonoReflectionCustomAttr *cattr;
1418 /* FIXME: check in assembly the Run flag is set */
1420 count = mono_array_length (cattrs);
1422 /* Skip nonpublic attributes since MS.NET seems to do the same */
1423 /* FIXME: This needs to be done more globally */
1425 for (i = 0; i < count; ++i) {
1426 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427 if (!custom_attr_visible (image, cattr))
1430 count -= not_visible;
1432 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1434 ainfo->image = image;
1435 ainfo->num_attrs = count;
1436 ainfo->cached = alloc_img != NULL;
1438 for (i = 0; i < count; ++i) {
1439 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1440 if (custom_attr_visible (image, cattr)) {
1441 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1442 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1443 ainfo->attrs [index].ctor = cattr->ctor->method;
1444 ainfo->attrs [index].data = saved;
1445 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1453 #ifndef DISABLE_REFLECTION_EMIT
1455 * LOCKING: Acquires the loader lock.
1458 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1460 MONO_REQ_GC_UNSAFE_MODE;
1462 MonoCustomAttrInfo *ainfo, *tmp;
1464 if (!cattrs || !mono_array_length (cattrs))
1467 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1469 mono_loader_lock ();
1470 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1472 mono_custom_attrs_free (tmp);
1473 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1474 mono_loader_unlock ();
1480 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1482 MONO_REQ_GC_NEUTRAL_MODE;
1484 if (ainfo && !ainfo->cached)
1489 * idx is the table index of the object
1490 * type is one of MONO_CUSTOM_ATTR_*
1493 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1495 MONO_REQ_GC_UNSAFE_MODE;
1497 MonoDynamicTable *table;
1498 MonoReflectionCustomAttr *cattr;
1500 guint32 count, i, token;
1502 char *p = blob_size;
1504 mono_error_init (error);
1506 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1509 count = mono_array_length (cattrs);
1510 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1511 table->rows += count;
1512 alloc_table (table, table->rows);
1513 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1514 idx <<= MONO_CUSTOM_ATTR_BITS;
1516 for (i = 0; i < count; ++i) {
1517 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1518 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1519 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1520 if (!mono_error_ok (error)) goto fail;
1521 type = mono_metadata_token_index (token);
1522 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1523 switch (mono_metadata_token_table (token)) {
1524 case MONO_TABLE_METHOD:
1525 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1527 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1528 * method, not the one returned by mono_image_create_token ().
1530 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1532 case MONO_TABLE_MEMBERREF:
1533 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1536 g_warning ("got wrong token in custom attr");
1539 values [MONO_CUSTOM_ATTR_TYPE] = type;
1541 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1542 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1543 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1544 values += MONO_CUSTOM_ATTR_SIZE;
1555 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1557 MONO_REQ_GC_UNSAFE_MODE;
1559 MonoDynamicTable *table;
1561 guint32 count, i, idx;
1562 MonoReflectionPermissionSet *perm;
1567 count = mono_array_length (permissions);
1568 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1569 table->rows += count;
1570 alloc_table (table, table->rows);
1572 for (i = 0; i < mono_array_length (permissions); ++i) {
1573 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1575 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1577 idx = mono_metadata_token_index (parent_token);
1578 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1579 switch (mono_metadata_token_table (parent_token)) {
1580 case MONO_TABLE_TYPEDEF:
1581 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1583 case MONO_TABLE_METHOD:
1584 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1586 case MONO_TABLE_ASSEMBLY:
1587 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1590 g_assert_not_reached ();
1593 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1594 values [MONO_DECL_SECURITY_PARENT] = idx;
1595 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1602 * Fill in the MethodDef and ParamDef tables for a method.
1603 * This is used for both normal methods and constructors.
1606 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1608 MONO_REQ_GC_UNSAFE_MODE;
1610 MonoDynamicTable *table;
1614 mono_error_init (error);
1616 /* room in this table is already allocated */
1617 table = &assembly->tables [MONO_TABLE_METHOD];
1618 *mb->table_idx = table->next_idx ++;
1619 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1620 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1621 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1622 values [MONO_METHOD_FLAGS] = mb->attrs;
1623 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1624 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1625 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1626 if (!mono_error_ok (error))
1629 table = &assembly->tables [MONO_TABLE_PARAM];
1630 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1632 mono_image_add_decl_security (assembly,
1633 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1636 MonoDynamicTable *mtable;
1639 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1640 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1643 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1644 if (mono_array_get (mb->pinfo, gpointer, i))
1647 table->rows += count;
1648 alloc_table (table, table->rows);
1649 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1650 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1651 MonoReflectionParamBuilder *pb;
1652 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1653 values [MONO_PARAM_FLAGS] = pb->attrs;
1654 values [MONO_PARAM_SEQUENCE] = i;
1655 if (pb->name != NULL) {
1656 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1658 values [MONO_PARAM_NAME] = 0;
1660 values += MONO_PARAM_SIZE;
1661 if (pb->marshal_info) {
1663 alloc_table (mtable, mtable->rows);
1664 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1665 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1666 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1668 pb->table_idx = table->next_idx++;
1669 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1670 guint32 field_type = 0;
1671 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1673 alloc_table (mtable, mtable->rows);
1674 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1675 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1676 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1677 mvalues [MONO_CONSTANT_TYPE] = field_type;
1678 mvalues [MONO_CONSTANT_PADDING] = 0;
1687 #ifndef DISABLE_REFLECTION_EMIT
1689 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1691 MONO_REQ_GC_UNSAFE_MODE;
1693 mono_error_init (error);
1694 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1696 rmb->ilgen = mb->ilgen;
1697 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1698 return_val_if_nok (error, FALSE);
1699 rmb->parameters = mb->parameters;
1700 rmb->generic_params = mb->generic_params;
1701 rmb->generic_container = mb->generic_container;
1702 rmb->opt_types = NULL;
1703 rmb->pinfo = mb->pinfo;
1704 rmb->attrs = mb->attrs;
1705 rmb->iattrs = mb->iattrs;
1706 rmb->call_conv = mb->call_conv;
1707 rmb->code = mb->code;
1708 rmb->type = mb->type;
1709 rmb->name = mb->name;
1710 rmb->table_idx = &mb->table_idx;
1711 rmb->init_locals = mb->init_locals;
1712 rmb->skip_visibility = FALSE;
1713 rmb->return_modreq = mb->return_modreq;
1714 rmb->return_modopt = mb->return_modopt;
1715 rmb->param_modreq = mb->param_modreq;
1716 rmb->param_modopt = mb->param_modopt;
1717 rmb->permissions = mb->permissions;
1718 rmb->mhandle = mb->mhandle;
1723 rmb->charset = mb->charset;
1724 rmb->extra_flags = mb->extra_flags;
1725 rmb->native_cc = mb->native_cc;
1726 rmb->dllentry = mb->dllentry;
1734 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1736 MONO_REQ_GC_UNSAFE_MODE;
1738 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1740 mono_error_init (error);
1742 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1744 rmb->ilgen = mb->ilgen;
1745 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1746 return_val_if_nok (error, FALSE);
1747 rmb->parameters = mb->parameters;
1748 rmb->generic_params = NULL;
1749 rmb->generic_container = NULL;
1750 rmb->opt_types = NULL;
1751 rmb->pinfo = mb->pinfo;
1752 rmb->attrs = mb->attrs;
1753 rmb->iattrs = mb->iattrs;
1754 rmb->call_conv = mb->call_conv;
1756 rmb->type = mb->type;
1757 rmb->name = mono_string_new (mono_domain_get (), name);
1758 rmb->table_idx = &mb->table_idx;
1759 rmb->init_locals = mb->init_locals;
1760 rmb->skip_visibility = FALSE;
1761 rmb->return_modreq = NULL;
1762 rmb->return_modopt = NULL;
1763 rmb->param_modreq = mb->param_modreq;
1764 rmb->param_modopt = mb->param_modopt;
1765 rmb->permissions = mb->permissions;
1766 rmb->mhandle = mb->mhandle;
1774 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1776 MONO_REQ_GC_UNSAFE_MODE;
1778 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1780 rmb->ilgen = mb->ilgen;
1781 rmb->rtype = mb->rtype;
1782 rmb->parameters = mb->parameters;
1783 rmb->generic_params = NULL;
1784 rmb->generic_container = NULL;
1785 rmb->opt_types = NULL;
1787 rmb->attrs = mb->attrs;
1789 rmb->call_conv = mb->call_conv;
1791 rmb->type = (MonoObject *) mb->owner;
1792 rmb->name = mb->name;
1793 rmb->table_idx = NULL;
1794 rmb->init_locals = mb->init_locals;
1795 rmb->skip_visibility = mb->skip_visibility;
1796 rmb->return_modreq = NULL;
1797 rmb->return_modopt = NULL;
1798 rmb->param_modreq = NULL;
1799 rmb->param_modopt = NULL;
1800 rmb->permissions = NULL;
1801 rmb->mhandle = mb->mhandle;
1808 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1810 MONO_REQ_GC_UNSAFE_MODE;
1812 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1813 MonoDynamicTable *table;
1816 MonoReflectionMethod *m;
1819 mono_error_init (error);
1821 if (!mb->override_methods)
1824 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1825 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1827 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1829 alloc_table (table, table->rows);
1830 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1831 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1832 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1834 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1835 return_val_if_nok (error, FALSE);
1837 switch (mono_metadata_token_table (tok)) {
1838 case MONO_TABLE_MEMBERREF:
1839 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1841 case MONO_TABLE_METHOD:
1842 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1845 g_assert_not_reached ();
1847 values [MONO_METHODIMPL_DECLARATION] = tok;
1853 #ifndef DISABLE_REFLECTION_EMIT
1855 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1857 MONO_REQ_GC_UNSAFE_MODE;
1859 MonoDynamicTable *table;
1861 ReflectionMethodBuilder rmb;
1864 mono_error_init (error);
1866 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1867 !mono_image_basic_method (&rmb, assembly, error))
1870 mb->table_idx = *rmb.table_idx;
1872 if (mb->dll) { /* It's a P/Invoke method */
1874 /* map CharSet values to on-disk values */
1875 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1876 int extra_flags = mb->extra_flags;
1877 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1879 alloc_table (table, table->rows);
1880 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1882 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1883 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1885 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1887 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1888 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1889 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1890 table = &assembly->tables [MONO_TABLE_MODULEREF];
1892 alloc_table (table, table->rows);
1893 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1894 values [MONO_IMPLMAP_SCOPE] = table->rows;
1898 if (mb->generic_params) {
1899 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1900 table->rows += mono_array_length (mb->generic_params);
1901 alloc_table (table, table->rows);
1902 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1903 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1905 mono_image_get_generic_param_info (
1906 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1914 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1916 MONO_REQ_GC_UNSAFE_MODE;
1918 ReflectionMethodBuilder rmb;
1920 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1923 if (!mono_image_basic_method (&rmb, assembly, error))
1926 mb->table_idx = *rmb.table_idx;
1933 type_get_fully_qualified_name (MonoType *type)
1935 MONO_REQ_GC_NEUTRAL_MODE;
1937 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1941 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1943 MONO_REQ_GC_UNSAFE_MODE;
1948 klass = mono_class_from_mono_type (type);
1950 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1951 ta = klass->image->assembly;
1952 if (assembly_is_dynamic (ta) || (ta == ass)) {
1953 if (klass->generic_class || klass->generic_container)
1954 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1955 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1957 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1960 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1963 #ifndef DISABLE_REFLECTION_EMIT
1964 /*field_image is the image to which the eventual custom mods have been encoded against*/
1966 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1968 MONO_REQ_GC_NEUTRAL_MODE;
1971 guint32 idx, i, token;
1973 if (!assembly->save)
1976 sigbuffer_init (&buf, 32);
1978 sigbuffer_add_value (&buf, 0x06);
1979 /* encode custom attributes before the type */
1980 if (type->num_mods) {
1981 for (i = 0; i < type->num_mods; ++i) {
1984 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1985 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1987 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1989 token = type->modifiers [i].token;
1992 if (type->modifiers [i].required)
1993 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1995 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1997 sigbuffer_add_value (&buf, token);
2000 encode_type (assembly, type, &buf);
2001 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2002 sigbuffer_free (&buf);
2008 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2010 MONO_REQ_GC_UNSAFE_MODE;
2015 guint32 typespec = 0;
2019 init_type_builder_generics (fb->type);
2021 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
2022 mono_error_raise_exception (&error); /* FIXME don't raise here */
2023 klass = mono_class_from_mono_type (type);
2025 sigbuffer_init (&buf, 32);
2027 sigbuffer_add_value (&buf, 0x06);
2028 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2029 /* encode custom attributes before the type */
2031 if (klass->generic_container)
2032 typespec = create_typespec (assembly, type);
2035 MonoGenericClass *gclass;
2036 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2037 encode_generic_class (assembly, gclass, &buf);
2039 encode_type (assembly, type, &buf);
2041 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2042 sigbuffer_free (&buf);
2047 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2049 MONO_REQ_GC_UNSAFE_MODE;
2051 char blob_size [64];
2052 char *b = blob_size;
2055 guint32 idx = 0, len = 0, dummy = 0;
2057 buf = (char *)g_malloc (64);
2059 *ret_type = MONO_TYPE_CLASS;
2061 box_val = (char*)&dummy;
2063 box_val = ((char*)val) + sizeof (MonoObject);
2064 *ret_type = val->vtable->klass->byval_arg.type;
2067 switch (*ret_type) {
2068 case MONO_TYPE_BOOLEAN:
2073 case MONO_TYPE_CHAR:
2090 case MONO_TYPE_VALUETYPE: {
2091 MonoClass *klass = val->vtable->klass;
2093 if (klass->enumtype) {
2094 *ret_type = mono_class_enum_basetype (klass)->type;
2096 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2099 g_error ("we can't encode valuetypes, we should have never reached this line");
2102 case MONO_TYPE_CLASS:
2104 case MONO_TYPE_STRING: {
2105 MonoString *str = (MonoString*)val;
2106 /* there is no signature */
2107 len = str->length * 2;
2108 mono_metadata_encode_value (len, b, &b);
2109 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2111 char *swapped = g_malloc (2 * mono_string_length (str));
2112 const char *p = (const char*)mono_string_chars (str);
2114 swap_with_size (swapped, p, 2, mono_string_length (str));
2115 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2119 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2125 case MONO_TYPE_GENERICINST:
2126 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2129 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2132 /* there is no signature */
2133 mono_metadata_encode_value (len, b, &b);
2134 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2135 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2136 swap_with_size (blob_size, box_val, len, 1);
2137 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2139 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2147 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2149 MONO_REQ_GC_UNSAFE_MODE;
2156 sigbuffer_init (&buf, 32);
2158 sigbuffer_add_value (&buf, minfo->type);
2160 switch (minfo->type) {
2161 case MONO_NATIVE_BYVALTSTR:
2162 case MONO_NATIVE_BYVALARRAY:
2163 sigbuffer_add_value (&buf, minfo->count);
2165 case MONO_NATIVE_LPARRAY:
2166 if (minfo->eltype || minfo->has_size) {
2167 sigbuffer_add_value (&buf, minfo->eltype);
2168 if (minfo->has_size) {
2169 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2170 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2172 /* LAMESPEC: ElemMult is undocumented */
2173 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2177 case MONO_NATIVE_SAFEARRAY:
2179 sigbuffer_add_value (&buf, minfo->eltype);
2181 case MONO_NATIVE_CUSTOM:
2183 str = mono_string_to_utf8 (minfo->guid);
2185 sigbuffer_add_value (&buf, len);
2186 sigbuffer_add_mem (&buf, str, len);
2189 sigbuffer_add_value (&buf, 0);
2191 /* native type name */
2192 sigbuffer_add_value (&buf, 0);
2193 /* custom marshaler type name */
2194 if (minfo->marshaltype || minfo->marshaltyperef) {
2195 if (minfo->marshaltyperef) {
2196 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
2197 mono_error_raise_exception (&error); /* FIXME don't raise here */
2198 str = type_get_fully_qualified_name (marshaltype);
2200 str = mono_string_to_utf8 (minfo->marshaltype);
2202 sigbuffer_add_value (&buf, len);
2203 sigbuffer_add_mem (&buf, str, len);
2206 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2207 sigbuffer_add_value (&buf, 0);
2209 if (minfo->mcookie) {
2210 str = mono_string_to_utf8 (minfo->mcookie);
2212 sigbuffer_add_value (&buf, len);
2213 sigbuffer_add_mem (&buf, str, len);
2216 sigbuffer_add_value (&buf, 0);
2222 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2223 sigbuffer_free (&buf);
2228 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2230 MONO_REQ_GC_UNSAFE_MODE;
2232 MonoDynamicTable *table;
2235 /* maybe this fixup should be done in the C# code */
2236 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2237 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2238 table = &assembly->tables [MONO_TABLE_FIELD];
2239 fb->table_idx = table->next_idx ++;
2240 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2241 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2242 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2243 values [MONO_FIELD_FLAGS] = fb->attrs;
2244 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2246 if (fb->offset != -1) {
2247 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2249 alloc_table (table, table->rows);
2250 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2251 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2252 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2254 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2255 MonoTypeEnum field_type = (MonoTypeEnum)0;
2256 table = &assembly->tables [MONO_TABLE_CONSTANT];
2258 alloc_table (table, table->rows);
2259 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2260 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2261 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2262 values [MONO_CONSTANT_TYPE] = field_type;
2263 values [MONO_CONSTANT_PADDING] = 0;
2265 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2267 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2269 alloc_table (table, table->rows);
2270 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2271 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2273 * We store it in the code section because it's simpler for now.
2276 if (mono_array_length (fb->rva_data) >= 10)
2277 stream_data_align (&assembly->code);
2278 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2280 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2281 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2283 if (fb->marshal_info) {
2284 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2286 alloc_table (table, table->rows);
2287 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2288 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2289 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2294 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2296 MONO_REQ_GC_UNSAFE_MODE;
2299 guint32 nparams = 0;
2300 MonoReflectionMethodBuilder *mb = fb->get_method;
2301 MonoReflectionMethodBuilder *smb = fb->set_method;
2304 if (mb && mb->parameters)
2305 nparams = mono_array_length (mb->parameters);
2306 if (!mb && smb && smb->parameters)
2307 nparams = mono_array_length (smb->parameters) - 1;
2308 sigbuffer_init (&buf, 32);
2309 if (fb->call_conv & 0x20)
2310 sigbuffer_add_byte (&buf, 0x28);
2312 sigbuffer_add_byte (&buf, 0x08);
2313 sigbuffer_add_value (&buf, nparams);
2315 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2316 for (i = 0; i < nparams; ++i) {
2317 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2318 encode_reflection_type (assembly, pt, &buf);
2320 } else if (smb && smb->parameters) {
2321 /* the property type is the last param */
2322 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2323 for (i = 0; i < nparams; ++i) {
2324 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2325 encode_reflection_type (assembly, pt, &buf);
2328 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2331 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2332 sigbuffer_free (&buf);
2337 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2339 MONO_REQ_GC_UNSAFE_MODE;
2341 MonoDynamicTable *table;
2343 guint num_methods = 0;
2347 * we need to set things in the following tables:
2348 * PROPERTYMAP (info already filled in _get_type_info ())
2349 * PROPERTY (rows already preallocated in _get_type_info ())
2350 * METHOD (method info already done with the generic method code)
2354 table = &assembly->tables [MONO_TABLE_PROPERTY];
2355 pb->table_idx = table->next_idx ++;
2356 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2357 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2358 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2359 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2361 /* FIXME: we still don't handle 'other' methods */
2362 if (pb->get_method) num_methods ++;
2363 if (pb->set_method) num_methods ++;
2365 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2366 table->rows += num_methods;
2367 alloc_table (table, table->rows);
2369 if (pb->get_method) {
2370 semaidx = table->next_idx ++;
2371 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2372 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2373 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2374 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2376 if (pb->set_method) {
2377 semaidx = table->next_idx ++;
2378 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2379 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2380 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2381 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2383 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2384 MonoTypeEnum field_type = (MonoTypeEnum)0;
2385 table = &assembly->tables [MONO_TABLE_CONSTANT];
2387 alloc_table (table, table->rows);
2388 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2389 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2390 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2391 values [MONO_CONSTANT_TYPE] = field_type;
2392 values [MONO_CONSTANT_PADDING] = 0;
2397 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2399 MONO_REQ_GC_UNSAFE_MODE;
2402 MonoDynamicTable *table;
2404 guint num_methods = 0;
2408 * we need to set things in the following tables:
2409 * EVENTMAP (info already filled in _get_type_info ())
2410 * EVENT (rows already preallocated in _get_type_info ())
2411 * METHOD (method info already done with the generic method code)
2414 table = &assembly->tables [MONO_TABLE_EVENT];
2415 eb->table_idx = table->next_idx ++;
2416 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2417 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2418 values [MONO_EVENT_FLAGS] = eb->attrs;
2419 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2420 mono_error_raise_exception (&error); /* FIXME don't raise here */
2421 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2424 * FIXME: we still don't handle 'other' methods
2426 if (eb->add_method) num_methods ++;
2427 if (eb->remove_method) num_methods ++;
2428 if (eb->raise_method) num_methods ++;
2430 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2431 table->rows += num_methods;
2432 alloc_table (table, table->rows);
2434 if (eb->add_method) {
2435 semaidx = table->next_idx ++;
2436 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2437 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2438 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2439 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2441 if (eb->remove_method) {
2442 semaidx = table->next_idx ++;
2443 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2444 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2445 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2446 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2448 if (eb->raise_method) {
2449 semaidx = table->next_idx ++;
2450 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2452 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2453 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2458 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2460 MONO_REQ_GC_UNSAFE_MODE;
2463 MonoDynamicTable *table;
2464 guint32 num_constraints, i;
2468 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2469 num_constraints = gparam->iface_constraints ?
2470 mono_array_length (gparam->iface_constraints) : 0;
2471 table->rows += num_constraints;
2472 if (gparam->base_type)
2474 alloc_table (table, table->rows);
2476 if (gparam->base_type) {
2477 table_idx = table->next_idx ++;
2478 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2480 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, &error);
2481 mono_error_raise_exception (&error); /* FIXME don't raise here */
2482 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2483 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2486 for (i = 0; i < num_constraints; i++) {
2487 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2488 gparam->iface_constraints, gpointer, i);
2490 table_idx = table->next_idx ++;
2491 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2493 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, &error);
2494 mono_error_raise_exception (&error); /* FIXME don't raise here */
2496 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2497 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2502 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2504 MONO_REQ_GC_UNSAFE_MODE;
2506 GenericParamTableEntry *entry;
2509 * The GenericParam table must be sorted according to the `owner' field.
2510 * We need to do this sorting prior to writing the GenericParamConstraint
2511 * table, since we have to use the final GenericParam table indices there
2512 * and they must also be sorted.
2515 entry = g_new0 (GenericParamTableEntry, 1);
2516 entry->owner = owner;
2517 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2518 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2519 entry->gparam = gparam;
2521 g_ptr_array_add (assembly->gen_params, entry);
2525 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2527 MONO_REQ_GC_UNSAFE_MODE;
2529 MonoDynamicTable *table;
2530 MonoGenericParam *param;
2534 mono_error_init (error);
2536 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2537 table_idx = table->next_idx ++;
2538 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2540 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2541 return_val_if_nok (error, FALSE);
2543 param = gparam_type->data.generic_param;
2545 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2546 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2547 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2548 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2550 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2553 encode_constraints (entry->gparam, table_idx, assembly);
2559 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2561 MONO_REQ_GC_UNSAFE_MODE;
2563 MonoDynamicTable *table;
2566 guint32 cols [MONO_ASSEMBLY_SIZE];
2570 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2573 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2574 table = &assembly->tables [MONO_TABLE_MODULEREF];
2575 token = table->next_idx ++;
2577 alloc_table (table, table->rows);
2578 values = table->values + token * MONO_MODULEREF_SIZE;
2579 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2581 token <<= MONO_RESOLUTION_SCOPE_BITS;
2582 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2583 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2588 if (assembly_is_dynamic (image->assembly))
2590 memset (cols, 0, sizeof (cols));
2592 /* image->assembly->image is the manifest module */
2593 image = image->assembly->image;
2594 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2597 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2598 token = table->next_idx ++;
2600 alloc_table (table, table->rows);
2601 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2602 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2603 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2604 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2605 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2606 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2607 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2608 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2609 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2611 if (strcmp ("", image->assembly->aname.culture)) {
2612 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2613 image->assembly->aname.culture);
2616 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2617 guchar pubtoken [9];
2619 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2620 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2622 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2624 token <<= MONO_RESOLUTION_SCOPE_BITS;
2625 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2626 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2631 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2633 MONO_REQ_GC_NEUTRAL_MODE;
2635 MonoDynamicTable *table;
2640 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2643 sigbuffer_init (&buf, 32);
2644 switch (type->type) {
2645 case MONO_TYPE_FNPTR:
2647 case MONO_TYPE_SZARRAY:
2648 case MONO_TYPE_ARRAY:
2650 case MONO_TYPE_MVAR:
2651 case MONO_TYPE_GENERICINST:
2652 encode_type (assembly, type, &buf);
2654 case MONO_TYPE_CLASS:
2655 case MONO_TYPE_VALUETYPE: {
2656 MonoClass *k = mono_class_from_mono_type (type);
2657 if (!k || !k->generic_container) {
2658 sigbuffer_free (&buf);
2661 encode_type (assembly, type, &buf);
2665 sigbuffer_free (&buf);
2669 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2670 if (assembly->save) {
2671 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2672 alloc_table (table, table->rows + 1);
2673 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2674 values [MONO_TYPESPEC_SIGNATURE] = token;
2676 sigbuffer_free (&buf);
2678 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2679 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2685 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2687 MONO_REQ_GC_UNSAFE_MODE;
2689 MonoDynamicTable *table;
2691 guint32 token, scope, enclosing;
2694 /* if the type requires a typespec, we must try that first*/
2695 if (try_typespec && (token = create_typespec (assembly, type)))
2697 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2700 klass = mono_class_from_mono_type (type);
2702 klass = mono_class_from_mono_type (type);
2705 * If it's in the same module and not a generic type parameter:
2707 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2708 (type->type != MONO_TYPE_MVAR)) {
2709 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2710 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2711 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2715 if (klass->nested_in) {
2716 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2717 /* get the typeref idx of the enclosing type */
2718 enclosing >>= MONO_TYPEDEFORREF_BITS;
2719 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2721 scope = resolution_scope_from_image (assembly, klass->image);
2723 table = &assembly->tables [MONO_TABLE_TYPEREF];
2724 if (assembly->save) {
2725 alloc_table (table, table->rows + 1);
2726 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2727 values [MONO_TYPEREF_SCOPE] = scope;
2728 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2729 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2731 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2732 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2734 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2739 * Despite the name, we handle also TypeSpec (with the above helper).
2742 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2744 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2747 #ifndef DISABLE_REFLECTION_EMIT
2749 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2751 MONO_REQ_GC_NEUTRAL_MODE;
2753 MonoDynamicTable *table;
2755 guint32 token, pclass;
2757 switch (parent & MONO_TYPEDEFORREF_MASK) {
2758 case MONO_TYPEDEFORREF_TYPEREF:
2759 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2761 case MONO_TYPEDEFORREF_TYPESPEC:
2762 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2764 case MONO_TYPEDEFORREF_TYPEDEF:
2765 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2768 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2771 /* extract the index */
2772 parent >>= MONO_TYPEDEFORREF_BITS;
2774 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2776 if (assembly->save) {
2777 alloc_table (table, table->rows + 1);
2778 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2779 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2780 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2781 values [MONO_MEMBERREF_SIGNATURE] = sig;
2784 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2791 * Insert a memberef row into the metadata: the token that point to the memberref
2792 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2793 * mono_image_get_fieldref_token()).
2794 * The sig param is an index to an already built signature.
2797 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2799 MONO_REQ_GC_NEUTRAL_MODE;
2801 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2802 return mono_image_add_memberef_row (assembly, parent, name, sig);
2807 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2809 MONO_REQ_GC_NEUTRAL_MODE;
2812 MonoMethodSignature *sig;
2814 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2816 if (create_typespec) {
2817 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2822 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2823 if (token && !create_typespec)
2826 g_assert (!method->is_inflated);
2829 * A methodref signature can't contain an unmanaged calling convention.
2831 sig = mono_metadata_signature_dup (mono_method_signature (method));
2832 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2833 sig->call_convention = MONO_CALL_DEFAULT;
2834 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2835 method->name, method_encode_signature (assembly, sig));
2837 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2840 if (create_typespec) {
2841 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2842 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2843 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2845 if (assembly->save) {
2848 alloc_table (table, table->rows + 1);
2849 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2850 values [MONO_METHODSPEC_METHOD] = token;
2851 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2854 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2856 /*methodspec and memberef tokens are diferent, */
2857 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2864 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2866 guint32 token, parent, sig;
2867 ReflectionMethodBuilder rmb;
2868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2870 mono_error_init (error);
2871 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2875 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2879 * A methodref signature can't contain an unmanaged calling convention.
2880 * Since some flags are encoded as part of call_conv, we need to check against it.
2882 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2883 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2885 sig = method_builder_encode_signature (assembly, &rmb);
2887 if (tb->generic_params)
2888 parent = create_generic_typespec (assembly, tb);
2890 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2891 return_val_if_nok (error, 0);
2893 parent = mono_image_typedef_or_ref (assembly, t);
2896 char *name = mono_string_to_utf8 (method->name);
2898 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2901 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2907 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2908 const gchar *name, guint32 sig)
2910 MonoDynamicTable *table;
2914 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2916 if (assembly->save) {
2917 alloc_table (table, table->rows + 1);
2918 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2919 values [MONO_MEMBERREF_CLASS] = original;
2920 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2921 values [MONO_MEMBERREF_SIGNATURE] = sig;
2924 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2931 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2935 guint32 nparams = mono_array_length (mb->generic_params);
2938 if (!assembly->save)
2941 sigbuffer_init (&buf, 32);
2943 sigbuffer_add_value (&buf, 0xa);
2944 sigbuffer_add_value (&buf, nparams);
2946 for (i = 0; i < nparams; i++) {
2947 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2948 sigbuffer_add_value (&buf, i);
2951 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2952 sigbuffer_free (&buf);
2957 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2959 MonoDynamicTable *table;
2961 guint32 token, mtoken = 0;
2963 mono_error_init (error);
2964 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2968 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2970 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2971 if (!mono_error_ok (error))
2974 switch (mono_metadata_token_table (mtoken)) {
2975 case MONO_TABLE_MEMBERREF:
2976 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2978 case MONO_TABLE_METHOD:
2979 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2982 g_assert_not_reached ();
2985 if (assembly->save) {
2986 alloc_table (table, table->rows + 1);
2987 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2988 values [MONO_METHODSPEC_METHOD] = mtoken;
2989 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2992 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2995 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3000 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3004 mono_error_init (error);
3006 if (mb->generic_params && create_methodspec)
3007 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3009 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3013 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3014 if (!mono_error_ok (error))
3016 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3021 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3023 guint32 token, parent, sig;
3024 ReflectionMethodBuilder rmb;
3026 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3028 mono_error_init (error);
3030 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3034 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3037 if (tb->generic_params)
3038 parent = create_generic_typespec (assembly, tb);
3040 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3041 return_val_if_nok (error, 0);
3042 parent = mono_image_typedef_or_ref (assembly, type);
3045 name = mono_string_to_utf8 (rmb.name);
3046 sig = method_builder_encode_signature (assembly, &rmb);
3048 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3051 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3057 is_field_on_inst (MonoClassField *field)
3059 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3063 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3066 get_field_on_inst_generic_type (MonoClassField *field)
3068 MonoClass *klass, *gtd;
3069 MonoDynamicGenericClass *dgclass;
3072 g_assert (is_field_on_inst (field));
3074 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3076 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3077 field_index = field - dgclass->fields;
3078 return dgclass->field_generic_types [field_index];
3081 klass = field->parent;
3082 gtd = klass->generic_class->container_class;
3084 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3085 field_index = field - klass->fields;
3086 return gtd->fields [field_index].type;
3089 g_assert_not_reached ();
3093 #ifndef DISABLE_REFLECTION_EMIT
3095 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3101 g_assert (field->parent);
3103 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3107 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3108 int index = field - field->parent->fields;
3109 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3111 if (is_field_on_inst (field))
3112 type = get_field_on_inst_generic_type (field);
3114 type = mono_field_get_type (field);
3116 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3117 mono_field_get_name (field),
3118 fieldref_encode_signature (assembly, field->parent->image, type));
3119 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3124 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3129 MonoGenericClass *gclass;
3133 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3136 if (is_sre_field_builder (mono_object_class (f->fb))) {
3137 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3138 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3139 mono_error_raise_exception (&error); /* FIXME don't raise here */
3140 klass = mono_class_from_mono_type (type);
3141 gclass = type->data.generic_class;
3142 g_assert (gclass->is_dynamic);
3144 name = mono_string_to_utf8 (fb->name);
3145 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3146 field_encode_signature (assembly, fb));
3148 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3150 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3152 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3153 mono_error_raise_exception (&error); /* FIXME don't raise here */
3154 klass = mono_class_from_mono_type (type);
3156 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3157 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3159 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3160 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3163 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3168 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3172 MonoGenericClass *gclass;
3175 mono_error_init (error);
3177 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3179 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3183 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3184 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3185 ReflectionMethodBuilder rmb;
3188 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3189 return_val_if_nok (error, 0);
3190 klass = mono_class_from_mono_type (type);
3192 gclass = type->data.generic_class;
3193 g_assert (gclass->is_dynamic);
3195 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3198 name = mono_string_to_utf8 (rmb.name);
3200 sig = method_builder_encode_signature (assembly, &rmb);
3202 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3204 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3205 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3207 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3208 return_val_if_nok (error, 0);
3209 klass = mono_class_from_mono_type (type);
3211 sig = method_encode_signature (assembly, mono_method_signature (mm));
3212 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3214 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3215 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3219 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3224 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3227 MonoGenericContext tmp_context;
3228 MonoType **type_argv;
3229 MonoGenericInst *ginst;
3230 MonoMethod *method, *inflated;
3233 mono_error_init (error);
3235 init_type_builder_generics ((MonoObject*)m->inst);
3237 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3238 return_val_if_nok (error, NULL);
3240 klass = method->klass;
3242 if (m->method_args == NULL)
3245 if (method->is_inflated)
3246 method = ((MonoMethodInflated *) method)->declaring;
3248 count = mono_array_length (m->method_args);
3250 type_argv = g_new0 (MonoType *, count);
3251 for (i = 0; i < count; i++) {
3252 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3253 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3254 return_val_if_nok (error, NULL);
3256 ginst = mono_metadata_get_generic_inst (count, type_argv);
3259 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3260 tmp_context.method_inst = ginst;
3262 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3263 mono_error_assert_ok (error);
3268 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3270 guint32 sig, token = 0;
3274 mono_error_init (error);
3276 if (m->method_args) {
3277 MonoMethod *inflated;
3279 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3280 return_val_if_nok (error, 0);
3282 if (create_methodspec)
3283 token = mono_image_get_methodspec_token (assembly, inflated);
3285 token = mono_image_get_inflated_method_token (assembly, inflated);
3289 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3293 if (is_sre_method_builder (mono_object_class (m->mb))) {
3294 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3295 MonoGenericClass *gclass;
3296 ReflectionMethodBuilder rmb;
3299 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3300 return_val_if_nok (error, 0);
3301 klass = mono_class_from_mono_type (type);
3302 gclass = type->data.generic_class;
3303 g_assert (gclass->is_dynamic);
3305 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3308 name = mono_string_to_utf8 (rmb.name);
3310 sig = method_builder_encode_signature (assembly, &rmb);
3312 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3314 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3315 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3317 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3318 return_val_if_nok (error, 0);
3319 klass = mono_class_from_mono_type (type);
3321 sig = method_encode_signature (assembly, mono_method_signature (mm));
3322 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3324 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3325 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3328 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3333 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3337 guint32 nparams = context->method_inst->type_argc;
3340 if (!assembly->save)
3343 sigbuffer_init (&buf, 32);
3345 * FIXME: vararg, explicit_this, differenc call_conv values...
3347 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3348 sigbuffer_add_value (&buf, nparams);
3350 for (i = 0; i < nparams; i++)
3351 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3353 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3354 sigbuffer_free (&buf);
3359 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3361 MonoDynamicTable *table;
3363 guint32 token, mtoken = 0, sig;
3364 MonoMethodInflated *imethod;
3365 MonoMethod *declaring;
3367 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3369 g_assert (method->is_inflated);
3370 imethod = (MonoMethodInflated *) method;
3371 declaring = imethod->declaring;
3373 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3374 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3376 if (!mono_method_signature (declaring)->generic_param_count)
3379 switch (mono_metadata_token_table (mtoken)) {
3380 case MONO_TABLE_MEMBERREF:
3381 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3383 case MONO_TABLE_METHOD:
3384 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3387 g_assert_not_reached ();
3390 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3392 if (assembly->save) {
3393 alloc_table (table, table->rows + 1);
3394 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3395 values [MONO_METHODSPEC_METHOD] = mtoken;
3396 values [MONO_METHODSPEC_SIGNATURE] = sig;
3399 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3406 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3408 MonoMethodInflated *imethod;
3411 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3415 g_assert (method->is_inflated);
3416 imethod = (MonoMethodInflated *) method;
3418 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3419 token = method_encode_methodspec (assembly, method);
3421 guint32 sig = method_encode_signature (
3422 assembly, mono_method_signature (imethod->declaring));
3423 token = mono_image_get_memberref_token (
3424 assembly, &method->klass->byval_arg, method->name, sig);
3427 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3432 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3434 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3437 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3438 token = mono_image_get_memberref_token (
3439 assembly, &m->klass->byval_arg, m->name, sig);
3445 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3448 MonoDynamicTable *table;
3457 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3458 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3459 * Because of this, we must not insert it into the `typeref' hash table.
3461 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3462 mono_error_raise_exception (&error); /* FIXME don't raise here */
3463 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3467 sigbuffer_init (&buf, 32);
3469 g_assert (tb->generic_params);
3470 klass = mono_class_from_mono_type (type);
3472 if (tb->generic_container)
3473 mono_reflection_create_generic_class (tb);
3475 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3476 g_assert (klass->generic_container);
3477 sigbuffer_add_value (&buf, klass->byval_arg.type);
3478 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3480 count = mono_array_length (tb->generic_params);
3481 sigbuffer_add_value (&buf, count);
3482 for (i = 0; i < count; i++) {
3483 MonoReflectionGenericParam *gparam;
3485 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3486 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3487 mono_error_raise_exception (&error); /* FIXME don't raise here */
3489 encode_type (assembly, gparam_type, &buf);
3492 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3494 if (assembly->save) {
3495 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3496 alloc_table (table, table->rows + 1);
3497 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3498 values [MONO_TYPESPEC_SIGNATURE] = token;
3500 sigbuffer_free (&buf);
3502 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3503 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3509 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3512 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3515 int i, count, len, pos;
3520 count += mono_array_length (modreq);
3522 count += mono_array_length (modopt);
3525 return mono_metadata_type_dup (NULL, type);
3527 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3528 t = (MonoType *)g_malloc (len);
3529 memcpy (t, type, MONO_SIZEOF_TYPE);
3531 t->num_mods = count;
3534 for (i = 0; i < mono_array_length (modreq); ++i) {
3535 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3536 mono_error_raise_exception (&error); /* FIXME don't raise here */
3537 t->modifiers [pos].required = 1;
3538 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3543 for (i = 0; i < mono_array_length (modopt); ++i) {
3544 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3545 mono_error_raise_exception (&error); /* FIXME don't raise here */
3546 t->modifiers [pos].required = 0;
3547 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3556 init_type_builder_generics (MonoObject *type)
3558 MonoReflectionTypeBuilder *tb;
3560 if (!is_sre_type_builder(mono_object_class (type)))
3562 tb = (MonoReflectionTypeBuilder *)type;
3564 if (tb && tb->generic_container)
3565 mono_reflection_create_generic_class (tb);
3569 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3572 MonoDynamicTable *table;
3573 MonoType *custom = NULL, *type;
3575 guint32 token, pclass, parent, sig;
3578 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3582 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3583 mono_error_raise_exception (&error); /* FIXME don't raise here */
3584 /* FIXME: is this call necessary? */
3585 mono_class_from_mono_type (typeb);
3586 name = mono_string_to_utf8 (fb->name);
3588 /*FIXME this is one more layer of ugliness due how types are created.*/
3589 init_type_builder_generics (fb->type);
3591 /* fb->type does not include the custom modifiers */
3592 /* FIXME: We should do this in one place when a fieldbuilder is created */
3593 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3594 mono_error_raise_exception (&error); /* FIXME don't raise here */
3596 if (fb->modreq || fb->modopt)
3597 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3599 sig = fieldref_encode_signature (assembly, NULL, type);
3602 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3603 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3605 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3606 parent >>= MONO_TYPEDEFORREF_BITS;
3608 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3610 if (assembly->save) {
3611 alloc_table (table, table->rows + 1);
3612 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3613 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3614 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3615 values [MONO_MEMBERREF_SIGNATURE] = sig;
3618 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3620 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3626 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3632 if (!assembly->save)
3635 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3636 g_assert (helper->type == 2);
3638 if (helper->arguments)
3639 nargs = mono_array_length (helper->arguments);
3643 sigbuffer_init (&buf, 32);
3645 /* Encode calling convention */
3646 /* Change Any to Standard */
3647 if ((helper->call_conv & 0x03) == 0x03)
3648 helper->call_conv = 0x01;
3649 /* explicit_this implies has_this */
3650 if (helper->call_conv & 0x40)
3651 helper->call_conv &= 0x20;
3653 if (helper->call_conv == 0) { /* Unmanaged */
3654 idx = helper->unmanaged_call_conv - 1;
3657 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3658 if (helper->call_conv & 0x02) /* varargs */
3662 sigbuffer_add_byte (&buf, idx);
3663 sigbuffer_add_value (&buf, nargs);
3664 encode_reflection_type (assembly, helper->return_type, &buf);
3665 for (i = 0; i < nargs; ++i) {
3666 MonoArray *modreqs = NULL;
3667 MonoArray *modopts = NULL;
3668 MonoReflectionType *pt;
3670 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3671 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3672 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3673 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3675 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3676 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3677 encode_reflection_type (assembly, pt, &buf);
3679 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3680 sigbuffer_free (&buf);
3686 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3689 MonoDynamicTable *table;
3692 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3693 idx = table->next_idx ++;
3695 alloc_table (table, table->rows);
3696 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3698 values [MONO_STAND_ALONE_SIGNATURE] =
3699 mono_reflection_encode_sighelper (assembly, helper);
3705 reflection_cc_to_file (int call_conv) {
3706 switch (call_conv & 0x3) {
3708 case 1: return MONO_CALL_DEFAULT;
3709 case 2: return MONO_CALL_VARARG;
3711 g_assert_not_reached ();
3715 #endif /* !DISABLE_REFLECTION_EMIT */
3719 MonoMethodSignature *sig;
3724 #ifndef DISABLE_REFLECTION_EMIT
3726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3732 MonoMethodSignature *sig;
3736 name = mono_string_to_utf8 (m->name);
3737 nparams = mono_array_length (m->parameters);
3738 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3740 sig->sentinelpos = -1;
3741 sig->call_convention = reflection_cc_to_file (m->call_conv);
3742 sig->param_count = nparams;
3744 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3745 mono_error_raise_exception (&error); /* FIXME don't raise here */
3747 sig->ret = &mono_defaults.void_class->byval_arg;
3749 mtype = mono_reflection_type_get_handle (m->parent, &error);
3750 mono_error_raise_exception (&error); /* FIXME don't raise here */
3752 for (i = 0; i < nparams; ++i) {
3753 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3754 mono_error_raise_exception (&error); /* FIXME don't raise here */
3757 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3758 am = (ArrayMethod *)tmp->data;
3759 if (strcmp (name, am->name) == 0 &&
3760 mono_metadata_type_equal (am->parent, mtype) &&
3761 mono_metadata_signature_equal (am->sig, sig)) {
3764 m->table_idx = am->token & 0xffffff;
3768 am = g_new0 (ArrayMethod, 1);
3772 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3773 method_encode_signature (assembly, sig));
3774 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3775 m->table_idx = am->token & 0xffffff;
3780 * Insert into the metadata tables all the info about the TypeBuilder tb.
3781 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3784 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3786 MonoDynamicTable *table;
3788 int i, is_object = 0, is_system = 0;
3791 mono_error_init (error);
3793 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3794 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3795 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3796 n = mono_string_to_utf8 (tb->name);
3797 if (strcmp (n, "Object") == 0)
3799 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3801 n = mono_string_to_utf8 (tb->nspace);
3802 if (strcmp (n, "System") == 0)
3804 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3806 if (tb->parent && !(is_system && is_object) &&
3807 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3808 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3809 return_val_if_nok (error, FALSE);
3810 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3812 values [MONO_TYPEDEF_EXTENDS] = 0;
3814 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3815 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3818 * if we have explicitlayout or sequentiallayouts, output data in the
3819 * ClassLayout table.
3821 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3822 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3823 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3825 alloc_table (table, table->rows);
3826 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3827 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3828 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3829 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3832 /* handle interfaces */
3833 if (tb->interfaces) {
3834 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3836 table->rows += mono_array_length (tb->interfaces);
3837 alloc_table (table, table->rows);
3838 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3839 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3840 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3841 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3842 return_val_if_nok (error, FALSE);
3843 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3844 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3845 values += MONO_INTERFACEIMPL_SIZE;
3851 table = &assembly->tables [MONO_TABLE_FIELD];
3852 table->rows += tb->num_fields;
3853 alloc_table (table, table->rows);
3854 for (i = 0; i < tb->num_fields; ++i)
3855 mono_image_get_field_info (
3856 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3859 /* handle constructors */
3861 table = &assembly->tables [MONO_TABLE_METHOD];
3862 table->rows += mono_array_length (tb->ctors);
3863 alloc_table (table, table->rows);
3864 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3865 if (!mono_image_get_ctor_info (domain,
3866 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3872 /* handle methods */
3874 table = &assembly->tables [MONO_TABLE_METHOD];
3875 table->rows += tb->num_methods;
3876 alloc_table (table, table->rows);
3877 for (i = 0; i < tb->num_methods; ++i) {
3878 if (!mono_image_get_method_info (
3879 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3884 /* Do the same with properties etc.. */
3885 if (tb->events && mono_array_length (tb->events)) {
3886 table = &assembly->tables [MONO_TABLE_EVENT];
3887 table->rows += mono_array_length (tb->events);
3888 alloc_table (table, table->rows);
3889 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3891 alloc_table (table, table->rows);
3892 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3893 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3894 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3895 for (i = 0; i < mono_array_length (tb->events); ++i)
3896 mono_image_get_event_info (
3897 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3899 if (tb->properties && mono_array_length (tb->properties)) {
3900 table = &assembly->tables [MONO_TABLE_PROPERTY];
3901 table->rows += mono_array_length (tb->properties);
3902 alloc_table (table, table->rows);
3903 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3905 alloc_table (table, table->rows);
3906 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3907 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3908 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3909 for (i = 0; i < mono_array_length (tb->properties); ++i)
3910 mono_image_get_property_info (
3911 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3914 /* handle generic parameters */
3915 if (tb->generic_params) {
3916 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3917 table->rows += mono_array_length (tb->generic_params);
3918 alloc_table (table, table->rows);
3919 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3920 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3922 mono_image_get_generic_param_info (
3923 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3927 mono_image_add_decl_security (assembly,
3928 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3931 MonoDynamicTable *ntable;
3933 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3934 ntable->rows += mono_array_length (tb->subtypes);
3935 alloc_table (ntable, ntable->rows);
3936 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3938 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3939 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3941 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3942 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3943 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3944 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3945 mono_string_to_utf8 (tb->name), tb->table_idx,
3946 ntable->next_idx, ntable->rows);*/
3947 values += MONO_NESTED_CLASS_SIZE;
3957 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3961 mono_ptr_array_append (*types, type);
3963 if (!type->subtypes)
3966 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3967 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3968 collect_types (types, subtype);
3973 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3975 if ((*type1)->table_idx < (*type2)->table_idx)
3978 if ((*type1)->table_idx > (*type2)->table_idx)
3985 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3988 mono_error_init (error);
3991 for (i = 0; i < mono_array_length (pinfo); ++i) {
3992 MonoReflectionParamBuilder *pb;
3993 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3996 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4004 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4007 mono_error_init (error);
4009 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4012 for (i = 0; i < tb->num_fields; ++i) {
4013 MonoReflectionFieldBuilder* fb;
4014 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4015 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4020 for (i = 0; i < mono_array_length (tb->events); ++i) {
4021 MonoReflectionEventBuilder* eb;
4022 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4023 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4027 if (tb->properties) {
4028 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4029 MonoReflectionPropertyBuilder* pb;
4030 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4031 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4036 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4037 MonoReflectionCtorBuilder* cb;
4038 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4039 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4040 !params_add_cattrs (assembly, cb->pinfo, error))
4046 for (i = 0; i < tb->num_methods; ++i) {
4047 MonoReflectionMethodBuilder* mb;
4048 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4049 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4050 !params_add_cattrs (assembly, mb->pinfo, error))
4056 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4057 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4066 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4070 mono_error_init (error);
4072 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4075 if (moduleb->global_methods) {
4076 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4077 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4078 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4079 !params_add_cattrs (assembly, mb->pinfo, error))
4084 if (moduleb->global_fields) {
4085 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4086 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4087 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4092 if (moduleb->types) {
4093 for (i = 0; i < moduleb->num_types; ++i) {
4094 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4103 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4105 MonoDynamicTable *table;
4109 char *b = blob_size;
4112 table = &assembly->tables [MONO_TABLE_FILE];
4114 alloc_table (table, table->rows);
4115 values = table->values + table->next_idx * MONO_FILE_SIZE;
4116 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4117 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4118 if (image_is_dynamic (module->image)) {
4119 /* This depends on the fact that the main module is emitted last */
4120 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4121 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4124 path = g_strdup (module->image->name);
4126 mono_sha1_get_digest_from_file (path, hash);
4129 mono_metadata_encode_value (20, b, &b);
4130 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4131 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4136 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4138 MonoDynamicTable *table;
4141 table = &assembly->tables [MONO_TABLE_MODULE];
4142 mb->table_idx = table->next_idx ++;
4143 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4144 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4147 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4148 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4149 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4150 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4154 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4155 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4157 MonoDynamicTable *table;
4161 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4162 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4165 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4167 alloc_table (table, table->rows);
4168 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4170 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4171 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4172 if (klass->nested_in)
4173 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4175 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4176 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4177 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4179 res = table->next_idx;
4183 /* Emit nested types */
4184 if (klass->ext && klass->ext->nested_classes) {
4187 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4188 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4195 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4196 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4202 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4203 mono_error_raise_exception (&error); /* FIXME don't raise here */
4205 klass = mono_class_from_mono_type (t);
4207 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4209 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4210 parent_index, assembly);
4214 * We need to do this ourselves since klass->nested_classes is not set up.
4217 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4218 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4223 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4224 guint32 module_index, MonoDynamicImage *assembly)
4226 MonoImage *image = module->image;
4230 t = &image->tables [MONO_TABLE_TYPEDEF];
4232 for (i = 0; i < t->rows; ++i) {
4234 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4235 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4237 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4238 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4243 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4245 MonoDynamicTable *table;
4247 guint32 scope, scope_idx, impl, current_idx;
4248 gboolean forwarder = TRUE;
4249 gpointer iter = NULL;
4252 if (klass->nested_in) {
4253 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4256 scope = resolution_scope_from_image (assembly, klass->image);
4257 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4258 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4259 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4262 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4265 alloc_table (table, table->rows);
4266 current_idx = table->next_idx;
4267 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4269 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4270 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4271 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4272 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4273 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4277 while ((nested = mono_class_get_nested_types (klass, &iter)))
4278 add_exported_type (assemblyb, assembly, nested, current_idx);
4282 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4288 if (!assemblyb->type_forwarders)
4291 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4292 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4297 type = mono_reflection_type_get_handle (t, &error);
4298 mono_error_assert_ok (&error);
4301 klass = mono_class_from_mono_type (type);
4303 add_exported_type (assemblyb, assembly, klass, 0);
4307 #define align_pointer(base,p)\
4309 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4311 (p) += 4 - (__diff & 3);\
4315 compare_constants (const void *a, const void *b)
4317 const guint32 *a_values = (const guint32 *)a;
4318 const guint32 *b_values = (const guint32 *)b;
4319 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4323 compare_semantics (const void *a, const void *b)
4325 const guint32 *a_values = (const guint32 *)a;
4326 const guint32 *b_values = (const guint32 *)b;
4327 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4330 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4334 compare_custom_attrs (const void *a, const void *b)
4336 const guint32 *a_values = (const guint32 *)a;
4337 const guint32 *b_values = (const guint32 *)b;
4339 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4343 compare_field_marshal (const void *a, const void *b)
4345 const guint32 *a_values = (const guint32 *)a;
4346 const guint32 *b_values = (const guint32 *)b;
4348 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4352 compare_nested (const void *a, const void *b)
4354 const guint32 *a_values = (const guint32 *)a;
4355 const guint32 *b_values = (const guint32 *)b;
4357 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4361 compare_genericparam (const void *a, const void *b)
4364 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4365 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4367 if ((*b_entry)->owner == (*a_entry)->owner) {
4368 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4369 mono_error_assert_ok (&error);
4370 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4371 mono_error_assert_ok (&error);
4373 mono_type_get_generic_param_num (a_type) -
4374 mono_type_get_generic_param_num (b_type);
4376 return (*a_entry)->owner - (*b_entry)->owner;
4380 compare_declsecurity_attrs (const void *a, const void *b)
4382 const guint32 *a_values = (const guint32 *)a;
4383 const guint32 *b_values = (const guint32 *)b;
4385 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4389 compare_interface_impl (const void *a, const void *b)
4391 const guint32 *a_values = (const guint32 *)a;
4392 const guint32 *b_values = (const guint32 *)b;
4394 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4398 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4402 pad_heap (MonoDynamicStream *sh)
4404 if (sh->index & 3) {
4405 int sz = 4 - (sh->index & 3);
4406 memset (sh->data + sh->index, 0, sz);
4413 MonoDynamicStream *stream;
4417 * build_compressed_metadata() fills in the blob of data that represents the
4418 * raw metadata as it will be saved in the PE file. The five streams are output
4419 * and the metadata tables are comnpressed from the guint32 array representation,
4420 * to the compressed on-disk format.
4423 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4425 MonoDynamicTable *table;
4427 guint64 valid_mask = 0;
4428 guint64 sorted_mask;
4429 guint32 heapt_size = 0;
4430 guint32 meta_size = 256; /* allow for header and other stuff */
4431 guint32 table_offset;
4432 guint32 ntables = 0;
4438 struct StreamDesc stream_desc [5];
4440 mono_error_init (error);
4442 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4443 for (i = 0; i < assembly->gen_params->len; i++) {
4444 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4445 if (!write_generic_param_entry (assembly, entry, error))
4449 stream_desc [0].name = "#~";
4450 stream_desc [0].stream = &assembly->tstream;
4451 stream_desc [1].name = "#Strings";
4452 stream_desc [1].stream = &assembly->sheap;
4453 stream_desc [2].name = "#US";
4454 stream_desc [2].stream = &assembly->us;
4455 stream_desc [3].name = "#Blob";
4456 stream_desc [3].stream = &assembly->blob;
4457 stream_desc [4].name = "#GUID";
4458 stream_desc [4].stream = &assembly->guid;
4460 /* tables that are sorted */
4461 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4462 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4463 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4464 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4465 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4466 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4467 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4469 /* Compute table sizes */
4470 /* the MonoImage has already been created in mono_image_basic_init() */
4471 meta = &assembly->image;
4473 /* sizes should be multiple of 4 */
4474 pad_heap (&assembly->blob);
4475 pad_heap (&assembly->guid);
4476 pad_heap (&assembly->sheap);
4477 pad_heap (&assembly->us);
4479 /* Setup the info used by compute_sizes () */
4480 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4481 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4482 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4484 meta_size += assembly->blob.index;
4485 meta_size += assembly->guid.index;
4486 meta_size += assembly->sheap.index;
4487 meta_size += assembly->us.index;
4489 for (i=0; i < MONO_TABLE_NUM; ++i)
4490 meta->tables [i].rows = assembly->tables [i].rows;
4492 for (i = 0; i < MONO_TABLE_NUM; i++){
4493 if (meta->tables [i].rows == 0)
4495 valid_mask |= (guint64)1 << i;
4497 meta->tables [i].row_size = mono_metadata_compute_size (
4498 meta, i, &meta->tables [i].size_bitfield);
4499 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4501 heapt_size += 24; /* #~ header size */
4502 heapt_size += ntables * 4;
4503 /* make multiple of 4 */
4506 meta_size += heapt_size;
4507 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4508 p = (unsigned char*)meta->raw_metadata;
4509 /* the metadata signature */
4510 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4511 /* version numbers and 4 bytes reserved */
4512 int16val = (guint16*)p;
4513 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4514 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4516 /* version string */
4517 int32val = (guint32*)p;
4518 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4520 memcpy (p, meta->version, strlen (meta->version));
4521 p += GUINT32_FROM_LE (*int32val);
4522 align_pointer (meta->raw_metadata, p);
4523 int16val = (guint16*)p;
4524 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4525 *int16val = GUINT16_TO_LE (5); /* number of streams */
4529 * write the stream info.
4531 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4532 table_offset += 3; table_offset &= ~3;
4534 assembly->tstream.index = heapt_size;
4535 for (i = 0; i < 5; ++i) {
4536 int32val = (guint32*)p;
4537 stream_desc [i].stream->offset = table_offset;
4538 *int32val++ = GUINT32_TO_LE (table_offset);
4539 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4540 table_offset += GUINT32_FROM_LE (*int32val);
4541 table_offset += 3; table_offset &= ~3;
4543 strcpy ((char*)p, stream_desc [i].name);
4544 p += strlen (stream_desc [i].name) + 1;
4545 align_pointer (meta->raw_metadata, p);
4548 * now copy the data, the table stream header and contents goes first.
4550 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4551 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4552 int32val = (guint32*)p;
4553 *int32val = GUINT32_TO_LE (0); /* reserved */
4556 *p++ = 2; /* version */
4559 if (meta->idx_string_wide)
4561 if (meta->idx_guid_wide)
4563 if (meta->idx_blob_wide)
4566 *p++ = 1; /* reserved */
4567 int64val = (guint64*)p;
4568 *int64val++ = GUINT64_TO_LE (valid_mask);
4569 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4571 int32val = (guint32*)p;
4572 for (i = 0; i < MONO_TABLE_NUM; i++){
4573 if (meta->tables [i].rows == 0)
4575 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4577 p = (unsigned char*)int32val;
4579 /* sort the tables that still need sorting */
4580 table = &assembly->tables [MONO_TABLE_CONSTANT];
4582 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4583 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4585 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4586 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4588 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4589 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4591 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4592 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4594 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4595 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4596 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4598 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4599 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4601 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4603 /* compress the tables */
4604 for (i = 0; i < MONO_TABLE_NUM; i++){
4607 guint32 bitfield = meta->tables [i].size_bitfield;
4608 if (!meta->tables [i].rows)
4610 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4611 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4612 meta->tables [i].base = (char*)p;
4613 for (row = 1; row <= meta->tables [i].rows; ++row) {
4614 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4615 for (col = 0; col < assembly->tables [i].columns; ++col) {
4616 switch (mono_metadata_table_size (bitfield, col)) {
4618 *p++ = values [col];
4621 *p++ = values [col] & 0xff;
4622 *p++ = (values [col] >> 8) & 0xff;
4625 *p++ = values [col] & 0xff;
4626 *p++ = (values [col] >> 8) & 0xff;
4627 *p++ = (values [col] >> 16) & 0xff;
4628 *p++ = (values [col] >> 24) & 0xff;
4631 g_assert_not_reached ();
4635 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4638 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4639 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4640 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4641 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4642 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4644 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4650 * Some tables in metadata need to be sorted according to some criteria, but
4651 * when methods and fields are first created with reflection, they may be assigned a token
4652 * that doesn't correspond to the final token they will get assigned after the sorting.
4653 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4654 * with the reflection objects that represent them. Once all the tables are set up, the
4655 * reflection objects will contains the correct table index. fixup_method() will fixup the
4656 * tokens for the method with ILGenerator @ilgen.
4659 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4661 guint32 code_idx = GPOINTER_TO_UINT (value);
4662 MonoReflectionILTokenInfo *iltoken;
4663 MonoReflectionFieldBuilder *field;
4664 MonoReflectionCtorBuilder *ctor;
4665 MonoReflectionMethodBuilder *method;
4666 MonoReflectionTypeBuilder *tb;
4667 MonoReflectionArrayMethod *am;
4669 unsigned char *target;
4671 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4672 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4673 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4674 switch (target [3]) {
4675 case MONO_TABLE_FIELD:
4676 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4677 field = (MonoReflectionFieldBuilder *)iltoken->member;
4678 idx = field->table_idx;
4679 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4680 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4681 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4683 g_assert_not_reached ();
4686 case MONO_TABLE_METHOD:
4687 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4688 method = (MonoReflectionMethodBuilder *)iltoken->member;
4689 idx = method->table_idx;
4690 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4691 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4692 idx = ctor->table_idx;
4693 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4694 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4695 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4696 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4698 g_assert_not_reached ();
4701 case MONO_TABLE_TYPEDEF:
4702 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4703 g_assert_not_reached ();
4704 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4705 idx = tb->table_idx;
4707 case MONO_TABLE_MEMBERREF:
4708 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4709 am = (MonoReflectionArrayMethod*)iltoken->member;
4710 idx = am->table_idx;
4711 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4712 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4713 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4714 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4715 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4716 g_assert (m->klass->generic_class || m->klass->generic_container);
4718 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4720 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4721 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4722 g_assert (is_field_on_inst (f));
4724 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4725 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4727 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4729 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4731 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4734 g_assert_not_reached ();
4737 case MONO_TABLE_METHODSPEC:
4738 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4739 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4740 g_assert (mono_method_signature (m)->generic_param_count);
4742 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4744 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4747 g_assert_not_reached ();
4751 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4753 target [0] = idx & 0xff;
4754 target [1] = (idx >> 8) & 0xff;
4755 target [2] = (idx >> 16) & 0xff;
4762 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4763 * value is not known when the table is emitted.
4766 fixup_cattrs (MonoDynamicImage *assembly)
4768 MonoDynamicTable *table;
4770 guint32 type, i, idx, token;
4773 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4775 for (i = 0; i < table->rows; ++i) {
4776 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4778 type = values [MONO_CUSTOM_ATTR_TYPE];
4779 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4780 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4781 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4782 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4785 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4786 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4787 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4788 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4789 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4790 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4791 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4792 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4799 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4801 MonoDynamicTable *table;
4804 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4806 alloc_table (table, table->rows);
4807 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4808 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4809 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4810 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4811 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4816 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4818 MonoDynamicTable *table;
4822 char *b = blob_size;
4824 guint32 idx, offset;
4826 if (rsrc->filename) {
4827 name = mono_string_to_utf8 (rsrc->filename);
4828 sname = g_path_get_basename (name);
4830 table = &assembly->tables [MONO_TABLE_FILE];
4832 alloc_table (table, table->rows);
4833 values = table->values + table->next_idx * MONO_FILE_SIZE;
4834 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4835 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4838 mono_sha1_get_digest_from_file (name, hash);
4839 mono_metadata_encode_value (20, b, &b);
4840 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4841 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4843 idx = table->next_idx++;
4845 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4851 data = mono_array_addr (rsrc->data, char, 0);
4852 len = mono_array_length (rsrc->data);
4858 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4859 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4860 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4861 mono_image_add_stream_data (&assembly->resources, data, len);
4865 * The entry should be emitted into the MANIFESTRESOURCE table of
4866 * the main module, but that needs to reference the FILE table
4867 * which isn't emitted yet.
4874 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4878 set_version_from_string (MonoString *version, guint32 *values)
4880 gchar *ver, *p, *str;
4883 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4884 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4885 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4886 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4889 ver = str = mono_string_to_utf8 (version);
4890 for (i = 0; i < 4; ++i) {
4891 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4897 /* handle Revision and Build */
4907 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4911 char *b = blob_size;
4916 len = mono_array_length (pkey);
4917 mono_metadata_encode_value (len, b, &b);
4918 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4919 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4921 assembly->public_key = (guint8 *)g_malloc (len);
4922 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4923 assembly->public_key_len = len;
4925 /* Special case: check for ECMA key (16 bytes) */
4926 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4927 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4928 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4929 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4930 /* minimum key size (in 2.0) is 384 bits */
4931 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4933 /* FIXME - verifier */
4934 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4935 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4937 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4943 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4945 MonoDynamicTable *table;
4946 MonoDynamicImage *assembly;
4947 MonoReflectionAssemblyBuilder *assemblyb;
4951 guint32 module_index;
4953 assemblyb = moduleb->assemblyb;
4954 assembly = moduleb->dynamic_image;
4955 domain = mono_object_domain (assemblyb);
4957 /* Emit ASSEMBLY table */
4958 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4959 alloc_table (table, 1);
4960 values = table->values + MONO_ASSEMBLY_SIZE;
4961 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4962 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4963 if (assemblyb->culture) {
4964 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4966 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4968 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4969 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4970 set_version_from_string (assemblyb->version, values);
4972 /* Emit FILE + EXPORTED_TYPE table */
4974 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4976 MonoReflectionModuleBuilder *file_module =
4977 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4978 if (file_module != moduleb) {
4979 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4981 if (file_module->types) {
4982 for (j = 0; j < file_module->num_types; ++j) {
4983 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4984 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4989 if (assemblyb->loaded_modules) {
4990 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4991 MonoReflectionModule *file_module =
4992 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4993 mono_image_fill_file_table (domain, file_module, assembly);
4995 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4998 if (assemblyb->type_forwarders)
4999 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5001 /* Emit MANIFESTRESOURCE table */
5003 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5005 MonoReflectionModuleBuilder *file_module =
5006 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5007 /* The table for the main module is emitted later */
5008 if (file_module != moduleb) {
5010 if (file_module->resources) {
5011 int len = mono_array_length (file_module->resources);
5012 for (j = 0; j < len; ++j) {
5013 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5014 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5021 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5024 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5025 * for the modulebuilder @moduleb.
5026 * At the end of the process, method and field tokens are fixed up and the
5027 * on-disk compressed metadata representation is created.
5028 * Return TRUE on success, or FALSE on failure and sets @error
5031 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5033 MonoDynamicTable *table;
5034 MonoDynamicImage *assembly;
5035 MonoReflectionAssemblyBuilder *assemblyb;
5041 mono_error_init (error);
5043 assemblyb = moduleb->assemblyb;
5044 assembly = moduleb->dynamic_image;
5045 domain = mono_object_domain (assemblyb);
5047 if (assembly->text_rva)
5050 assembly->text_rva = START_TEXT_RVA;
5052 if (moduleb->is_main) {
5053 mono_image_emit_manifest (moduleb);
5056 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5057 table->rows = 1; /* .<Module> */
5059 alloc_table (table, table->rows);
5061 * Set the first entry.
5063 values = table->values + table->columns;
5064 values [MONO_TYPEDEF_FLAGS] = 0;
5065 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5066 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5067 values [MONO_TYPEDEF_EXTENDS] = 0;
5068 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5069 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5072 * handle global methods
5073 * FIXME: test what to do when global methods are defined in multiple modules.
5075 if (moduleb->global_methods) {
5076 table = &assembly->tables [MONO_TABLE_METHOD];
5077 table->rows += mono_array_length (moduleb->global_methods);
5078 alloc_table (table, table->rows);
5079 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5080 if (!mono_image_get_method_info (
5081 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5085 if (moduleb->global_fields) {
5086 table = &assembly->tables [MONO_TABLE_FIELD];
5087 table->rows += mono_array_length (moduleb->global_fields);
5088 alloc_table (table, table->rows);
5089 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5090 mono_image_get_field_info (
5091 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5094 table = &assembly->tables [MONO_TABLE_MODULE];
5095 alloc_table (table, 1);
5096 mono_image_fill_module_table (domain, moduleb, assembly);
5098 /* Collect all types into a list sorted by their table_idx */
5099 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5102 for (i = 0; i < moduleb->num_types; ++i) {
5103 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5104 collect_types (&types, type);
5107 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5108 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5109 table->rows += mono_ptr_array_size (types);
5110 alloc_table (table, table->rows);
5113 * Emit type names + namespaces at one place inside the string heap,
5114 * so load_class_names () needs to touch fewer pages.
5116 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5117 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5118 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5120 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5121 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5122 string_heap_insert_mstring (&assembly->sheap, tb->name);
5125 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5126 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5127 if (!mono_image_get_type_info (domain, type, assembly, error))
5132 * table->rows is already set above and in mono_image_fill_module_table.
5134 /* add all the custom attributes at the end, once all the indexes are stable */
5135 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5138 /* CAS assembly permissions */
5139 if (assemblyb->permissions_minimum)
5140 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5141 if (assemblyb->permissions_optional)
5142 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5143 if (assemblyb->permissions_refused)
5144 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5146 if (!module_add_cattrs (assembly, moduleb, error))
5150 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5152 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5153 * the final tokens and don't need another fixup pass. */
5155 if (moduleb->global_methods) {
5156 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5157 MonoReflectionMethodBuilder *mb = mono_array_get (
5158 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5159 if (!mono_image_add_methodimpl (assembly, mb, error))
5164 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5165 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5166 if (type->methods) {
5167 for (j = 0; j < type->num_methods; ++j) {
5168 MonoReflectionMethodBuilder *mb = mono_array_get (
5169 type->methods, MonoReflectionMethodBuilder*, j);
5171 if (!mono_image_add_methodimpl (assembly, mb, error))
5177 fixup_cattrs (assembly);
5180 mono_ptr_array_destroy (types);
5183 return mono_error_ok (error);
5186 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5189 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5191 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5194 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5198 guint32 import_lookup_table;
5202 guint32 import_address_table_rva;
5210 #ifndef DISABLE_REFLECTION_EMIT
5213 * mono_image_insert_string:
5214 * @module: module builder object
5217 * Insert @str into the user string stream of @module.
5220 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5222 MonoDynamicImage *assembly;
5227 if (!module->dynamic_image)
5228 mono_image_module_basic_init (module);
5230 assembly = module->dynamic_image;
5232 if (assembly->save) {
5233 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5234 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5235 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5237 char *swapped = g_malloc (2 * mono_string_length (str));
5238 const char *p = (const char*)mono_string_chars (str);
5240 swap_with_size (swapped, p, 2, mono_string_length (str));
5241 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5245 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5247 mono_image_add_stream_data (&assembly->us, "", 1);
5249 idx = assembly->us.index ++;
5252 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5254 return MONO_TOKEN_STRING | idx;
5258 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5262 MonoMethodSignature *sig;
5264 mono_error_init (error);
5266 klass = obj->vtable->klass;
5267 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5268 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5269 MonoMethodSignature *old;
5270 guint32 sig_token, parent;
5273 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5275 nargs = mono_array_length (opt_param_types);
5276 old = mono_method_signature (method);
5277 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5279 sig->hasthis = old->hasthis;
5280 sig->explicit_this = old->explicit_this;
5281 sig->call_convention = old->call_convention;
5282 sig->generic_param_count = old->generic_param_count;
5283 sig->param_count = old->param_count + nargs;
5284 sig->sentinelpos = old->param_count;
5285 sig->ret = old->ret;
5287 for (i = 0; i < old->param_count; i++)
5288 sig->params [i] = old->params [i];
5290 for (i = 0; i < nargs; i++) {
5291 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5292 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5293 if (!is_ok (error)) goto fail;
5296 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5297 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5298 parent >>= MONO_TYPEDEFORREF_BITS;
5300 parent <<= MONO_MEMBERREF_PARENT_BITS;
5301 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5303 sig_token = method_encode_signature (assembly, sig);
5304 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5305 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5306 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5307 ReflectionMethodBuilder rmb;
5308 guint32 parent, sig_token;
5309 int nopt_args, nparams, ngparams, i;
5311 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5314 rmb.opt_types = opt_param_types;
5315 nopt_args = mono_array_length (opt_param_types);
5317 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5318 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5319 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5321 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5322 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5323 sig->call_convention = rmb.call_conv;
5324 sig->generic_param_count = ngparams;
5325 sig->param_count = nparams + nopt_args;
5326 sig->sentinelpos = nparams;
5327 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5328 if (!is_ok (error)) goto fail;
5330 for (i = 0; i < nparams; i++) {
5331 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5332 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5333 if (!is_ok (error)) goto fail;
5336 for (i = 0; i < nopt_args; i++) {
5337 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5338 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5339 if (!is_ok (error)) goto fail;
5342 sig_token = method_builder_encode_signature (assembly, &rmb);
5344 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5345 if (!mono_error_ok (error))
5347 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5349 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5350 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5352 char *name = mono_string_to_utf8 (rmb.name);
5353 token = mono_image_get_varargs_method_token (
5354 assembly, parent, name, sig_token);
5357 g_error ("requested method token for %s\n", klass->name);
5360 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5361 register_dyn_token (assembly, token, obj);
5364 g_assert (!mono_error_ok (error));
5369 * mono_image_create_token:
5370 * @assembly: a dynamic assembly
5372 * @register_token: Whenever to register the token in the assembly->tokens hash.
5374 * Get a token to insert in the IL code stream for the given MemberInfo.
5375 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5376 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5380 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5381 gboolean create_open_instance, gboolean register_token,
5387 mono_error_init (error);
5389 klass = obj->vtable->klass;
5391 /* Check for user defined reflection objects */
5392 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5393 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5394 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5398 if (strcmp (klass->name, "MethodBuilder") == 0) {
5399 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5400 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5402 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5403 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5405 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5406 if (!mono_error_ok (error))
5409 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5410 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5411 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5412 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5414 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5415 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5417 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5418 if (!mono_error_ok (error))
5421 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5422 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5423 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5424 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5425 if (tb->generic_params) {
5426 token = mono_image_get_generic_field_token (assembly, fb);
5428 if (tb->module->dynamic_image == assembly) {
5429 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5431 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5434 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5435 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5436 if (create_open_instance && tb->generic_params) {
5438 init_type_builder_generics (obj);
5439 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5440 return_val_if_nok (error, 0);
5441 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5442 token = mono_metadata_token_from_dor (token);
5443 } else if (tb->module->dynamic_image == assembly) {
5444 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5447 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5448 return_val_if_nok (error, 0);
5449 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5451 } else if (strcmp (klass->name, "MonoType") == 0) {
5452 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5453 return_val_if_nok (error, 0);
5454 MonoClass *mc = mono_class_from_mono_type (type);
5455 token = mono_metadata_token_from_dor (
5456 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5457 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5458 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5459 return_val_if_nok (error, 0);
5460 token = mono_metadata_token_from_dor (
5461 mono_image_typedef_or_ref (assembly, type));
5462 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5463 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5464 return_val_if_nok (error, 0);
5465 token = mono_metadata_token_from_dor (
5466 mono_image_typedef_or_ref (assembly, type));
5467 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5468 strcmp (klass->name, "MonoMethod") == 0 ||
5469 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5470 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5471 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5472 if (m->method->is_inflated) {
5473 if (create_open_instance)
5474 token = mono_image_get_methodspec_token (assembly, m->method);
5476 token = mono_image_get_inflated_method_token (assembly, m->method);
5477 } else if ((m->method->klass->image == &assembly->image) &&
5478 !m->method->klass->generic_class) {
5479 static guint32 method_table_idx = 0xffffff;
5480 if (m->method->klass->wastypebuilder) {
5481 /* we use the same token as the one that was assigned
5482 * to the Methodbuilder.
5483 * FIXME: do the equivalent for Fields.
5485 token = m->method->token;
5488 * Each token should have a unique index, but the indexes are
5489 * assigned by managed code, so we don't know about them. An
5490 * easy solution is to count backwards...
5492 method_table_idx --;
5493 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5496 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5498 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5499 } else if (strcmp (klass->name, "MonoField") == 0) {
5500 MonoReflectionField *f = (MonoReflectionField *)obj;
5501 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5502 static guint32 field_table_idx = 0xffffff;
5504 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5506 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5508 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5509 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5510 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5511 token = mono_image_get_array_token (assembly, m);
5512 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5513 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5514 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5515 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5516 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5517 return_val_if_nok (error, 0);
5518 token = mono_metadata_token_from_dor (
5519 mono_image_typedef_or_ref (assembly, type));
5520 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5521 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5522 token = mono_image_get_field_on_inst_token (assembly, f);
5523 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5524 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5525 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5526 if (!mono_error_ok (error))
5528 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5529 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5530 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5531 if (!mono_error_ok (error))
5533 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5534 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5535 return_val_if_nok (error, 0);
5536 token = mono_metadata_token_from_dor (
5537 mono_image_typedef_or_ref (assembly, type));
5539 g_error ("requested token for %s\n", klass->name);
5543 mono_image_register_token (assembly, token, obj);
5549 * mono_image_register_token:
5551 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5552 * the Module.ResolveXXXToken () methods to work.
5555 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5559 dynamic_image_lock (assembly);
5560 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5562 /* There could be multiple MethodInfo objects with the same token */
5563 //g_assert (prev == obj);
5565 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5567 dynamic_image_unlock (assembly);
5570 static MonoDynamicImage*
5571 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5573 static const guchar entrycode [16] = {0xff, 0x25, 0};
5574 MonoDynamicImage *image;
5577 const char *version;
5579 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5580 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5582 version = mono_get_runtime_info ()->runtime_version;
5585 /* The MonoGHashTable's need GC tracking */
5586 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5588 image = g_new0 (MonoDynamicImage, 1);
5591 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5593 /*g_print ("created image %p\n", image);*/
5594 /* keep in sync with image.c */
5595 image->image.name = assembly_name;
5596 image->image.assembly_name = image->image.name; /* they may be different */
5597 image->image.module_name = module_name;
5598 image->image.version = g_strdup (version);
5599 image->image.md_version_major = 1;
5600 image->image.md_version_minor = 1;
5601 image->image.dynamic = TRUE;
5603 image->image.references = g_new0 (MonoAssembly*, 1);
5604 image->image.references [0] = NULL;
5606 mono_image_init (&image->image);
5608 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");
5609 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5610 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5611 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5612 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5613 image->handleref = g_hash_table_new (NULL, NULL);
5614 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");
5615 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5616 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");
5617 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");
5618 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5619 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5620 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5621 image->gen_params = g_ptr_array_new ();
5622 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5624 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5625 string_heap_init (&image->sheap);
5626 mono_image_add_stream_data (&image->us, "", 1);
5627 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5628 /* import tables... */
5629 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5630 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5631 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5632 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5633 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5634 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5635 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5636 stream_data_align (&image->code);
5638 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5640 for (i=0; i < MONO_TABLE_NUM; ++i) {
5641 image->tables [i].next_idx = 1;
5642 image->tables [i].columns = table_sizes [i];
5645 image->image.assembly = (MonoAssembly*)assembly;
5646 image->run = assembly->run;
5647 image->save = assembly->save;
5648 image->pe_kind = 0x1; /* ILOnly */
5649 image->machine = 0x14c; /* I386 */
5651 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5653 dynamic_images_lock ();
5655 if (!dynamic_images)
5656 dynamic_images = g_ptr_array_new ();
5658 g_ptr_array_add (dynamic_images, image);
5660 dynamic_images_unlock ();
5667 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5673 release_hashtable (MonoGHashTable **hash)
5676 mono_g_hash_table_destroy (*hash);
5682 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5684 release_hashtable (&image->token_fixups);
5685 release_hashtable (&image->handleref_managed);
5686 release_hashtable (&image->tokens);
5687 release_hashtable (&image->remapped_tokens);
5688 release_hashtable (&image->generic_def_objects);
5689 release_hashtable (&image->methodspec);
5692 // Free dynamic image pass one: Free resources but not image itself
5694 mono_dynamic_image_free (MonoDynamicImage *image)
5696 MonoDynamicImage *di = image;
5701 mono_g_hash_table_destroy (di->methodspec);
5703 g_hash_table_destroy (di->typespec);
5705 g_hash_table_destroy (di->typeref);
5707 g_hash_table_destroy (di->handleref);
5708 if (di->handleref_managed)
5709 mono_g_hash_table_destroy (di->handleref_managed);
5711 mono_g_hash_table_destroy (di->tokens);
5712 if (di->remapped_tokens)
5713 mono_g_hash_table_destroy (di->remapped_tokens);
5714 if (di->generic_def_objects)
5715 mono_g_hash_table_destroy (di->generic_def_objects);
5716 if (di->blob_cache) {
5717 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5718 g_hash_table_destroy (di->blob_cache);
5720 if (di->standalonesig_cache)
5721 g_hash_table_destroy (di->standalonesig_cache);
5722 for (list = di->array_methods; list; list = list->next) {
5723 ArrayMethod *am = (ArrayMethod *)list->data;
5728 g_list_free (di->array_methods);
5729 if (di->gen_params) {
5730 for (i = 0; i < di->gen_params->len; i++) {
5731 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5732 mono_gc_deregister_root ((char*) &entry->gparam);
5735 g_ptr_array_free (di->gen_params, TRUE);
5737 if (di->token_fixups)
5738 mono_g_hash_table_destroy (di->token_fixups);
5739 if (di->method_to_table_idx)
5740 g_hash_table_destroy (di->method_to_table_idx);
5741 if (di->field_to_table_idx)
5742 g_hash_table_destroy (di->field_to_table_idx);
5743 if (di->method_aux_hash)
5744 g_hash_table_destroy (di->method_aux_hash);
5745 if (di->vararg_aux_hash)
5746 g_hash_table_destroy (di->vararg_aux_hash);
5747 g_free (di->strong_name);
5748 g_free (di->win32_res);
5750 g_free (di->public_key);
5752 /*g_print ("string heap destroy for image %p\n", di);*/
5753 mono_dynamic_stream_reset (&di->sheap);
5754 mono_dynamic_stream_reset (&di->code);
5755 mono_dynamic_stream_reset (&di->resources);
5756 mono_dynamic_stream_reset (&di->us);
5757 mono_dynamic_stream_reset (&di->blob);
5758 mono_dynamic_stream_reset (&di->tstream);
5759 mono_dynamic_stream_reset (&di->guid);
5760 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5761 g_free (di->tables [i].values);
5764 dynamic_images_lock ();
5767 g_ptr_array_remove (dynamic_images, di);
5769 dynamic_images_unlock ();
5772 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5774 mono_dynamic_image_free_image (MonoDynamicImage *image)
5776 /* See create_dynamic_mono_image () */
5778 /* Allocated using GC_MALLOC */
5784 #ifndef DISABLE_REFLECTION_EMIT
5787 * mono_image_basic_init:
5788 * @assembly: an assembly builder object
5790 * Create the MonoImage that represents the assembly builder and setup some
5791 * of the helper hash table and the basic metadata streams.
5794 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5796 MonoDynamicAssembly *assembly;
5797 MonoDynamicImage *image;
5798 MonoDomain *domain = mono_object_domain (assemblyb);
5800 if (assemblyb->dynamic_assembly)
5804 /* assembly->assembly.image might be GC allocated */
5805 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5807 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5810 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5812 assembly->assembly.ref_count = 1;
5813 assembly->assembly.dynamic = TRUE;
5814 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5815 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5816 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5817 if (assemblyb->culture)
5818 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5820 assembly->assembly.aname.culture = g_strdup ("");
5822 if (assemblyb->version) {
5823 char *vstr = mono_string_to_utf8 (assemblyb->version);
5824 char **version = g_strsplit (vstr, ".", 4);
5825 char **parts = version;
5826 assembly->assembly.aname.major = atoi (*parts++);
5827 assembly->assembly.aname.minor = atoi (*parts++);
5828 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5829 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5831 g_strfreev (version);
5834 assembly->assembly.aname.major = 0;
5835 assembly->assembly.aname.minor = 0;
5836 assembly->assembly.aname.build = 0;
5837 assembly->assembly.aname.revision = 0;
5840 assembly->run = assemblyb->access != 2;
5841 assembly->save = assemblyb->access != 1;
5842 assembly->domain = domain;
5844 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5845 image->initial_image = TRUE;
5846 assembly->assembly.aname.name = image->image.name;
5847 assembly->assembly.image = &image->image;
5848 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5849 /* -1 to correct for the trailing NULL byte */
5850 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5851 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5853 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5856 mono_domain_assemblies_lock (domain);
5857 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5858 mono_domain_assemblies_unlock (domain);
5860 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5862 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5864 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5867 #endif /* !DISABLE_REFLECTION_EMIT */
5869 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5872 calc_section_size (MonoDynamicImage *assembly)
5876 /* alignment constraints */
5877 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5878 g_assert ((assembly->code.index % 4) == 0);
5879 assembly->meta_size += 3;
5880 assembly->meta_size &= ~3;
5881 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5882 g_assert ((assembly->resources.index % 4) == 0);
5884 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5885 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5888 if (assembly->win32_res) {
5889 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5891 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5892 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5896 assembly->sections [MONO_SECTION_RELOC].size = 12;
5897 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5907 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5911 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5913 ResTreeNode *t1 = (ResTreeNode*)a;
5914 ResTreeNode *t2 = (ResTreeNode*)b;
5916 return t1->id - t2->id;
5920 * resource_tree_create:
5922 * Organize the resources into a resource tree.
5924 static ResTreeNode *
5925 resource_tree_create (MonoArray *win32_resources)
5927 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5931 tree = g_new0 (ResTreeNode, 1);
5933 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5934 MonoReflectionWin32Resource *win32_res =
5935 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5939 /* FIXME: BUG: this stores managed references in unmanaged memory */
5940 lang_node = g_new0 (ResTreeNode, 1);
5941 lang_node->id = win32_res->lang_id;
5942 lang_node->win32_res = win32_res;
5944 /* Create type node if neccesary */
5946 for (l = tree->children; l; l = l->next)
5947 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5948 type_node = (ResTreeNode*)l->data;
5953 type_node = g_new0 (ResTreeNode, 1);
5954 type_node->id = win32_res->res_type;
5957 * The resource types have to be sorted otherwise
5958 * Windows Explorer can't display the version information.
5960 tree->children = g_slist_insert_sorted (tree->children,
5961 type_node, resource_tree_compare_by_id);
5964 /* Create res node if neccesary */
5966 for (l = type_node->children; l; l = l->next)
5967 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5968 res_node = (ResTreeNode*)l->data;
5973 res_node = g_new0 (ResTreeNode, 1);
5974 res_node->id = win32_res->res_id;
5975 type_node->children = g_slist_append (type_node->children, res_node);
5978 res_node->children = g_slist_append (res_node->children, lang_node);
5985 * resource_tree_encode:
5987 * Encode the resource tree into the format used in the PE file.
5990 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5993 MonoPEResourceDir dir;
5994 MonoPEResourceDirEntry dir_entry;
5995 MonoPEResourceDataEntry data_entry;
5997 guint32 res_id_entries;
6000 * For the format of the resource directory, see the article
6001 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6005 memset (&dir, 0, sizeof (dir));
6006 memset (&dir_entry, 0, sizeof (dir_entry));
6007 memset (&data_entry, 0, sizeof (data_entry));
6009 g_assert (sizeof (dir) == 16);
6010 g_assert (sizeof (dir_entry) == 8);
6011 g_assert (sizeof (data_entry) == 16);
6013 node->offset = p - begin;
6015 /* IMAGE_RESOURCE_DIRECTORY */
6016 res_id_entries = g_slist_length (node->children);
6017 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6019 memcpy (p, &dir, sizeof (dir));
6022 /* Reserve space for entries */
6024 p += sizeof (dir_entry) * res_id_entries;
6026 /* Write children */
6027 for (l = node->children; l; l = l->next) {
6028 ResTreeNode *child = (ResTreeNode*)l->data;
6030 if (child->win32_res) {
6033 child->offset = p - begin;
6035 /* IMAGE_RESOURCE_DATA_ENTRY */
6036 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6037 size = mono_array_length (child->win32_res->res_data);
6038 data_entry.rde_size = GUINT32_TO_LE (size);
6040 memcpy (p, &data_entry, sizeof (data_entry));
6041 p += sizeof (data_entry);
6043 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6046 resource_tree_encode (child, begin, p, &p);
6050 /* IMAGE_RESOURCE_ENTRY */
6051 for (l = node->children; l; l = l->next) {
6052 ResTreeNode *child = (ResTreeNode*)l->data;
6054 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6055 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6057 memcpy (entries, &dir_entry, sizeof (dir_entry));
6058 entries += sizeof (dir_entry);
6065 resource_tree_free (ResTreeNode * node)
6068 for (list = node->children; list; list = list->next)
6069 resource_tree_free ((ResTreeNode*)list->data);
6070 g_slist_free(node->children);
6075 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6080 MonoReflectionWin32Resource *win32_res;
6083 if (!assemblyb->win32_resources)
6087 * Resources are stored in a three level tree inside the PE file.
6088 * - level one contains a node for each type of resource
6089 * - level two contains a node for each resource
6090 * - level three contains a node for each instance of a resource for a
6091 * specific language.
6094 tree = resource_tree_create (assemblyb->win32_resources);
6096 /* Estimate the size of the encoded tree */
6098 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6099 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6100 size += mono_array_length (win32_res->res_data);
6102 /* Directory structure */
6103 size += mono_array_length (assemblyb->win32_resources) * 256;
6104 p = buf = (char *)g_malloc (size);
6106 resource_tree_encode (tree, p, p, &p);
6108 g_assert (p - buf <= size);
6110 assembly->win32_res = (char *)g_malloc (p - buf);
6111 assembly->win32_res_size = p - buf;
6112 memcpy (assembly->win32_res, buf, p - buf);
6115 resource_tree_free (tree);
6119 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6121 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6124 p += sizeof (MonoPEResourceDir);
6125 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6126 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6127 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6128 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6129 fixup_resource_directory (res_section, child, rva);
6131 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6132 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6135 p += sizeof (MonoPEResourceDirEntry);
6140 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6143 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6144 g_error ("WriteFile returned %d\n", GetLastError ());
6148 * mono_image_create_pefile:
6149 * @mb: a module builder object
6151 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6152 * assembly->pefile where it can be easily retrieved later in chunks.
6155 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6157 MonoMSDOSHeader *msdos;
6158 MonoDotNetHeader *header;
6159 MonoSectionTable *section;
6160 MonoCLIHeader *cli_header;
6161 guint32 size, image_size, virtual_base, text_offset;
6162 guint32 header_start, section_start, file_offset, virtual_offset;
6163 MonoDynamicImage *assembly;
6164 MonoReflectionAssemblyBuilder *assemblyb;
6165 MonoDynamicStream pefile_stream = {0};
6166 MonoDynamicStream *pefile = &pefile_stream;
6168 guint32 *rva, value;
6170 static const unsigned char msheader[] = {
6171 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6172 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6175 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6176 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6177 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6178 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6181 mono_error_init (error);
6183 assemblyb = mb->assemblyb;
6185 mono_image_basic_init (assemblyb);
6186 assembly = mb->dynamic_image;
6188 assembly->pe_kind = assemblyb->pe_kind;
6189 assembly->machine = assemblyb->machine;
6190 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6191 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6193 if (!mono_image_build_metadata (mb, error))
6197 if (mb->is_main && assemblyb->resources) {
6198 int len = mono_array_length (assemblyb->resources);
6199 for (i = 0; i < len; ++i)
6200 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6203 if (mb->resources) {
6204 int len = mono_array_length (mb->resources);
6205 for (i = 0; i < len; ++i)
6206 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6209 if (!build_compressed_metadata (assembly, error))
6213 assembly_add_win32_resources (assembly, assemblyb);
6215 nsections = calc_section_size (assembly);
6217 /* The DOS header and stub */
6218 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6219 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6221 /* the dotnet header */
6222 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6224 /* the section tables */
6225 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6227 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6228 virtual_offset = VIRT_ALIGN;
6231 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6232 if (!assembly->sections [i].size)
6235 file_offset += FILE_ALIGN - 1;
6236 file_offset &= ~(FILE_ALIGN - 1);
6237 virtual_offset += VIRT_ALIGN - 1;
6238 virtual_offset &= ~(VIRT_ALIGN - 1);
6240 assembly->sections [i].offset = file_offset;
6241 assembly->sections [i].rva = virtual_offset;
6243 file_offset += assembly->sections [i].size;
6244 virtual_offset += assembly->sections [i].size;
6245 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6248 file_offset += FILE_ALIGN - 1;
6249 file_offset &= ~(FILE_ALIGN - 1);
6251 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6253 /* back-patch info */
6254 msdos = (MonoMSDOSHeader*)pefile->data;
6255 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6257 header = (MonoDotNetHeader*)(pefile->data + header_start);
6258 header->pesig [0] = 'P';
6259 header->pesig [1] = 'E';
6261 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6262 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6263 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6264 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6265 if (assemblyb->pekind == 1) {
6267 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6270 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6273 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6275 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6276 header->pe.pe_major = 6;
6277 header->pe.pe_minor = 0;
6278 size = assembly->sections [MONO_SECTION_TEXT].size;
6279 size += FILE_ALIGN - 1;
6280 size &= ~(FILE_ALIGN - 1);
6281 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6282 size = assembly->sections [MONO_SECTION_RSRC].size;
6283 size += FILE_ALIGN - 1;
6284 size &= ~(FILE_ALIGN - 1);
6285 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6286 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6287 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6288 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6289 /* pe_rva_entry_point always at the beginning of the text section */
6290 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6292 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6293 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6294 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6295 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6296 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6297 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6298 size = section_start;
6299 size += FILE_ALIGN - 1;
6300 size &= ~(FILE_ALIGN - 1);
6301 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6303 size += VIRT_ALIGN - 1;
6304 size &= ~(VIRT_ALIGN - 1);
6305 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6308 // Translate the PEFileKind value to the value expected by the Windows loader
6314 // PEFileKinds.Dll == 1
6315 // PEFileKinds.ConsoleApplication == 2
6316 // PEFileKinds.WindowApplication == 3
6319 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6320 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6322 if (assemblyb->pekind == 3)
6327 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6329 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6330 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6331 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6332 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6333 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6334 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6336 /* fill data directory entries */
6338 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6339 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6341 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6342 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6344 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6345 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6346 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6347 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6348 /* patch entrypoint name */
6349 if (assemblyb->pekind == 1)
6350 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6352 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6353 /* patch imported function RVA name */
6354 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6355 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6357 /* the import table */
6358 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6359 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6360 /* patch imported dll RVA name and other entries in the dir */
6361 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6362 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6363 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6364 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6365 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6366 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6368 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6369 value = (assembly->text_rva + assembly->imp_names_offset);
6370 *p++ = (value) & 0xff;
6371 *p++ = (value >> 8) & (0xff);
6372 *p++ = (value >> 16) & (0xff);
6373 *p++ = (value >> 24) & (0xff);
6375 /* the CLI header info */
6376 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6377 cli_header->ch_size = GUINT32_FROM_LE (72);
6378 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6379 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6380 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6381 if (assemblyb->entry_point) {
6382 guint32 table_idx = 0;
6383 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6384 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6385 table_idx = methodb->table_idx;
6387 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6389 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6391 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6393 /* The embedded managed resources */
6394 text_offset = assembly->text_rva + assembly->code.index;
6395 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6396 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6397 text_offset += assembly->resources.index;
6398 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6399 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6400 text_offset += assembly->meta_size;
6401 if (assembly->strong_name_size) {
6402 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6403 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6404 text_offset += assembly->strong_name_size;
6407 /* write the section tables and section content */
6408 section = (MonoSectionTable*)(pefile->data + section_start);
6409 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6410 static const char section_names [][7] = {
6411 ".text", ".rsrc", ".reloc"
6413 if (!assembly->sections [i].size)
6415 strcpy (section->st_name, section_names [i]);
6416 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6417 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6418 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6419 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6420 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6421 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6422 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6426 checked_write_file (file, pefile->data, pefile->index);
6428 mono_dynamic_stream_reset (pefile);
6430 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6431 if (!assembly->sections [i].size)
6434 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6435 g_error ("SetFilePointer returned %d\n", GetLastError ());
6438 case MONO_SECTION_TEXT:
6439 /* patch entry point */
6440 p = (guchar*)(assembly->code.data + 2);
6441 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6442 *p++ = (value) & 0xff;
6443 *p++ = (value >> 8) & 0xff;
6444 *p++ = (value >> 16) & 0xff;
6445 *p++ = (value >> 24) & 0xff;
6447 checked_write_file (file, assembly->code.data, assembly->code.index);
6448 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6449 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6450 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6453 g_free (assembly->image.raw_metadata);
6455 case MONO_SECTION_RELOC: {
6459 guint16 type_and_offset;
6463 g_assert (sizeof (reloc) == 12);
6465 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6466 reloc.block_size = GUINT32_FROM_LE (12);
6469 * the entrypoint is always at the start of the text section
6470 * 3 is IMAGE_REL_BASED_HIGHLOW
6471 * 2 is patch_size_rva - text_rva
6473 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6476 checked_write_file (file, &reloc, sizeof (reloc));
6480 case MONO_SECTION_RSRC:
6481 if (assembly->win32_res) {
6483 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6484 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6485 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6489 g_assert_not_reached ();
6493 /* check that the file is properly padded */
6494 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6495 g_error ("SetFilePointer returned %d\n", GetLastError ());
6496 if (! SetEndOfFile (file))
6497 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6499 mono_dynamic_stream_reset (&assembly->code);
6500 mono_dynamic_stream_reset (&assembly->us);
6501 mono_dynamic_stream_reset (&assembly->blob);
6502 mono_dynamic_stream_reset (&assembly->guid);
6503 mono_dynamic_stream_reset (&assembly->sheap);
6505 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6506 g_hash_table_destroy (assembly->blob_cache);
6507 assembly->blob_cache = NULL;
6512 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6515 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6517 g_assert_not_reached ();
6520 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6522 #ifndef DISABLE_REFLECTION_EMIT
6524 MonoReflectionModule *
6525 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6528 MonoReflectionModule *result = NULL;
6531 MonoImageOpenStatus status;
6532 MonoDynamicAssembly *assembly;
6533 guint32 module_count;
6534 MonoImage **new_modules;
6535 gboolean *new_modules_loaded;
6537 name = mono_string_to_utf8 (fileName);
6539 image = mono_image_open (name, &status);
6542 if (status == MONO_IMAGE_ERROR_ERRNO)
6543 exc = mono_get_exception_file_not_found (fileName);
6545 exc = mono_get_exception_bad_image_format (name);
6547 mono_raise_exception (exc);
6552 assembly = ab->dynamic_assembly;
6553 image->assembly = (MonoAssembly*)assembly;
6555 module_count = image->assembly->image->module_count;
6556 new_modules = g_new0 (MonoImage *, module_count + 1);
6557 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6559 if (image->assembly->image->modules)
6560 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6561 if (image->assembly->image->modules_loaded)
6562 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6563 new_modules [module_count] = image;
6564 new_modules_loaded [module_count] = TRUE;
6565 mono_image_addref (image);
6567 g_free (image->assembly->image->modules);
6568 image->assembly->image->modules = new_modules;
6569 image->assembly->image->modules_loaded = new_modules_loaded;
6570 image->assembly->image->module_count ++;
6572 mono_assembly_load_references (image, &status);
6574 mono_image_close (image);
6575 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6578 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6579 mono_error_raise_exception (&error); /* FIXME don't raise here */
6583 #endif /* DISABLE_REFLECTION_EMIT */
6586 * We need to return always the same object for MethodInfo, FieldInfo etc..
6587 * but we need to consider the reflected type.
6588 * type uses a different hash, since it uses custom hash/equal functions.
6593 MonoClass *refclass;
6597 reflected_equal (gconstpointer a, gconstpointer b) {
6598 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6599 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6601 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6605 reflected_hash (gconstpointer a) {
6606 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6607 return mono_aligned_addr_hash (ea->item);
6610 #define CHECK_OBJECT(t,p,k) \
6616 mono_domain_lock (domain); \
6617 if (!domain->refobject_hash) \
6618 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"); \
6619 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6620 mono_domain_unlock (domain); \
6623 mono_domain_unlock (domain); \
6626 #ifdef HAVE_BOEHM_GC
6627 /* ReflectedEntry doesn't need to be GC tracked */
6628 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6629 #define FREE_REFENTRY(entry) g_free ((entry))
6630 #define REFENTRY_REQUIRES_CLEANUP
6632 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6634 #define FREE_REFENTRY(entry)
6637 #define CACHE_OBJECT(t,p,o,k) \
6640 ReflectedEntry pe; \
6642 pe.refclass = (k); \
6643 mono_domain_lock (domain); \
6644 if (!domain->refobject_hash) \
6645 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"); \
6646 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6648 ReflectedEntry *e = ALLOC_REFENTRY; \
6650 e->refclass = (k); \
6651 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6654 mono_domain_unlock (domain); \
6659 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6661 mono_domain_lock (domain);
6662 if (domain->refobject_hash) {
6664 gpointer orig_pe, orig_value;
6667 pe.refclass = klass;
6668 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6669 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6670 FREE_REFENTRY (orig_pe);
6673 mono_domain_unlock (domain);
6676 #ifdef REFENTRY_REQUIRES_CLEANUP
6678 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6680 FREE_REFENTRY (key);
6685 mono_reflection_cleanup_domain (MonoDomain *domain)
6687 if (domain->refobject_hash) {
6688 /*let's avoid scanning the whole hashtable if not needed*/
6689 #ifdef REFENTRY_REQUIRES_CLEANUP
6690 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6692 mono_g_hash_table_destroy (domain->refobject_hash);
6693 domain->refobject_hash = NULL;
6697 #ifndef DISABLE_REFLECTION_EMIT
6699 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6701 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6705 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6707 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6711 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6713 MonoDynamicImage *image = moduleb->dynamic_image;
6714 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6718 MonoImage **new_modules;
6720 char *name, *fqname;
6722 * FIXME: we already created an image in mono_image_basic_init (), but
6723 * we don't know which module it belongs to, since that is only
6724 * determined at assembly save time.
6726 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6727 name = mono_string_to_utf8 (ab->name);
6728 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6729 if (!mono_error_ok (&error)) {
6731 mono_error_raise_exception (&error);
6733 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6735 moduleb->module.image = &image->image;
6736 moduleb->dynamic_image = image;
6737 register_module (mono_object_domain (moduleb), moduleb, image);
6739 /* register the module with the assembly */
6740 ass = ab->dynamic_assembly->assembly.image;
6741 module_count = ass->module_count;
6742 new_modules = g_new0 (MonoImage *, module_count + 1);
6745 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6746 new_modules [module_count] = &image->image;
6747 mono_image_addref (&image->image);
6749 g_free (ass->modules);
6750 ass->modules = new_modules;
6751 ass->module_count ++;
6756 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6758 MonoDynamicImage *image = moduleb->dynamic_image;
6760 g_assert (type->type);
6761 image->wrappers_type = mono_class_from_mono_type (type->type);
6767 * mono_assembly_get_object:
6768 * @domain: an app domain
6769 * @assembly: an assembly
6771 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6773 MonoReflectionAssembly*
6774 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6777 MonoReflectionAssembly *result;
6778 result = mono_assembly_get_object_checked (domain, assembly, &error);
6779 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6783 * mono_assembly_get_object_checked:
6784 * @domain: an app domain
6785 * @assembly: an assembly
6787 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6789 MonoReflectionAssembly*
6790 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6792 MonoReflectionAssembly *res;
6794 mono_error_init (error);
6796 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6797 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6800 res->assembly = assembly;
6802 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6807 MonoReflectionModule*
6808 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6811 MonoReflectionModule *result;
6812 result = mono_module_get_object_checked (domain, image, &error);
6813 mono_error_raise_exception (&error);
6817 MonoReflectionModule*
6818 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6820 MonoReflectionModule *res;
6823 mono_error_init (error);
6824 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6825 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6830 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6833 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6835 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6836 basename = g_path_get_basename (image->name);
6837 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6838 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6842 if (image->assembly->image == image) {
6843 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6847 if (image->assembly->image->modules) {
6848 for (i = 0; i < image->assembly->image->module_count; i++) {
6849 if (image->assembly->image->modules [i] == image)
6850 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6852 g_assert (res->token);
6856 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6859 MonoReflectionModule*
6860 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6863 MonoReflectionModule *result;
6864 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6865 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6869 MonoReflectionModule*
6870 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6872 MonoReflectionModule *res;
6873 MonoTableInfo *table;
6874 guint32 cols [MONO_FILE_SIZE];
6876 guint32 i, name_idx;
6879 mono_error_init (error);
6881 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6885 table = &image->tables [MONO_TABLE_FILE];
6886 g_assert (table_index < table->rows);
6887 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6890 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6893 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6894 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6896 /* Check whenever the row has a corresponding row in the moduleref table */
6897 table = &image->tables [MONO_TABLE_MODULEREF];
6898 for (i = 0; i < table->rows; ++i) {
6899 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6900 val = mono_metadata_string_heap (image, name_idx);
6901 if (strcmp (val, name) == 0)
6902 res->image = image->modules [i];
6905 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6906 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6907 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6908 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6909 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6915 verify_safe_for_managed_space (MonoType *type)
6917 switch (type->type) {
6919 case MONO_TYPE_ARRAY:
6920 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6922 return verify_safe_for_managed_space (type->data.type);
6923 case MONO_TYPE_SZARRAY:
6924 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6925 case MONO_TYPE_GENERICINST: {
6926 MonoGenericInst *inst = type->data.generic_class->inst;
6930 for (i = 0; i < inst->type_argc; ++i)
6931 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6937 case MONO_TYPE_MVAR:
6945 mono_type_normalize (MonoType *type)
6948 MonoGenericClass *gclass;
6949 MonoGenericInst *ginst;
6951 MonoGenericContainer *gcontainer;
6952 MonoType **argv = NULL;
6953 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6955 if (type->type != MONO_TYPE_GENERICINST)
6958 gclass = type->data.generic_class;
6959 ginst = gclass->context.class_inst;
6960 if (!ginst->is_open)
6963 gtd = gclass->container_class;
6964 gcontainer = gtd->generic_container;
6965 argv = g_newa (MonoType*, ginst->type_argc);
6967 for (i = 0; i < ginst->type_argc; ++i) {
6968 MonoType *t = ginst->type_argv [i], *norm;
6969 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6970 is_denorm_gtd = FALSE;
6971 norm = mono_type_normalize (t);
6974 requires_rebind = TRUE;
6978 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6980 if (requires_rebind) {
6981 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6982 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6988 * mono_type_get_object:
6989 * @domain: an app domain
6992 * Return an System.MonoType object representing the type @type.
6995 mono_type_get_object (MonoDomain *domain, MonoType *type)
6998 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6999 mono_error_raise_exception (&error);
7005 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7007 MonoType *norm_type;
7008 MonoReflectionType *res;
7011 mono_error_init (error);
7013 klass = mono_class_from_mono_type (type);
7015 /*we must avoid using @type as it might have come
7016 * from a mono_metadata_type_dup and the caller
7017 * expects that is can be freed.
7018 * Using the right type from
7020 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7022 /* void is very common */
7023 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7024 return (MonoReflectionType*)domain->typeof_void;
7027 * If the vtable of the given class was already created, we can use
7028 * the MonoType from there and avoid all locking and hash table lookups.
7030 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7031 * that the resulting object is different.
7033 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7034 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7035 if (vtable && vtable->type)
7036 return (MonoReflectionType *)vtable->type;
7039 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7040 mono_domain_lock (domain);
7041 if (!domain->type_hash)
7042 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7043 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7044 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7045 mono_domain_unlock (domain);
7046 mono_loader_unlock ();
7050 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7051 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7052 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7053 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7054 * artifact of how generics are encoded and should be transparent to managed code so we
7055 * need to weed out this diference when retrieving managed System.Type objects.
7057 norm_type = mono_type_normalize (type);
7058 if (norm_type != type) {
7059 res = mono_type_get_object_checked (domain, norm_type, error);
7060 if (!mono_error_ok (error))
7062 mono_g_hash_table_insert (domain->type_hash, type, res);
7063 mono_domain_unlock (domain);
7064 mono_loader_unlock ();
7068 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7069 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7072 if (!verify_safe_for_managed_space (type)) {
7073 mono_domain_unlock (domain);
7074 mono_loader_unlock ();
7075 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7079 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7080 gboolean is_type_done = TRUE;
7081 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7082 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7083 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7085 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7086 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7088 if (gparam->owner && gparam->owner->is_method) {
7089 MonoMethod *method = gparam->owner->owner.method;
7090 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7091 is_type_done = FALSE;
7092 } else if (gparam->owner && !gparam->owner->is_method) {
7093 MonoClass *klass = gparam->owner->owner.klass;
7094 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7095 is_type_done = FALSE;
7099 /* g_assert_not_reached (); */
7100 /* should this be considered an error condition? */
7101 if (is_type_done && !type->byref) {
7102 mono_domain_unlock (domain);
7103 mono_loader_unlock ();
7104 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7107 /* This is stored in vtables/JITted code so it has to be pinned */
7108 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7109 if (!mono_error_ok (error))
7113 mono_g_hash_table_insert (domain->type_hash, type, res);
7115 if (type->type == MONO_TYPE_VOID)
7116 domain->typeof_void = (MonoObject*)res;
7118 mono_domain_unlock (domain);
7119 mono_loader_unlock ();
7124 * mono_method_get_object:
7125 * @domain: an app domain
7127 * @refclass: the reflected type (can be NULL)
7129 * Return an System.Reflection.MonoMethod object representing the method @method.
7131 MonoReflectionMethod*
7132 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7135 MonoReflectionMethod *ret = NULL;
7136 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7137 mono_error_raise_exception (&error);
7142 * mono_method_get_object_checked:
7143 * @domain: an app domain
7145 * @refclass: the reflected type (can be NULL)
7146 * @error: set on error.
7148 * Return an System.Reflection.MonoMethod object representing the method @method.
7149 * Returns NULL and sets @error on error.
7151 MonoReflectionMethod*
7152 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7155 * We use the same C representation for methods and constructors, but the type
7156 * name in C# is different.
7158 MonoReflectionType *rt;
7160 MonoReflectionMethod *ret;
7162 mono_error_init (error);
7164 if (method->is_inflated) {
7165 MonoReflectionGenericMethod *gret;
7168 refclass = method->klass;
7169 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7170 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7171 klass = mono_class_get_mono_generic_cmethod_class ();
7173 klass = mono_class_get_mono_generic_method_class ();
7175 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7176 if (!mono_error_ok (error))
7178 gret->method.method = method;
7180 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7182 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7183 if (!mono_error_ok (error))
7186 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7188 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7192 refclass = method->klass;
7194 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7195 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7196 klass = mono_class_get_mono_cmethod_class ();
7199 klass = mono_class_get_mono_method_class ();
7201 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7202 if (!mono_error_ok (error))
7204 ret->method = method;
7206 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7207 if (!mono_error_ok (error))
7210 MONO_OBJECT_SETREF (ret, reftype, rt);
7212 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7215 g_assert (!mono_error_ok (error));
7220 * mono_method_clear_object:
7222 * Clear the cached reflection objects for the dynamic method METHOD.
7225 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7228 g_assert (method_is_dynamic (method));
7230 klass = method->klass;
7232 clear_cached_object (domain, method, klass);
7233 klass = klass->parent;
7235 /* Added by mono_param_get_objects () */
7236 clear_cached_object (domain, &(method->signature), NULL);
7237 klass = method->klass;
7239 clear_cached_object (domain, &(method->signature), klass);
7240 klass = klass->parent;
7245 * mono_field_get_object:
7246 * @domain: an app domain
7250 * Return an System.Reflection.MonoField object representing the field @field
7253 MonoReflectionField*
7254 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7257 MonoReflectionField *result;
7258 result = mono_field_get_object_checked (domain, klass, field, &error);
7259 mono_error_raise_exception (&error);
7264 * mono_field_get_object_checked:
7265 * @domain: an app domain
7268 * @error: set on error
7270 * Return an System.Reflection.MonoField object representing the field @field
7271 * in class @klass. On error, returns NULL and sets @error.
7273 MonoReflectionField*
7274 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7276 MonoReflectionType *rt;
7277 MonoReflectionField *res;
7279 mono_error_init (error);
7281 CHECK_OBJECT (MonoReflectionField *, field, klass);
7282 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7287 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7289 if (is_field_on_inst (field)) {
7290 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7292 rt = mono_type_get_object_checked (domain, field->type, error);
7293 if (!mono_error_ok (error))
7296 MONO_OBJECT_SETREF (res, type, rt);
7299 rt = mono_type_get_object_checked (domain, field->type, error);
7300 if (!mono_error_ok (error))
7303 MONO_OBJECT_SETREF (res, type, rt);
7305 res->attrs = mono_field_get_flags (field);
7307 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7311 * mono_property_get_object:
7312 * @domain: an app domain
7314 * @property: a property
7316 * Return an System.Reflection.MonoProperty object representing the property @property
7319 MonoReflectionProperty*
7320 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7323 MonoReflectionProperty *result;
7324 result = mono_property_get_object_checked (domain, klass, property, &error);
7325 mono_error_raise_exception (&error);
7330 * mono_property_get_object:
7331 * @domain: an app domain
7333 * @property: a property
7334 * @error: set on error
7336 * Return an System.Reflection.MonoProperty object representing the property @property
7337 * in class @klass. On error returns NULL and sets @error.
7339 MonoReflectionProperty*
7340 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7342 MonoReflectionProperty *res;
7344 mono_error_init (error);
7346 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7347 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7351 res->property = property;
7352 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7356 * mono_event_get_object:
7357 * @domain: an app domain
7361 * Return an System.Reflection.MonoEvent object representing the event @event
7364 MonoReflectionEvent*
7365 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7368 MonoReflectionEvent *result;
7369 result = mono_event_get_object_checked (domain, klass, event, &error);
7370 mono_error_raise_exception (&error);
7375 * mono_event_get_object_checked:
7376 * @domain: an app domain
7379 * @error: set on error
7381 * Return an System.Reflection.MonoEvent object representing the event @event
7382 * in class @klass. On failure sets @error and returns NULL
7384 MonoReflectionEvent*
7385 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7387 MonoReflectionEvent *res;
7388 MonoReflectionMonoEvent *mono_event;
7390 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7391 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7394 mono_event->klass = klass;
7395 mono_event->event = event;
7396 res = (MonoReflectionEvent*)mono_event;
7397 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7401 * mono_get_reflection_missing_object:
7402 * @domain: Domain where the object lives
7404 * Returns the System.Reflection.Missing.Value singleton object
7405 * (of type System.Reflection.Missing).
7407 * Used as the value for ParameterInfo.DefaultValue when Optional
7411 mono_get_reflection_missing_object (MonoDomain *domain)
7414 static MonoClassField *missing_value_field = NULL;
7416 if (!missing_value_field) {
7417 MonoClass *missing_klass;
7418 missing_klass = mono_class_get_missing_class ();
7419 mono_class_init (missing_klass);
7420 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7421 g_assert (missing_value_field);
7423 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7429 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7432 *dbnull = mono_get_dbnull_object (domain);
7437 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7439 if (!*reflection_missing)
7440 *reflection_missing = mono_get_reflection_missing_object (domain);
7441 return *reflection_missing;
7445 * mono_param_get_objects:
7446 * @domain: an app domain
7449 * Return an System.Reflection.ParameterInfo array object representing the parameters
7450 * in the method @method.
7453 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7455 static MonoClass *System_Reflection_ParameterInfo;
7456 static MonoClass *System_Reflection_ParameterInfo_array;
7457 MonoArray *res = NULL;
7458 MonoReflectionMethod *member = NULL;
7459 MonoReflectionParameter *param = NULL;
7460 char **names = NULL, **blobs = NULL;
7461 guint32 *types = NULL;
7462 MonoType *type = NULL;
7463 MonoObject *dbnull = NULL;
7464 MonoObject *missing = NULL;
7465 MonoMarshalSpec **mspecs = NULL;
7466 MonoMethodSignature *sig = NULL;
7467 MonoVTable *pinfo_vtable;
7468 MonoReflectionType *rt;
7471 mono_error_init (error);
7473 if (!System_Reflection_ParameterInfo_array) {
7476 klass = mono_class_get_mono_parameter_info_class ();
7478 mono_memory_barrier ();
7479 System_Reflection_ParameterInfo = klass;
7482 klass = mono_array_class_get (klass, 1);
7483 mono_memory_barrier ();
7484 System_Reflection_ParameterInfo_array = klass;
7487 sig = mono_method_signature_checked (method, error);
7488 if (!mono_error_ok (error))
7491 if (!sig->param_count) {
7492 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7499 /* Note: the cache is based on the address of the signature into the method
7500 * since we already cache MethodInfos with the method as keys.
7502 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7504 member = mono_method_get_object_checked (domain, method, refclass, error);
7507 names = g_new (char *, sig->param_count);
7508 mono_method_get_param_names (method, (const char **) names);
7510 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7511 mono_method_get_marshal_info (method, mspecs);
7513 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7517 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7518 for (i = 0; i < sig->param_count; ++i) {
7519 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7523 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7527 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7529 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7531 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7533 param->PositionImpl = i;
7534 param->AttrsImpl = sig->params [i]->attrs;
7536 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7537 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7538 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7540 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7544 blobs = g_new0 (char *, sig->param_count);
7545 types = g_new0 (guint32, sig->param_count);
7546 get_default_param_value_blobs (method, blobs, types);
7549 /* Build MonoType for the type from the Constant Table */
7551 type = g_new0 (MonoType, 1);
7552 type->type = (MonoTypeEnum)types [i];
7553 type->data.klass = NULL;
7554 if (types [i] == MONO_TYPE_CLASS)
7555 type->data.klass = mono_defaults.object_class;
7556 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7557 /* For enums, types [i] contains the base type */
7559 type->type = MONO_TYPE_VALUETYPE;
7560 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7562 type->data.klass = mono_class_from_mono_type (type);
7564 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7567 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7569 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7570 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7571 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7572 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7574 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7579 if (mspecs [i + 1]) {
7580 MonoReflectionMarshalAsAttribute* mobj;
7581 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7584 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7587 mono_array_setref (res, i, param);
7597 for (i = sig->param_count; i >= 0; i--) {
7599 mono_metadata_free_marshal_spec (mspecs [i]);
7607 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7611 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7614 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7615 mono_error_assert_ok (&error);
7620 * mono_method_body_get_object:
7621 * @domain: an app domain
7624 * Return an System.Reflection.MethodBody object representing the method @method.
7626 MonoReflectionMethodBody*
7627 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7630 MonoReflectionMethodBody *ret;
7631 MonoMethodHeader *header;
7633 MonoReflectionType *rt;
7634 guint32 method_rva, local_var_sig_token;
7636 unsigned char format, flags;
7639 /* for compatibility with .net */
7640 if (method_is_dynamic (method))
7641 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7643 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7645 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7646 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7647 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7648 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7649 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7652 image = method->klass->image;
7653 header = mono_method_get_header_checked (method, &error);
7654 mono_error_raise_exception (&error); /* FIXME don't raise here */
7656 if (!image_is_dynamic (image)) {
7657 /* Obtain local vars signature token */
7658 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7659 ptr = mono_image_rva_map (image, method_rva);
7660 flags = *(const unsigned char *) ptr;
7661 format = flags & METHOD_HEADER_FORMAT_MASK;
7663 case METHOD_HEADER_TINY_FORMAT:
7664 local_var_sig_token = 0;
7666 case METHOD_HEADER_FAT_FORMAT:
7670 local_var_sig_token = read32 (ptr);
7673 g_assert_not_reached ();
7676 local_var_sig_token = 0; //FIXME
7678 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7679 mono_error_raise_exception (&error); /* FIXME don't raise here */
7681 ret->init_locals = header->init_locals;
7682 ret->max_stack = header->max_stack;
7683 ret->local_var_sig_token = local_var_sig_token;
7684 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7685 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7688 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7689 for (i = 0; i < header->num_locals; ++i) {
7690 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7691 mono_error_raise_exception (&error); /* FIXME don't raise here */
7693 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7694 mono_error_raise_exception (&error); /* FIXME don't raise here */
7696 MONO_OBJECT_SETREF (info, local_type, rt);
7698 info->is_pinned = header->locals [i]->pinned;
7699 info->local_index = i;
7700 mono_array_setref (ret->locals, i, info);
7704 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7705 for (i = 0; i < header->num_clauses; ++i) {
7706 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7707 mono_error_raise_exception (&error); /* FIXME don't raise here */
7708 MonoExceptionClause *clause = &header->clauses [i];
7710 info->flags = clause->flags;
7711 info->try_offset = clause->try_offset;
7712 info->try_length = clause->try_len;
7713 info->handler_offset = clause->handler_offset;
7714 info->handler_length = clause->handler_len;
7715 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7716 info->filter_offset = clause->data.filter_offset;
7717 else if (clause->data.catch_class) {
7718 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7719 mono_error_raise_exception (&error); /* FIXME don't raise here */
7721 MONO_OBJECT_SETREF (info, catch_type, rt);
7724 mono_array_setref (ret->clauses, i, info);
7727 mono_metadata_free_mh (header);
7728 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7733 * mono_get_dbnull_object:
7734 * @domain: Domain where the object lives
7736 * Returns the System.DBNull.Value singleton object
7738 * Used as the value for ParameterInfo.DefaultValue
7741 mono_get_dbnull_object (MonoDomain *domain)
7744 static MonoClassField *dbnull_value_field = NULL;
7746 if (!dbnull_value_field) {
7747 MonoClass *dbnull_klass;
7748 dbnull_klass = mono_class_get_dbnull_class ();
7749 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7750 g_assert (dbnull_value_field);
7752 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7758 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7760 guint32 param_index, i, lastp, crow = 0;
7761 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7764 MonoClass *klass = method->klass;
7765 MonoImage *image = klass->image;
7766 MonoMethodSignature *methodsig = mono_method_signature (method);
7768 MonoTableInfo *constt;
7769 MonoTableInfo *methodt;
7770 MonoTableInfo *paramt;
7772 if (!methodsig->param_count)
7775 mono_class_init (klass);
7777 if (image_is_dynamic (klass->image)) {
7778 MonoReflectionMethodAux *aux;
7779 if (method->is_inflated)
7780 method = ((MonoMethodInflated*)method)->declaring;
7781 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7782 if (aux && aux->param_defaults) {
7783 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7784 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7789 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7790 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7791 constt = &image->tables [MONO_TABLE_CONSTANT];
7793 idx = mono_method_get_index (method) - 1;
7794 g_assert (idx != -1);
7796 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7797 if (idx + 1 < methodt->rows)
7798 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7800 lastp = paramt->rows + 1;
7802 for (i = param_index; i < lastp; ++i) {
7805 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7806 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7808 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7811 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7816 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7817 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7818 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7825 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
7830 MonoType *basetype = type;
7832 mono_error_init (error);
7837 klass = mono_class_from_mono_type (type);
7838 if (klass->valuetype) {
7839 object = mono_object_new_checked (domain, klass, error);
7840 return_val_if_nok (error, NULL);
7841 retval = ((gchar *) object + sizeof (MonoObject));
7842 if (klass->enumtype)
7843 basetype = mono_class_enum_basetype (klass);
7848 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7855 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7858 gboolean quoted = FALSE;
7860 memset (assembly, 0, sizeof (MonoAssemblyName));
7861 assembly->culture = "";
7862 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7869 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7880 /* Remove trailing whitespace */
7882 while (*s && g_ascii_isspace (*s))
7885 while (g_ascii_isspace (*p))
7888 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7890 assembly->major = strtoul (p, &s, 10);
7891 if (s == p || *s != '.')
7894 assembly->minor = strtoul (p, &s, 10);
7895 if (s == p || *s != '.')
7898 assembly->build = strtoul (p, &s, 10);
7899 if (s == p || *s != '.')
7902 assembly->revision = strtoul (p, &s, 10);
7906 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7908 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7909 assembly->culture = "";
7912 assembly->culture = p;
7913 while (*p && *p != ',') {
7917 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7919 if (strncmp (p, "null", 4) == 0) {
7924 while (*p && *p != ',') {
7927 len = (p - start + 1);
7928 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7929 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7930 g_strlcpy ((char*)assembly->public_key_token, start, len);
7933 while (*p && *p != ',')
7937 while (g_ascii_isspace (*p) || *p == ',') {
7951 * mono_reflection_parse_type:
7954 * Parse a type name as accepted by the GetType () method and output the info
7955 * extracted in the info structure.
7956 * the name param will be mangled, so, make a copy before passing it to this function.
7957 * The fields in info will be valid until the memory pointed to by name is valid.
7959 * See also mono_type_get_name () below.
7961 * Returns: 0 on parse error.
7964 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7965 MonoTypeNameParse *info)
7967 char *start, *p, *w, *last_point, *startn;
7968 int in_modifiers = 0;
7969 int isbyref = 0, rank = 0, isptr = 0;
7971 start = p = w = name;
7973 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7974 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7975 info->name = info->name_space = NULL;
7976 info->nested = NULL;
7977 info->modifiers = NULL;
7978 info->type_arguments = NULL;
7980 /* last_point separates the namespace from the name */
7983 while (*p == ' ') p++, start++, w++, name++;
7988 *p = 0; /* NULL terminate the name */
7990 info->nested = g_list_append (info->nested, startn);
7991 /* we have parsed the nesting namespace + name */
7995 info->name_space = start;
7997 info->name = last_point + 1;
7999 info->name_space = (char *)"";
8027 info->name_space = start;
8029 info->name = last_point + 1;
8031 info->name_space = (char *)"";
8038 if (isbyref) /* only one level allowed by the spec */
8042 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8046 if (isbyref) /* pointer to ref not okay */
8048 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8053 if (isbyref) /* array of ref and generic ref are not okay */
8055 //Decide if it's an array of a generic argument list
8060 if (*p == ',' || *p == '*' || *p == ']') { //array
8068 else if (*p == '*') /* '*' means unknown lower bound */
8069 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8076 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8078 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8081 info->type_arguments = g_ptr_array_new ();
8083 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8084 gboolean fqname = FALSE;
8086 g_ptr_array_add (info->type_arguments, subinfo);
8088 while (*p == ' ') p++;
8094 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8097 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8098 if (fqname && (*p != ']')) {
8106 while (*p && (*p != ']'))
8114 if (g_ascii_isspace (*aname)) {
8121 !assembly_name_to_aname (&subinfo->assembly, aname))
8123 } else if (fqname && (*p == ']')) {
8145 if (g_ascii_isspace (*p)) {
8152 return 0; /* missing assembly name */
8153 if (!assembly_name_to_aname (&info->assembly, p))
8159 if (info->assembly.name)
8162 // *w = 0; /* terminate class name */
8164 if (!info->name || !*info->name)
8168 /* add other consistency checks */
8174 * mono_identifier_unescape_type_name_chars:
8175 * @identifier: the display name of a mono type
8178 * The name in internal form, that is without escaping backslashes.
8180 * The string is modified in place!
8183 mono_identifier_unescape_type_name_chars(char* identifier)
8188 for (w = r = identifier; *r != 0; r++)
8206 mono_identifier_unescape_info (MonoTypeNameParse* info);
8209 unescape_each_type_argument(void* data, void* user_data)
8211 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8212 mono_identifier_unescape_info (info);
8216 unescape_each_nested_name (void* data, void* user_data)
8218 char* nested_name = (char*) data;
8219 mono_identifier_unescape_type_name_chars(nested_name);
8223 * mono_identifier_unescape_info:
8225 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8229 * Destructively updates the info by unescaping the identifiers that
8230 * comprise the type namespace, name, nested types (if any) and
8231 * generic type arguments (if any).
8233 * The resulting info has the names in internal form.
8237 mono_identifier_unescape_info (MonoTypeNameParse *info)
8241 mono_identifier_unescape_type_name_chars(info->name_space);
8242 mono_identifier_unescape_type_name_chars(info->name);
8243 // but don't escape info->assembly
8244 if (info->type_arguments)
8245 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8247 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8251 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8253 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8255 mono_identifier_unescape_info (info);
8261 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8263 gboolean type_resolve = FALSE;
8265 MonoImage *rootimage = image;
8267 mono_error_init (error);
8269 if (info->assembly.name) {
8270 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8271 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8273 * This could happen in the AOT compiler case when the search hook is not
8276 assembly = image->assembly;
8278 /* then we must load the assembly ourselve - see #60439 */
8279 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8283 image = assembly->image;
8284 } else if (!image) {
8285 image = mono_defaults.corlib;
8288 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8289 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8290 mono_error_cleanup (error);
8291 image = mono_defaults.corlib;
8292 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8299 * mono_reflection_get_type_internal:
8301 * Returns: may return NULL on success, sets error on failure.
8304 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8309 gboolean bounded = FALSE;
8311 mono_error_init (error);
8313 image = mono_defaults.corlib;
8316 rootimage = mono_defaults.corlib;
8319 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8321 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8326 for (mod = info->nested; mod; mod = mod->next) {
8327 gpointer iter = NULL;
8331 mono_class_init (parent);
8333 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8335 char *nested_name, *nested_nspace;
8336 gboolean match = TRUE;
8338 lastp = strrchr ((const char *)mod->data, '.');
8340 /* Nested classes can have namespaces */
8343 nested_name = g_strdup (lastp + 1);
8344 nspace_len = lastp - (char*)mod->data;
8345 nested_nspace = (char *)g_malloc (nspace_len + 1);
8346 memcpy (nested_nspace, mod->data, nspace_len);
8347 nested_nspace [nspace_len] = '\0';
8350 nested_name = (char *)mod->data;
8351 nested_nspace = NULL;
8354 if (nested_nspace) {
8356 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8359 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8365 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8368 if (strcmp (klass->name, nested_name) != 0)
8373 g_free (nested_name);
8374 g_free (nested_nspace);
8386 if (info->type_arguments) {
8387 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8388 MonoReflectionType *the_type;
8392 for (i = 0; i < info->type_arguments->len; i++) {
8393 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8395 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8396 if (!type_args [i]) {
8402 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8406 instance = mono_reflection_bind_generic_parameters (
8407 the_type, info->type_arguments->len, type_args);
8413 klass = mono_class_from_mono_type (instance);
8416 for (mod = info->modifiers; mod; mod = mod->next) {
8417 modval = GPOINTER_TO_UINT (mod->data);
8418 if (!modval) { /* byref: must be last modifier */
8419 return &klass->this_arg;
8420 } else if (modval == -1) {
8421 klass = mono_ptr_class_get (&klass->byval_arg);
8422 } else if (modval == -2) {
8424 } else { /* array rank */
8425 klass = mono_bounded_array_class_get (klass, modval, bounded);
8429 return &klass->byval_arg;
8433 * mono_reflection_get_type:
8434 * @image: a metadata context
8435 * @info: type description structure
8436 * @ignorecase: flag for case-insensitive string compares
8437 * @type_resolve: whenever type resolve was already tried
8439 * Build a MonoType from the type description in @info.
8444 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8446 MonoType *result = mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve, &error);
8447 mono_error_raise_exception (&error); /* FIXME don't raise here */
8452 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8454 MonoReflectionAssemblyBuilder *abuilder;
8458 mono_error_init (error);
8459 g_assert (assembly_is_dynamic (assembly));
8460 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8464 /* Enumerate all modules */
8467 if (abuilder->modules) {
8468 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8469 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8470 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8473 if (!mono_error_ok (error))
8478 if (!type && abuilder->loaded_modules) {
8479 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8480 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8481 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8484 if (!mono_error_ok (error))
8493 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8496 MonoReflectionAssembly *assembly;
8500 mono_error_init (error);
8502 if (image && image_is_dynamic (image))
8503 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8505 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8507 return_val_if_nok (error, NULL);
8511 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8518 *type_resolve = TRUE;
8521 /* Reconstruct the type name */
8522 fullName = g_string_new ("");
8523 if (info->name_space && (info->name_space [0] != '\0'))
8524 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8526 g_string_printf (fullName, "%s", info->name);
8527 for (mod = info->nested; mod; mod = mod->next)
8528 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8530 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8531 if (!is_ok (error)) {
8532 g_string_free (fullName, TRUE);
8537 if (assembly_is_dynamic (assembly->assembly))
8538 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8539 info, ignorecase, error);
8541 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8542 info, ignorecase, error);
8544 g_string_free (fullName, TRUE);
8545 return_val_if_nok (error, NULL);
8550 mono_reflection_free_type_info (MonoTypeNameParse *info)
8552 g_list_free (info->modifiers);
8553 g_list_free (info->nested);
8555 if (info->type_arguments) {
8558 for (i = 0; i < info->type_arguments->len; i++) {
8559 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8561 mono_reflection_free_type_info (subinfo);
8562 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8566 g_ptr_array_free (info->type_arguments, TRUE);
8571 * mono_reflection_type_from_name:
8573 * @image: a metadata context (can be NULL).
8575 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8576 * it defaults to get the type from @image or, if @image is NULL or loading
8577 * from it fails, uses corlib.
8581 mono_reflection_type_from_name (char *name, MonoImage *image)
8584 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8585 mono_error_cleanup (&error);
8590 * mono_reflection_type_from_name_checked:
8592 * @image: a metadata context (can be NULL).
8593 * @error: set on errror.
8595 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8596 * it defaults to get the type from @image or, if @image is NULL or loading
8597 * from it fails, uses corlib. On failure returns NULL and sets @error.
8601 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8603 MonoType *type = NULL;
8604 MonoTypeNameParse info;
8607 mono_error_init (error);
8608 /* Make a copy since parse_type modifies its argument */
8609 tmp = g_strdup (name);
8611 /*g_print ("requested type %s\n", str);*/
8612 if (mono_reflection_parse_type (tmp, &info)) {
8613 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8614 if (!is_ok (error)) {
8616 mono_reflection_free_type_info (&info);
8622 mono_reflection_free_type_info (&info);
8627 * mono_reflection_get_token:
8629 * Return the metadata token of OBJ which should be an object
8630 * representing a metadata element.
8633 mono_reflection_get_token (MonoObject *obj)
8639 klass = obj->vtable->klass;
8641 if (strcmp (klass->name, "MethodBuilder") == 0) {
8642 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8644 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8645 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8646 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8648 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8649 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8650 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8652 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8653 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8654 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8655 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8656 } else if (strcmp (klass->name, "MonoType") == 0) {
8657 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8658 mono_error_raise_exception (&error); /* FIXME don't raise here */
8659 MonoClass *mc = mono_class_from_mono_type (type);
8660 if (!mono_class_init (mc))
8661 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8663 token = mc->type_token;
8664 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8665 strcmp (klass->name, "MonoMethod") == 0 ||
8666 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8667 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8668 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8669 if (m->method->is_inflated) {
8670 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8671 return inflated->declaring->token;
8673 token = m->method->token;
8675 } else if (strcmp (klass->name, "MonoField") == 0) {
8676 MonoReflectionField *f = (MonoReflectionField*)obj;
8678 if (is_field_on_inst (f->field)) {
8679 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8681 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8682 int field_index = f->field - dgclass->fields;
8685 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8686 obj = dgclass->field_objects [field_index];
8687 return mono_reflection_get_token (obj);
8690 token = mono_class_get_field_token (f->field);
8691 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8692 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8694 token = mono_class_get_property_token (p->property);
8695 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8696 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8698 token = mono_class_get_event_token (p->event);
8699 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8700 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8701 MonoClass *member_class = mono_object_class (p->MemberImpl);
8702 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8704 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8705 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8706 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8709 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8710 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8712 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8713 MonoException *ex = mono_get_exception_not_implemented (msg);
8715 mono_raise_exception (ex);
8722 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8726 int slen = mono_metadata_decode_value (p, &p);
8728 mono_error_init (error);
8730 n = (char *)g_memdup (p, slen + 1);
8732 t = mono_reflection_type_from_name_checked (n, image, error);
8734 char *msg = g_strdup (mono_error_get_message (error));
8735 mono_error_cleanup (error);
8736 /* We don't free n, it's consumed by mono_error */
8737 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8744 return mono_class_from_mono_type (t);
8748 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8750 int slen, type = t->type;
8751 MonoClass *tklass = t->data.klass;
8753 mono_error_init (error);
8759 case MONO_TYPE_BOOLEAN: {
8760 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8765 case MONO_TYPE_CHAR:
8767 case MONO_TYPE_I2: {
8768 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8773 #if SIZEOF_VOID_P == 4
8779 case MONO_TYPE_I4: {
8780 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8785 #if SIZEOF_VOID_P == 8
8786 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8790 case MONO_TYPE_I8: {
8791 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8796 case MONO_TYPE_R8: {
8797 double *val = (double *)g_malloc (sizeof (double));
8802 case MONO_TYPE_VALUETYPE:
8803 if (t->data.klass->enumtype) {
8804 type = mono_class_enum_basetype (t->data.klass)->type;
8807 MonoClass *k = t->data.klass;
8809 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8810 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8816 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8819 case MONO_TYPE_STRING:
8820 if (*p == (char)0xFF) {
8824 slen = mono_metadata_decode_value (p, &p);
8826 return mono_string_new_len (mono_domain_get (), p, slen);
8827 case MONO_TYPE_CLASS: {
8828 MonoReflectionType *rt;
8831 if (*p == (char)0xFF) {
8836 slen = mono_metadata_decode_value (p, &p);
8837 n = (char *)g_memdup (p, slen + 1);
8839 t = mono_reflection_type_from_name_checked (n, image, error);
8841 char *msg = g_strdup (mono_error_get_message (error));
8842 mono_error_cleanup (error);
8843 /* We don't free n, it's consumed by mono_error */
8844 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
8851 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8852 if (!mono_error_ok (error))
8857 case MONO_TYPE_OBJECT: {
8860 MonoClass *subc = NULL;
8865 } else if (subt == 0x0E) {
8866 type = MONO_TYPE_STRING;
8868 } else if (subt == 0x1D) {
8869 MonoType simple_type = {{0}};
8873 type = MONO_TYPE_SZARRAY;
8874 if (etype == 0x50) {
8875 tklass = mono_defaults.systemtype_class;
8876 } else if (etype == 0x55) {
8877 tklass = load_cattr_enum_type (image, p, &p, error);
8878 if (!mono_error_ok (error))
8882 /* See Partition II, Appendix B3 */
8883 etype = MONO_TYPE_OBJECT;
8884 simple_type.type = (MonoTypeEnum)etype;
8885 tklass = mono_class_from_mono_type (&simple_type);
8888 } else if (subt == 0x55) {
8891 slen = mono_metadata_decode_value (p, &p);
8892 n = (char *)g_memdup (p, slen + 1);
8894 t = mono_reflection_type_from_name_checked (n, image, error);
8896 char *msg = g_strdup (mono_error_get_message (error));
8897 mono_error_cleanup (error);
8898 /* We don't free n, it's consumed by mono_error */
8899 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
8905 subc = mono_class_from_mono_type (t);
8906 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8907 MonoType simple_type = {{0}};
8908 simple_type.type = (MonoTypeEnum)subt;
8909 subc = mono_class_from_mono_type (&simple_type);
8911 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8913 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8915 if (mono_error_ok (error)) {
8916 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8917 g_assert (!subc->has_references);
8918 if (mono_error_ok (error))
8919 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8925 case MONO_TYPE_SZARRAY: {
8927 guint32 i, alen, basetype;
8930 if (alen == 0xffffffff) {
8934 arr = mono_array_new (mono_domain_get(), tklass, alen);
8935 basetype = tklass->byval_arg.type;
8936 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8937 basetype = mono_class_enum_basetype (tklass)->type;
8942 case MONO_TYPE_BOOLEAN:
8943 for (i = 0; i < alen; i++) {
8944 MonoBoolean val = *p++;
8945 mono_array_set (arr, MonoBoolean, i, val);
8948 case MONO_TYPE_CHAR:
8951 for (i = 0; i < alen; i++) {
8952 guint16 val = read16 (p);
8953 mono_array_set (arr, guint16, i, val);
8960 for (i = 0; i < alen; i++) {
8961 guint32 val = read32 (p);
8962 mono_array_set (arr, guint32, i, val);
8967 for (i = 0; i < alen; i++) {
8970 mono_array_set (arr, double, i, val);
8976 for (i = 0; i < alen; i++) {
8977 guint64 val = read64 (p);
8978 mono_array_set (arr, guint64, i, val);
8982 case MONO_TYPE_CLASS:
8983 case MONO_TYPE_OBJECT:
8984 case MONO_TYPE_STRING:
8985 case MONO_TYPE_SZARRAY:
8986 for (i = 0; i < alen; i++) {
8987 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8988 if (!mono_error_ok (error))
8990 mono_array_setref (arr, i, item);
8994 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9000 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9006 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9008 static MonoMethod *ctor;
9010 void *params [2], *unboxed;
9012 mono_error_init (error);
9015 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9017 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9018 return_val_if_nok (error, NULL);
9021 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9022 return_val_if_nok (error, NULL);
9023 unboxed = mono_object_unbox (retval);
9025 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9026 return_val_if_nok (error, NULL);
9032 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9034 static MonoMethod *ctor;
9036 void *unboxed, *params [2];
9038 mono_error_init (error);
9041 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9044 params [1] = typedarg;
9045 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9046 return_val_if_nok (error, NULL);
9048 unboxed = mono_object_unbox (retval);
9050 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9051 return_val_if_nok (error, NULL);
9057 type_is_reference (MonoType *type)
9059 switch (type->type) {
9060 case MONO_TYPE_BOOLEAN:
9061 case MONO_TYPE_CHAR:
9074 case MONO_TYPE_VALUETYPE:
9082 free_param_data (MonoMethodSignature *sig, void **params) {
9084 for (i = 0; i < sig->param_count; ++i) {
9085 if (!type_is_reference (sig->params [i]))
9086 g_free (params [i]);
9091 * Find the field index in the metadata FieldDef table.
9094 find_field_index (MonoClass *klass, MonoClassField *field) {
9097 for (i = 0; i < klass->field.count; ++i) {
9098 if (field == &klass->fields [i])
9099 return klass->field.first + 1 + i;
9105 * Find the property index in the metadata Property table.
9108 find_property_index (MonoClass *klass, MonoProperty *property) {
9111 for (i = 0; i < klass->ext->property.count; ++i) {
9112 if (property == &klass->ext->properties [i])
9113 return klass->ext->property.first + 1 + i;
9119 * Find the event index in the metadata Event table.
9122 find_event_index (MonoClass *klass, MonoEvent *event) {
9125 for (i = 0; i < klass->ext->event.count; ++i) {
9126 if (event == &klass->ext->events [i])
9127 return klass->ext->event.first + 1 + i;
9133 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9135 const char *p = (const char*)data;
9137 guint32 i, j, num_named;
9139 void *params_buf [32];
9140 void **params = NULL;
9141 MonoMethodSignature *sig;
9142 MonoObject *exc = NULL;
9144 mono_error_init (error);
9146 mono_class_init (method->klass);
9148 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9149 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9154 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9155 if (!mono_error_ok (error)) return NULL;
9157 mono_runtime_invoke_checked (method, attr, NULL, error);
9158 if (!mono_error_ok (error))
9164 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9167 /*g_print ("got attr %s\n", method->klass->name);*/
9169 sig = mono_method_signature (method);
9170 if (sig->param_count < 32) {
9171 params = params_buf;
9172 memset (params, 0, sizeof (void*) * sig->param_count);
9174 /* Allocate using GC so it gets GC tracking */
9175 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9180 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9181 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9182 if (!mono_error_ok (error))
9187 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9188 if (!mono_error_ok (error)) goto fail;
9190 mono_runtime_try_invoke (method, attr, params, &exc, error);
9191 if (!mono_error_ok (error))
9196 num_named = read16 (named);
9198 for (j = 0; j < num_named; j++) {
9200 char *name, named_type, data_type;
9201 named_type = *named++;
9202 data_type = *named++; /* type of data */
9203 if (data_type == MONO_TYPE_SZARRAY)
9204 data_type = *named++;
9205 if (data_type == MONO_TYPE_ENUM) {
9208 type_len = mono_metadata_decode_blob_size (named, &named);
9209 type_name = (char *)g_malloc (type_len + 1);
9210 memcpy (type_name, named, type_len);
9211 type_name [type_len] = 0;
9213 /* FIXME: lookup the type and check type consistency */
9216 name_len = mono_metadata_decode_blob_size (named, &named);
9217 name = (char *)g_malloc (name_len + 1);
9218 memcpy (name, named, name_len);
9219 name [name_len] = 0;
9221 if (named_type == 0x53) {
9222 MonoClassField *field;
9225 /* how this fail is a blackbox */
9226 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9228 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9233 val = load_cattr_value (image, field->type, named, &named, error);
9234 if (!mono_error_ok (error)) {
9236 if (!type_is_reference (field->type))
9241 mono_field_set_value (attr, field, val);
9242 if (!type_is_reference (field->type))
9244 } else if (named_type == 0x54) {
9247 MonoType *prop_type;
9249 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9252 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9258 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9263 /* can we have more that 1 arg in a custom attr named property? */
9264 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9265 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9267 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9268 if (!mono_error_ok (error)) {
9270 if (!type_is_reference (prop_type))
9271 g_free (pparams [0]);
9276 mono_property_set_value (prop, attr, pparams, NULL);
9277 if (!type_is_reference (prop_type))
9278 g_free (pparams [0]);
9283 free_param_data (method->signature, params);
9284 if (params != params_buf)
9285 mono_gc_free_fixed (params);
9290 free_param_data (method->signature, params);
9291 if (params != params_buf)
9292 mono_gc_free_fixed (params);
9294 mono_raise_exception ((MonoException*)exc);
9299 * mono_reflection_create_custom_attr_data_args:
9301 * Create an array of typed and named arguments from the cattr blob given by DATA.
9302 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9303 * NAMED_ARG_INFO will contain information about the named arguments.
9306 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)
9308 MonoArray *typedargs, *namedargs;
9309 MonoClass *attrklass;
9311 const char *p = (const char*)data;
9313 guint32 i, j, num_named;
9314 CattrNamedArg *arginfo = NULL;
9318 *named_arg_info = NULL;
9320 mono_error_init (error);
9322 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9323 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9327 mono_class_init (method->klass);
9329 domain = mono_domain_get ();
9331 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9334 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9338 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9342 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9343 if (!mono_error_ok (error)) {
9344 if (!type_is_reference (mono_method_signature (method)->params [i]))
9349 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9350 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9351 mono_array_setref (typedargs, i, obj);
9353 if (!type_is_reference (mono_method_signature (method)->params [i]))
9358 num_named = read16 (named);
9359 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9361 attrklass = method->klass;
9363 arginfo = g_new0 (CattrNamedArg, num_named);
9364 *named_arg_info = arginfo;
9366 for (j = 0; j < num_named; j++) {
9368 char *name, named_type, data_type;
9369 named_type = *named++;
9370 data_type = *named++; /* type of data */
9371 if (data_type == MONO_TYPE_SZARRAY)
9372 data_type = *named++;
9373 if (data_type == MONO_TYPE_ENUM) {
9376 type_len = mono_metadata_decode_blob_size (named, &named);
9377 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9380 type_name = (char *)g_malloc (type_len + 1);
9381 memcpy (type_name, named, type_len);
9382 type_name [type_len] = 0;
9384 /* FIXME: lookup the type and check type consistency */
9387 name_len = mono_metadata_decode_blob_size (named, &named);
9388 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9390 name = (char *)g_malloc (name_len + 1);
9391 memcpy (name, named, name_len);
9392 name [name_len] = 0;
9394 if (named_type == 0x53) {
9396 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9404 arginfo [j].type = field->type;
9405 arginfo [j].field = field;
9407 val = load_cattr_value (image, field->type, named, &named, error);
9408 if (!mono_error_ok (error)) {
9409 if (!type_is_reference (field->type))
9415 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9416 mono_array_setref (namedargs, j, obj);
9417 if (!type_is_reference (field->type))
9419 } else if (named_type == 0x54) {
9421 MonoType *prop_type;
9422 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9425 if (!prop || !prop->set) {
9430 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9431 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9433 arginfo [j].type = prop_type;
9434 arginfo [j].prop = prop;
9436 val = load_cattr_value (image, prop_type, named, &named, error);
9437 if (!mono_error_ok (error)) {
9438 if (!type_is_reference (prop_type))
9444 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9445 mono_array_setref (namedargs, j, obj);
9446 if (!type_is_reference (prop_type))
9452 *typed_args = typedargs;
9453 *named_args = namedargs;
9456 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9458 *named_arg_info = NULL;
9462 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9465 MonoArray *typedargs, *namedargs;
9468 CattrNamedArg *arginfo = NULL;
9472 mono_error_init (&error);
9480 image = assembly->assembly->image;
9481 method = ref_method->method;
9482 domain = mono_object_domain (ref_method);
9484 if (!mono_class_init (method->klass))
9485 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9487 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9488 if (!mono_error_ok (&error))
9491 if (mono_loader_get_last_error ()) {
9492 mono_error_set_from_loader_error (&error);
9496 if (!typedargs || !namedargs)
9499 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9500 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9501 MonoObject *typedarg;
9503 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9504 if (!is_ok (&error))
9506 mono_array_setref (typedargs, i, typedarg);
9509 for (i = 0; i < mono_array_length (namedargs); ++i) {
9510 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9511 MonoObject *typedarg, *namedarg, *minfo;
9513 if (arginfo [i].prop) {
9514 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9518 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9519 if (!mono_error_ok (&error))
9523 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9524 if (!is_ok (&error))
9526 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9527 if (!is_ok (&error))
9530 mono_array_setref (namedargs, i, namedarg);
9533 *ctor_args = typedargs;
9534 *named_args = namedargs;
9537 mono_error_raise_exception (&error);
9542 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9544 static MonoMethod *ctor;
9550 mono_error_init (error);
9552 g_assert (image->assembly);
9555 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9557 domain = mono_domain_get ();
9558 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9559 return_val_if_nok (error, NULL);
9560 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9561 return_val_if_nok (error, NULL);
9562 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9563 return_val_if_nok (error, NULL);
9564 params [2] = (gpointer)&cattr->data;
9565 params [3] = &cattr->data_size;
9567 mono_runtime_invoke_checked (ctor, attr, params, error);
9568 return_val_if_nok (error, NULL);
9573 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9579 mono_error_init (error);
9582 for (i = 0; i < cinfo->num_attrs; ++i) {
9583 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9587 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9589 for (i = 0; i < cinfo->num_attrs; ++i) {
9590 if (!cinfo->attrs [i].ctor) {
9591 /* The cattr type is not finished yet */
9592 /* We should include the type name but cinfo doesn't contain it */
9593 mono_error_set_type_load_name (error, NULL, NULL, "");
9596 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9597 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9598 if (!mono_error_ok (error))
9600 mono_array_setref (result, n, attr);
9608 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9611 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9612 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9618 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9624 mono_error_init (error);
9625 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9626 for (i = 0; i < cinfo->num_attrs; ++i) {
9627 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9628 return_val_if_nok (error, NULL);
9629 mono_array_setref (result, i, attr);
9635 * mono_custom_attrs_from_index:
9637 * Returns: NULL if no attributes are found or if a loading error occurs.
9640 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9643 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9644 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9648 * mono_custom_attrs_from_index_checked:
9650 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9653 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9655 guint32 mtoken, i, len;
9656 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9658 MonoCustomAttrInfo *ainfo;
9659 GList *tmp, *list = NULL;
9661 MonoCustomAttrEntry* attr;
9663 mono_error_init (error);
9665 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9667 i = mono_metadata_custom_attrs_from_index (image, idx);
9671 while (i < ca->rows) {
9672 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9674 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9677 len = g_list_length (list);
9680 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9681 ainfo->num_attrs = len;
9682 ainfo->image = image;
9683 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9684 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9685 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9686 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9687 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9688 mtoken |= MONO_TOKEN_METHOD_DEF;
9690 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9691 mtoken |= MONO_TOKEN_MEMBER_REF;
9694 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9697 attr = &ainfo->attrs [i - 1];
9698 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9700 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9706 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9707 /*FIXME raising an exception here doesn't make any sense*/
9708 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9713 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9714 attr->data_size = mono_metadata_decode_value (data, &data);
9715 attr->data = (guchar*)data;
9723 mono_custom_attrs_from_method (MonoMethod *method)
9726 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9727 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9732 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9736 mono_error_init (error);
9739 * An instantiated method has the same cattrs as the generic method definition.
9741 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9742 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9744 if (method->is_inflated)
9745 method = ((MonoMethodInflated *) method)->declaring;
9747 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9748 return lookup_custom_attr (method->klass->image, method);
9751 /* Synthetic methods */
9754 idx = mono_method_get_index (method);
9755 idx <<= MONO_CUSTOM_ATTR_BITS;
9756 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9757 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9761 mono_custom_attrs_from_class (MonoClass *klass)
9764 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9765 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9770 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9774 mono_error_init (error);
9776 if (klass->generic_class)
9777 klass = klass->generic_class->container_class;
9779 if (image_is_dynamic (klass->image))
9780 return lookup_custom_attr (klass->image, klass);
9782 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9783 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9784 idx <<= MONO_CUSTOM_ATTR_BITS;
9785 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9787 idx = mono_metadata_token_index (klass->type_token);
9788 idx <<= MONO_CUSTOM_ATTR_BITS;
9789 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9791 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9795 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9798 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9799 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9804 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9808 mono_error_init (error);
9810 if (image_is_dynamic (assembly->image))
9811 return lookup_custom_attr (assembly->image, assembly);
9812 idx = 1; /* there is only one assembly */
9813 idx <<= MONO_CUSTOM_ATTR_BITS;
9814 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9815 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9818 static MonoCustomAttrInfo*
9819 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9823 if (image_is_dynamic (image))
9824 return lookup_custom_attr (image, image);
9825 idx = 1; /* there is only one module */
9826 idx <<= MONO_CUSTOM_ATTR_BITS;
9827 idx |= MONO_CUSTOM_ATTR_MODULE;
9828 return mono_custom_attrs_from_index_checked (image, idx, error);
9832 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9835 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9836 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9841 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9845 if (image_is_dynamic (klass->image)) {
9846 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9847 return lookup_custom_attr (klass->image, property);
9849 idx = find_property_index (klass, property);
9850 idx <<= MONO_CUSTOM_ATTR_BITS;
9851 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9852 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9856 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9859 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9860 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9865 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9869 if (image_is_dynamic (klass->image)) {
9870 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9871 return lookup_custom_attr (klass->image, event);
9873 idx = find_event_index (klass, event);
9874 idx <<= MONO_CUSTOM_ATTR_BITS;
9875 idx |= MONO_CUSTOM_ATTR_EVENT;
9876 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9880 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9883 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9884 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9889 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9892 mono_error_init (error);
9894 if (image_is_dynamic (klass->image)) {
9895 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9896 return lookup_custom_attr (klass->image, field);
9898 idx = find_field_index (klass, field);
9899 idx <<= MONO_CUSTOM_ATTR_BITS;
9900 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9901 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9905 * mono_custom_attrs_from_param:
9906 * @method: handle to the method that we want to retrieve custom parameter information from
9907 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9909 * The result must be released with mono_custom_attrs_free().
9911 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9914 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9917 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9918 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9923 * mono_custom_attrs_from_param_checked:
9924 * @method: handle to the method that we want to retrieve custom parameter information from
9925 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9926 * @error: set on error
9928 * The result must be released with mono_custom_attrs_free().
9930 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9933 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9936 guint32 i, idx, method_index;
9937 guint32 param_list, param_last, param_pos, found;
9939 MonoReflectionMethodAux *aux;
9941 mono_error_init (error);
9944 * An instantiated method has the same cattrs as the generic method definition.
9946 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9947 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9949 if (method->is_inflated)
9950 method = ((MonoMethodInflated *) method)->declaring;
9952 if (image_is_dynamic (method->klass->image)) {
9953 MonoCustomAttrInfo *res, *ainfo;
9956 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9957 if (!aux || !aux->param_cattr)
9960 /* Need to copy since it will be freed later */
9961 ainfo = aux->param_cattr [param];
9964 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9965 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9966 memcpy (res, ainfo, size);
9970 image = method->klass->image;
9971 method_index = mono_method_get_index (method);
9974 ca = &image->tables [MONO_TABLE_METHOD];
9976 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9977 if (method_index == ca->rows) {
9978 ca = &image->tables [MONO_TABLE_PARAM];
9979 param_last = ca->rows + 1;
9981 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9982 ca = &image->tables [MONO_TABLE_PARAM];
9985 for (i = param_list; i < param_last; ++i) {
9986 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9987 if (param_pos == param) {
9995 idx <<= MONO_CUSTOM_ATTR_BITS;
9996 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9997 return mono_custom_attrs_from_index_checked (image, idx, error);
10001 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10005 for (i = 0; i < ainfo->num_attrs; ++i) {
10006 klass = ainfo->attrs [i].ctor->klass;
10007 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10014 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10017 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10018 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10023 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10029 mono_error_init (error);
10032 for (i = 0; i < ainfo->num_attrs; ++i) {
10033 klass = ainfo->attrs [i].ctor->klass;
10034 if (mono_class_has_parent (klass, attr_klass)) {
10039 if (attr_index == -1)
10042 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10043 if (!mono_error_ok (error))
10045 return mono_array_get (attrs, MonoObject*, attr_index);
10049 * mono_reflection_get_custom_attrs_info:
10050 * @obj: a reflection object handle
10052 * Return the custom attribute info for attributes defined for the
10053 * reflection handle @obj. The objects.
10055 * FIXME this function leaks like a sieve for SRE objects.
10057 MonoCustomAttrInfo*
10058 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10061 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10062 mono_error_assert_ok (&error);
10067 * mono_reflection_get_custom_attrs_info_checked:
10068 * @obj: a reflection object handle
10069 * @error: set on error
10071 * Return the custom attribute info for attributes defined for the
10072 * reflection handle @obj. The objects.
10074 * On failure returns NULL and sets @error.
10076 * FIXME this function leaks like a sieve for SRE objects.
10078 MonoCustomAttrInfo*
10079 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10082 MonoCustomAttrInfo *cinfo = NULL;
10084 mono_error_init (error);
10086 klass = obj->vtable->klass;
10087 if (klass == mono_defaults.monotype_class) {
10088 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10089 return_val_if_nok (error, NULL);
10090 klass = mono_class_from_mono_type (type);
10091 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10092 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10093 return_val_if_nok (error, NULL);
10094 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10095 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10096 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10097 return_val_if_nok (error, NULL);
10098 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10099 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10100 cinfo = mono_custom_attrs_from_module (module->image, error);
10101 return_val_if_nok (error, NULL);
10102 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10103 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10104 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10105 return_val_if_nok (error, NULL);
10106 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10107 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10108 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10109 return_val_if_nok (error, NULL);
10110 } else if (strcmp ("MonoField", klass->name) == 0) {
10111 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10112 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10113 return_val_if_nok (error, NULL);
10114 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10115 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10116 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10117 return_val_if_nok (error, NULL);
10118 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10119 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10120 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10121 return_val_if_nok (error, NULL);
10122 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10123 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10124 MonoClass *member_class = mono_object_class (param->MemberImpl);
10125 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10126 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10127 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10128 return_val_if_nok (error, NULL);
10129 } else if (is_sr_mono_property (member_class)) {
10130 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10131 MonoMethod *method;
10132 if (!(method = prop->property->get))
10133 method = prop->property->set;
10136 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10137 return_val_if_nok (error, NULL);
10139 #ifndef DISABLE_REFLECTION_EMIT
10140 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10141 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10142 return_val_if_nok (error, NULL);
10143 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10144 return_val_if_nok (error, NULL);
10145 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10146 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10147 MonoMethod *method = NULL;
10148 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10149 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10150 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10151 method = ((MonoReflectionMethod *)c->cb)->method;
10153 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));
10155 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10156 return_val_if_nok (error, NULL);
10160 char *type_name = mono_type_get_full_name (member_class);
10161 mono_error_set_generic_error (error, "System", "NotSupportedException",
10162 "Custom attributes on a ParamInfo with member %s are not supported",
10164 g_free (type_name);
10167 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10168 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10169 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10170 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10171 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10172 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10173 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10174 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10175 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10176 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10177 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10178 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10179 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10180 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10181 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10182 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10183 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10184 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10185 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10186 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10187 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10188 return_val_if_nok (error, NULL);
10189 } else { /* handle other types here... */
10190 g_error ("get custom attrs not yet supported for %s", klass->name);
10197 * mono_reflection_get_custom_attrs_by_type:
10198 * @obj: a reflection object handle
10200 * Return an array with all the custom attributes defined of the
10201 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10202 * of that type are returned. The objects are fully build. Return NULL if a loading error
10206 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10209 MonoCustomAttrInfo *cinfo;
10211 mono_error_init (error);
10213 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10214 return_val_if_nok (error, NULL);
10216 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10219 if (!cinfo->cached)
10220 mono_custom_attrs_free (cinfo);
10222 mono_loader_assert_no_error ();
10223 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10230 * mono_reflection_get_custom_attrs:
10231 * @obj: a reflection object handle
10233 * Return an array with all the custom attributes defined of the
10234 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10238 mono_reflection_get_custom_attrs (MonoObject *obj)
10242 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10246 * mono_reflection_get_custom_attrs_data:
10247 * @obj: a reflection obj handle
10249 * Returns an array of System.Reflection.CustomAttributeData,
10250 * which include information about attributes reflected on
10251 * types loaded using the Reflection Only methods
10254 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10258 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10259 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10264 * mono_reflection_get_custom_attrs_data_checked:
10265 * @obj: a reflection obj handle
10266 * @error: set on error
10268 * Returns an array of System.Reflection.CustomAttributeData,
10269 * which include information about attributes reflected on
10270 * types loaded using the Reflection Only methods
10273 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10276 MonoCustomAttrInfo *cinfo;
10278 mono_error_init (error);
10280 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10281 return_val_if_nok (error, NULL);
10283 result = mono_custom_attrs_data_construct (cinfo, error);
10284 return_val_if_nok (error, NULL);
10285 if (!cinfo->cached)
10286 mono_custom_attrs_free (cinfo);
10288 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10290 if (mono_loader_get_last_error ())
10291 mono_error_set_from_loader_error (error);
10296 static MonoReflectionType*
10297 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10299 static MonoMethod *method_get_underlying_system_type = NULL;
10300 MonoReflectionType *rt;
10301 MonoMethod *usertype_method;
10303 mono_error_init (error);
10305 if (!method_get_underlying_system_type)
10306 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10308 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10310 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10317 is_corlib_type (MonoClass *klass)
10319 return klass->image == mono_defaults.corlib;
10322 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10323 static MonoClass *cached_class; \
10324 if (cached_class) \
10325 return cached_class == _class; \
10326 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10327 cached_class = _class; \
10334 #ifndef DISABLE_REFLECTION_EMIT
10336 is_sre_array (MonoClass *klass)
10338 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10342 is_sre_byref (MonoClass *klass)
10344 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10348 is_sre_pointer (MonoClass *klass)
10350 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10354 is_sre_generic_instance (MonoClass *klass)
10356 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10360 is_sre_type_builder (MonoClass *klass)
10362 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10366 is_sre_method_builder (MonoClass *klass)
10368 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10372 is_sre_ctor_builder (MonoClass *klass)
10374 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10378 is_sre_field_builder (MonoClass *klass)
10380 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10384 is_sre_method_on_tb_inst (MonoClass *klass)
10386 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10390 is_sre_ctor_on_tb_inst (MonoClass *klass)
10392 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10396 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10399 mono_error_init (error);
10406 if (is_usertype (ref)) {
10407 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10408 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10414 klass = mono_object_class (ref);
10416 if (is_sre_array (klass)) {
10418 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10419 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10420 return_val_if_nok (error, NULL);
10422 if (sre_array->rank == 0) //single dimentional array
10423 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10425 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10426 sre_array->type.type = res;
10428 } else if (is_sre_byref (klass)) {
10430 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10431 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10432 return_val_if_nok (error, NULL);
10434 res = &mono_class_from_mono_type (base)->this_arg;
10435 sre_byref->type.type = res;
10437 } else if (is_sre_pointer (klass)) {
10439 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10440 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10441 return_val_if_nok (error, NULL);
10443 res = &mono_ptr_class_get (base)->byval_arg;
10444 sre_pointer->type.type = res;
10446 } else if (is_sre_generic_instance (klass)) {
10447 MonoType *res, **types;
10448 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10451 count = mono_array_length (gclass->type_arguments);
10452 types = g_new0 (MonoType*, count);
10453 for (i = 0; i < count; ++i) {
10454 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10455 types [i] = mono_reflection_type_get_handle (t, error);
10456 if (!types[i] || !is_ok (error)) {
10462 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10465 gclass->type.type = res;
10469 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10474 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10477 mono_reflection_type_get_handle (type, &error);
10478 mono_error_set_pending_exception (&error);
10482 mono_reflection_register_with_runtime (MonoReflectionType *type)
10485 MonoType *res = mono_reflection_type_get_handle (type, &error);
10486 mono_error_raise_exception (&error); /* FIXME don't raise here */
10487 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10491 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10493 klass = mono_class_from_mono_type (res);
10495 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10496 mono_domain_lock (domain);
10498 if (!image_is_dynamic (klass->image)) {
10499 mono_class_setup_supertypes (klass);
10501 if (!domain->type_hash)
10502 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10503 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10504 mono_g_hash_table_insert (domain->type_hash, res, type);
10506 mono_domain_unlock (domain);
10507 mono_loader_unlock ();
10511 * LOCKING: Assumes the loader lock is held.
10513 static MonoMethodSignature*
10514 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10516 MonoMethodSignature *sig;
10519 count = parameters? mono_array_length (parameters): 0;
10521 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10522 sig->param_count = count;
10523 sig->sentinelpos = -1; /* FIXME */
10524 for (i = 0; i < count; ++i) {
10525 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10526 mono_error_raise_exception (&error); /* FIXME don't raise here */
10532 * LOCKING: Assumes the loader lock is held.
10534 static MonoMethodSignature*
10535 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10536 MonoMethodSignature *sig;
10538 sig = parameters_to_signature (image, ctor->parameters);
10539 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10540 sig->ret = &mono_defaults.void_class->byval_arg;
10545 * LOCKING: Assumes the loader lock is held.
10547 static MonoMethodSignature*
10548 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10550 MonoMethodSignature *sig;
10552 sig = parameters_to_signature (image, method->parameters);
10553 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10554 if (method->rtype) {
10555 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10556 mono_error_raise_exception (&error); /* FIXME don't raise here */
10558 sig->ret = &mono_defaults.void_class->byval_arg;
10560 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10564 static MonoMethodSignature*
10565 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10567 MonoMethodSignature *sig;
10569 sig = parameters_to_signature (NULL, method->parameters);
10570 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10571 if (method->rtype) {
10572 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10573 mono_error_raise_exception (&error); /* FIXME don't raise here */
10575 sig->ret = &mono_defaults.void_class->byval_arg;
10577 sig->generic_param_count = 0;
10582 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10585 MonoClass *klass = mono_object_class (prop);
10586 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10587 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10588 *name = mono_string_to_utf8 (pb->name);
10589 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10590 mono_error_raise_exception (&error); /* FIXME don't raise here */
10592 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10593 *name = g_strdup (p->property->name);
10594 if (p->property->get)
10595 *type = mono_method_signature (p->property->get)->ret;
10597 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10602 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10605 MonoClass *klass = mono_object_class (field);
10606 if (strcmp (klass->name, "FieldBuilder") == 0) {
10607 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10608 *name = mono_string_to_utf8 (fb->name);
10609 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10610 mono_error_raise_exception (&error); /* FIXME don't raise here */
10612 MonoReflectionField *f = (MonoReflectionField *)field;
10613 *name = g_strdup (mono_field_get_name (f->field));
10614 *type = f->field->type;
10618 #else /* DISABLE_REFLECTION_EMIT */
10621 mono_reflection_register_with_runtime (MonoReflectionType *type)
10623 /* This is empty */
10627 is_sre_type_builder (MonoClass *klass)
10633 is_sre_generic_instance (MonoClass *klass)
10639 init_type_builder_generics (MonoObject *type)
10643 #endif /* !DISABLE_REFLECTION_EMIT */
10647 is_sr_mono_field (MonoClass *klass)
10649 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10653 is_sr_mono_property (MonoClass *klass)
10655 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10659 is_sr_mono_method (MonoClass *klass)
10661 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10665 is_sr_mono_cmethod (MonoClass *klass)
10667 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10671 is_sr_mono_generic_method (MonoClass *klass)
10673 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10677 is_sr_mono_generic_cmethod (MonoClass *klass)
10679 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10683 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10685 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10689 is_usertype (MonoReflectionType *ref)
10691 MonoClass *klass = mono_object_class (ref);
10692 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10695 static MonoReflectionType*
10696 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10698 mono_error_init (error);
10699 if (!type || type->type)
10702 if (is_usertype (type)) {
10703 type = mono_reflection_type_get_underlying_system_type (type, error);
10704 return_val_if_nok (error, NULL);
10705 if (is_usertype (type)) {
10706 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10714 * Encode a value in a custom attribute stream of bytes.
10715 * The value to encode is either supplied as an object in argument val
10716 * (valuetypes are boxed), or as a pointer to the data in the
10718 * @type represents the type of the value
10719 * @buffer is the start of the buffer
10720 * @p the current position in the buffer
10721 * @buflen contains the size of the buffer and is used to return the new buffer size
10722 * if this needs to be realloced.
10723 * @retbuffer and @retp return the start and the position of the buffer
10726 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10729 MonoTypeEnum simple_type;
10731 if ((p-buffer) + 10 >= *buflen) {
10734 newbuf = (char *)g_realloc (buffer, *buflen);
10735 p = newbuf + (p-buffer);
10739 argval = ((char*)arg + sizeof (MonoObject));
10740 simple_type = type->type;
10742 switch (simple_type) {
10743 case MONO_TYPE_BOOLEAN:
10748 case MONO_TYPE_CHAR:
10751 swap_with_size (p, argval, 2, 1);
10757 swap_with_size (p, argval, 4, 1);
10761 swap_with_size (p, argval, 8, 1);
10766 swap_with_size (p, argval, 8, 1);
10769 case MONO_TYPE_VALUETYPE:
10770 if (type->data.klass->enumtype) {
10771 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10774 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10777 case MONO_TYPE_STRING: {
10784 str = mono_string_to_utf8 ((MonoString*)arg);
10785 slen = strlen (str);
10786 if ((p-buffer) + 10 + slen >= *buflen) {
10790 newbuf = (char *)g_realloc (buffer, *buflen);
10791 p = newbuf + (p-buffer);
10794 mono_metadata_encode_value (slen, p, &p);
10795 memcpy (p, str, slen);
10800 case MONO_TYPE_CLASS: {
10803 MonoType *arg_type;
10809 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10810 mono_error_raise_exception (&error); /* FIXME don't raise here */
10811 str = type_get_qualified_name (arg_type, NULL);
10812 slen = strlen (str);
10813 if ((p-buffer) + 10 + slen >= *buflen) {
10817 newbuf = (char *)g_realloc (buffer, *buflen);
10818 p = newbuf + (p-buffer);
10821 mono_metadata_encode_value (slen, p, &p);
10822 memcpy (p, str, slen);
10827 case MONO_TYPE_SZARRAY: {
10829 MonoClass *eclass, *arg_eclass;
10832 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10835 len = mono_array_length ((MonoArray*)arg);
10837 *p++ = (len >> 8) & 0xff;
10838 *p++ = (len >> 16) & 0xff;
10839 *p++ = (len >> 24) & 0xff;
10841 *retbuffer = buffer;
10842 eclass = type->data.klass;
10843 arg_eclass = mono_object_class (arg)->element_class;
10846 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10847 eclass = mono_defaults.object_class;
10849 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10850 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10851 int elsize = mono_class_array_element_size (arg_eclass);
10852 for (i = 0; i < len; ++i) {
10853 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10856 } else if (eclass->valuetype && arg_eclass->valuetype) {
10857 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10858 int elsize = mono_class_array_element_size (eclass);
10859 for (i = 0; i < len; ++i) {
10860 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10864 for (i = 0; i < len; ++i) {
10865 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10870 case MONO_TYPE_OBJECT: {
10876 * The parameter type is 'object' but the type of the actual
10877 * argument is not. So we have to add type information to the blob
10878 * too. This is completely undocumented in the spec.
10882 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10887 klass = mono_object_class (arg);
10889 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10892 } else if (klass->enumtype) {
10894 } else if (klass == mono_defaults.string_class) {
10895 simple_type = MONO_TYPE_STRING;
10898 } else if (klass->rank == 1) {
10900 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10901 /* See Partition II, Appendix B3 */
10904 *p++ = klass->element_class->byval_arg.type;
10905 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10907 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10908 *p++ = simple_type = klass->byval_arg.type;
10911 g_error ("unhandled type in custom attr");
10913 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10914 slen = strlen (str);
10915 if ((p-buffer) + 10 + slen >= *buflen) {
10919 newbuf = (char *)g_realloc (buffer, *buflen);
10920 p = newbuf + (p-buffer);
10923 mono_metadata_encode_value (slen, p, &p);
10924 memcpy (p, str, slen);
10927 simple_type = mono_class_enum_basetype (klass)->type;
10931 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10934 *retbuffer = buffer;
10938 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10940 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10941 char *str = type_get_qualified_name (type, NULL);
10942 int slen = strlen (str);
10946 * This seems to be optional...
10949 mono_metadata_encode_value (slen, p, &p);
10950 memcpy (p, str, slen);
10953 } else if (type->type == MONO_TYPE_OBJECT) {
10955 } else if (type->type == MONO_TYPE_CLASS) {
10956 /* it should be a type: encode_cattr_value () has the check */
10959 mono_metadata_encode_value (type->type, p, &p);
10960 if (type->type == MONO_TYPE_SZARRAY)
10961 /* See the examples in Partition VI, Annex B */
10962 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10968 #ifndef DISABLE_REFLECTION_EMIT
10970 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10973 /* Preallocate a large enough buffer */
10974 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10975 char *str = type_get_qualified_name (type, NULL);
10976 len = strlen (str);
10978 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10979 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10980 len = strlen (str);
10985 len += strlen (name);
10987 if ((p-buffer) + 20 + len >= *buflen) {
10991 newbuf = (char *)g_realloc (buffer, *buflen);
10992 p = newbuf + (p-buffer);
10996 encode_field_or_prop_type (type, p, &p);
10998 len = strlen (name);
10999 mono_metadata_encode_value (len, p, &p);
11000 memcpy (p, name, len);
11002 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11004 *retbuffer = buffer;
11008 * mono_reflection_get_custom_attrs_blob:
11009 * @ctor: custom attribute constructor
11010 * @ctorArgs: arguments o the constructor
11016 * Creates the blob of data that needs to be saved in the metadata and that represents
11017 * the custom attributed described by @ctor, @ctorArgs etc.
11018 * Returns: a Byte array representing the blob of data.
11021 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11024 MonoMethodSignature *sig;
11029 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11030 /* sig is freed later so allocate it in the heap */
11031 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11033 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11036 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11038 p = buffer = (char *)g_malloc (buflen);
11039 /* write the prolog */
11042 for (i = 0; i < sig->param_count; ++i) {
11043 arg = mono_array_get (ctorArgs, MonoObject*, i);
11044 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11048 i += mono_array_length (properties);
11050 i += mono_array_length (fields);
11052 *p++ = (i >> 8) & 0xff;
11055 for (i = 0; i < mono_array_length (properties); ++i) {
11059 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11060 get_prop_name_and_type (prop, &pname, &ptype);
11061 *p++ = 0x54; /* PROPERTY signature */
11062 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11069 for (i = 0; i < mono_array_length (fields); ++i) {
11073 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11074 get_field_name_and_type (field, &fname, &ftype);
11075 *p++ = 0x53; /* FIELD signature */
11076 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11081 g_assert (p - buffer <= buflen);
11082 buflen = p - buffer;
11083 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11084 p = mono_array_addr (result, char, 0);
11085 memcpy (p, buffer, buflen);
11087 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11093 * mono_reflection_setup_internal_class:
11094 * @tb: a TypeBuilder object
11096 * Creates a MonoClass that represents the TypeBuilder.
11097 * This is a trick that lets us simplify a lot of reflection code
11098 * (and will allow us to support Build and Run assemblies easier).
11101 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11104 MonoClass *klass, *parent;
11106 RESOLVE_TYPE (tb->parent, &error);
11107 mono_error_raise_exception (&error); /* FIXME don't raise here */
11109 mono_loader_lock ();
11112 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11113 if (!is_ok (&error)) {
11114 mono_loader_unlock ();
11115 mono_error_raise_exception (&error); /* FIXME don't raise here */
11117 /* check so we can compile corlib correctly */
11118 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11119 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11120 parent = parent_type->data.klass;
11122 parent = mono_class_from_mono_type (parent_type);
11128 /* the type has already being created: it means we just have to change the parent */
11129 if (tb->type.type) {
11130 klass = mono_class_from_mono_type (tb->type.type);
11131 klass->parent = NULL;
11132 /* fool mono_class_setup_parent */
11133 klass->supertypes = NULL;
11134 mono_class_setup_parent (klass, parent);
11135 mono_class_setup_mono_type (klass);
11136 mono_loader_unlock ();
11140 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11142 klass->image = &tb->module->dynamic_image->image;
11144 klass->inited = 1; /* we lie to the runtime */
11145 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11146 if (!mono_error_ok (&error))
11148 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11149 if (!mono_error_ok (&error))
11151 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11152 klass->flags = tb->attrs;
11154 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11156 klass->element_class = klass;
11158 if (mono_class_get_ref_info (klass) == NULL) {
11160 mono_class_set_ref_info (klass, tb);
11162 /* Put into cache so mono_class_get_checked () will find it.
11163 Skip nested types as those should not be available on the global scope. */
11164 if (!tb->nesting_type)
11165 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11168 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11169 by performing a mono_class_get which does the full resolution.
11171 Working around this semantics would require us to write a lot of code for no clear advantage.
11173 mono_image_append_class_to_reflection_info_set (klass);
11175 g_assert (mono_class_get_ref_info (klass) == tb);
11178 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11180 if (parent != NULL) {
11181 mono_class_setup_parent (klass, parent);
11182 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11183 const char *old_n = klass->name;
11184 /* trick to get relative numbering right when compiling corlib */
11185 klass->name = "BuildingObject";
11186 mono_class_setup_parent (klass, mono_defaults.object_class);
11187 klass->name = old_n;
11190 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11191 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11192 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11193 klass->instance_size = sizeof (MonoObject);
11194 klass->size_inited = 1;
11195 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11198 mono_class_setup_mono_type (klass);
11200 mono_class_setup_supertypes (klass);
11203 * FIXME: handle interfaces.
11206 tb->type.type = &klass->byval_arg;
11208 if (tb->nesting_type) {
11209 g_assert (tb->nesting_type->type);
11210 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11211 if (!is_ok (&error)) goto failure;
11212 klass->nested_in = mono_class_from_mono_type (nesting_type);
11215 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11217 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11219 mono_loader_unlock ();
11223 mono_loader_unlock ();
11224 mono_error_raise_exception (&error);
11228 * mono_reflection_setup_generic_class:
11229 * @tb: a TypeBuilder object
11231 * Setup the generic class before adding the first generic parameter.
11234 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11239 * mono_reflection_create_generic_class:
11240 * @tb: a TypeBuilder object
11242 * Creates the generic class after all generic parameters have been added.
11245 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11251 klass = mono_class_from_mono_type (tb->type.type);
11253 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11255 if (klass->generic_container || (count == 0))
11258 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11260 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11262 klass->generic_container->owner.klass = klass;
11263 klass->generic_container->type_argc = count;
11264 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11266 klass->is_generic = 1;
11268 for (i = 0; i < count; i++) {
11269 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11270 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11271 mono_error_raise_exception (&error); /* FIXME don't raise here */
11272 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11273 klass->generic_container->type_params [i] = *param;
11274 /*Make sure we are a diferent type instance */
11275 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11276 klass->generic_container->type_params [i].info.pklass = NULL;
11277 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11279 g_assert (klass->generic_container->type_params [i].param.owner);
11282 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11286 * mono_reflection_create_internal_class:
11287 * @tb: a TypeBuilder object
11289 * Actually create the MonoClass that is associated with the TypeBuilder.
11292 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11297 klass = mono_class_from_mono_type (tb->type.type);
11299 mono_loader_lock ();
11300 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11301 MonoReflectionFieldBuilder *fb;
11303 MonoType *enum_basetype;
11305 g_assert (tb->fields != NULL);
11306 g_assert (mono_array_length (tb->fields) >= 1);
11308 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11310 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11311 if (!is_ok (&error)) {
11312 mono_loader_unlock ();
11313 mono_error_raise_exception (&error); /* FIXME don't raise here */
11315 if (!mono_type_is_valid_enum_basetype (field_type)) {
11316 mono_loader_unlock ();
11320 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11321 if (!is_ok (&error)) {
11322 mono_loader_unlock ();
11323 mono_error_raise_exception (&error); /* FIXME don't raise here */
11325 klass->element_class = mono_class_from_mono_type (enum_basetype);
11326 if (!klass->element_class)
11327 klass->element_class = mono_class_from_mono_type (enum_basetype);
11330 * get the element_class from the current corlib.
11332 ec = default_class_from_mono_type (enum_basetype);
11333 klass->instance_size = ec->instance_size;
11334 klass->size_inited = 1;
11336 * this is almost safe to do with enums and it's needed to be able
11337 * to create objects of the enum type (for use in SetConstant).
11339 /* FIXME: Does this mean enums can't have method overrides ? */
11340 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11342 mono_loader_unlock ();
11345 static MonoMarshalSpec*
11346 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11347 MonoReflectionMarshal *minfo)
11350 MonoMarshalSpec *res;
11352 res = image_g_new0 (image, MonoMarshalSpec, 1);
11353 res->native = (MonoMarshalNative)minfo->type;
11355 switch (minfo->type) {
11356 case MONO_NATIVE_LPARRAY:
11357 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11358 if (minfo->has_size) {
11359 res->data.array_data.param_num = minfo->param_num;
11360 res->data.array_data.num_elem = minfo->count;
11361 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11364 res->data.array_data.param_num = -1;
11365 res->data.array_data.num_elem = -1;
11366 res->data.array_data.elem_mult = -1;
11370 case MONO_NATIVE_BYVALTSTR:
11371 case MONO_NATIVE_BYVALARRAY:
11372 res->data.array_data.num_elem = minfo->count;
11375 case MONO_NATIVE_CUSTOM:
11376 if (minfo->marshaltyperef) {
11377 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11378 mono_error_raise_exception (&error); /* FIXME don't raise here */
11379 res->data.custom_data.custom_name =
11380 type_get_fully_qualified_name (marshaltyperef);
11382 if (minfo->mcookie)
11383 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11392 #endif /* !DISABLE_REFLECTION_EMIT */
11394 MonoReflectionMarshalAsAttribute*
11395 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11396 MonoMarshalSpec *spec, MonoError *error)
11398 MonoReflectionType *rt;
11399 MonoReflectionMarshalAsAttribute *minfo;
11402 mono_error_init (error);
11404 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11407 minfo->utype = spec->native;
11409 switch (minfo->utype) {
11410 case MONO_NATIVE_LPARRAY:
11411 minfo->array_subtype = spec->data.array_data.elem_type;
11412 minfo->size_const = spec->data.array_data.num_elem;
11413 if (spec->data.array_data.param_num != -1)
11414 minfo->size_param_index = spec->data.array_data.param_num;
11417 case MONO_NATIVE_BYVALTSTR:
11418 case MONO_NATIVE_BYVALARRAY:
11419 minfo->size_const = spec->data.array_data.num_elem;
11422 case MONO_NATIVE_CUSTOM:
11423 if (spec->data.custom_data.custom_name) {
11424 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11425 return_val_if_nok (error, NULL);
11428 rt = mono_type_get_object_checked (domain, mtype, error);
11432 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11435 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11437 if (spec->data.custom_data.cookie)
11438 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11448 #ifndef DISABLE_REFLECTION_EMIT
11450 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11451 ReflectionMethodBuilder *rmb,
11452 MonoMethodSignature *sig)
11456 MonoMethodWrapper *wrapperm;
11457 MonoMarshalSpec **specs;
11458 MonoReflectionMethodAux *method_aux;
11463 mono_error_init (&error);
11465 * Methods created using a MethodBuilder should have their memory allocated
11466 * inside the image mempool, while dynamic methods should have their memory
11469 dynamic = rmb->refs != NULL;
11470 image = dynamic ? NULL : klass->image;
11473 g_assert (!klass->generic_class);
11475 mono_loader_lock ();
11477 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11478 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11479 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11481 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11483 wrapperm = (MonoMethodWrapper*)m;
11485 m->dynamic = dynamic;
11487 m->flags = rmb->attrs;
11488 m->iflags = rmb->iattrs;
11489 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11491 m->signature = sig;
11492 m->sre_method = TRUE;
11493 m->skip_visibility = rmb->skip_visibility;
11494 if (rmb->table_idx)
11495 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11497 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11498 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11499 m->string_ctor = 1;
11501 m->signature->pinvoke = 1;
11502 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11503 m->signature->pinvoke = 1;
11505 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11507 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11508 g_assert (mono_error_ok (&error));
11509 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11510 g_assert (mono_error_ok (&error));
11512 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11514 if (image_is_dynamic (klass->image))
11515 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11517 mono_loader_unlock ();
11520 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11521 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11522 MonoMethodHeader *header;
11524 gint32 max_stack, i;
11525 gint32 num_locals = 0;
11526 gint32 num_clauses = 0;
11530 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11531 code_size = rmb->ilgen->code_len;
11532 max_stack = rmb->ilgen->max_stack;
11533 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11534 if (rmb->ilgen->ex_handlers)
11535 num_clauses = method_count_clauses (rmb->ilgen);
11538 code = mono_array_addr (rmb->code, guint8, 0);
11539 code_size = mono_array_length (rmb->code);
11540 /* we probably need to run a verifier on the code... */
11550 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11551 header->code_size = code_size;
11552 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11553 memcpy ((char*)header->code, code, code_size);
11554 header->max_stack = max_stack;
11555 header->init_locals = rmb->init_locals;
11556 header->num_locals = num_locals;
11558 for (i = 0; i < num_locals; ++i) {
11559 MonoReflectionLocalBuilder *lb =
11560 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11562 header->locals [i] = image_g_new0 (image, MonoType, 1);
11563 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11564 mono_error_assert_ok (&error);
11565 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11568 header->num_clauses = num_clauses;
11570 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11571 rmb->ilgen, num_clauses);
11574 wrapperm->header = header;
11577 if (rmb->generic_params) {
11578 int count = mono_array_length (rmb->generic_params);
11579 MonoGenericContainer *container = rmb->generic_container;
11581 g_assert (container);
11583 container->type_argc = count;
11584 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11585 container->owner.method = m;
11586 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11588 m->is_generic = TRUE;
11589 mono_method_set_generic_container (m, container);
11591 for (i = 0; i < count; i++) {
11592 MonoReflectionGenericParam *gp =
11593 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11594 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11595 mono_error_assert_ok (&error);
11596 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11597 container->type_params [i] = *param;
11601 * The method signature might have pointers to generic parameters that belong to other methods.
11602 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11603 * generic parameters.
11605 for (i = 0; i < m->signature->param_count; ++i) {
11606 MonoType *t = m->signature->params [i];
11607 if (t->type == MONO_TYPE_MVAR) {
11608 MonoGenericParam *gparam = t->data.generic_param;
11609 if (gparam->num < count) {
11610 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11611 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11617 if (klass->generic_container) {
11618 container->parent = klass->generic_container;
11619 container->context.class_inst = klass->generic_container->context.class_inst;
11621 container->context.method_inst = mono_get_shared_generic_inst (container);
11625 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11629 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11631 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11632 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11633 for (i = 0; i < rmb->nrefs; ++i)
11634 data [i + 1] = rmb->refs [i];
11639 /* Parameter info */
11642 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11643 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11644 for (i = 0; i <= m->signature->param_count; ++i) {
11645 MonoReflectionParamBuilder *pb;
11646 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11647 if ((i > 0) && (pb->attrs)) {
11648 /* Make a copy since it might point to a shared type structure */
11649 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11650 m->signature->params [i - 1]->attrs = pb->attrs;
11653 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11654 MonoDynamicImage *assembly;
11656 MonoTypeEnum def_type;
11660 if (!method_aux->param_defaults) {
11661 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11662 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11664 assembly = (MonoDynamicImage*)klass->image;
11665 idx = encode_constant (assembly, pb->def_value, &def_type);
11666 /* Copy the data from the blob since it might get realloc-ed */
11667 p = assembly->blob.data + idx;
11668 len = mono_metadata_decode_blob_size (p, &p2);
11670 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11671 method_aux->param_default_types [i] = def_type;
11672 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11676 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11677 g_assert (mono_error_ok (&error));
11680 if (!method_aux->param_cattr)
11681 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11682 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11688 /* Parameter marshalling */
11691 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11692 MonoReflectionParamBuilder *pb;
11693 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11694 if (pb->marshal_info) {
11696 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11697 specs [pb->position] =
11698 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11702 if (specs != NULL) {
11704 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11705 method_aux->param_marshall = specs;
11708 if (image_is_dynamic (klass->image) && method_aux)
11709 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11711 mono_loader_unlock ();
11717 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11719 ReflectionMethodBuilder rmb;
11720 MonoMethodSignature *sig;
11722 mono_loader_lock ();
11723 sig = ctor_builder_to_signature (klass->image, mb);
11724 mono_loader_unlock ();
11726 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11729 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11730 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11732 /* If we are in a generic class, we might be called multiple times from inflate_method */
11733 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11734 /* ilgen is no longer needed */
11738 return mb->mhandle;
11742 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11744 ReflectionMethodBuilder rmb;
11745 MonoMethodSignature *sig;
11747 mono_error_init (error);
11749 mono_loader_lock ();
11750 sig = method_builder_to_signature (klass->image, mb);
11751 mono_loader_unlock ();
11753 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11756 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11757 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11759 /* If we are in a generic class, we might be called multiple times from inflate_method */
11760 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11761 /* ilgen is no longer needed */
11764 return mb->mhandle;
11767 static MonoClassField*
11768 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11770 MonoClassField *field;
11774 field = g_new0 (MonoClassField, 1);
11776 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11777 g_assert (mono_error_ok (&error));
11778 if (fb->attrs || fb->modreq || fb->modopt) {
11779 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11780 if (!is_ok (&error)) {
11782 mono_error_raise_exception (&error); /* FIXME don't raise here */
11784 field->type = mono_metadata_type_dup (NULL, type);
11785 field->type->attrs = fb->attrs;
11787 g_assert (image_is_dynamic (klass->image));
11788 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11789 g_free (field->type);
11790 field->type = mono_metadata_type_dup (klass->image, custom);
11793 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11794 if (!is_ok (&error)) {
11796 mono_error_raise_exception (&error); /* FIXME don't raise here */
11799 if (fb->offset != -1)
11800 field->offset = fb->offset;
11801 field->parent = klass;
11802 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11804 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11811 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11815 MonoReflectionTypeBuilder *tb = NULL;
11816 gboolean is_dynamic = FALSE;
11817 MonoClass *geninst;
11819 mono_loader_lock ();
11821 if (is_sre_type_builder (mono_object_class (type))) {
11822 tb = (MonoReflectionTypeBuilder *) type;
11825 } else if (is_sre_generic_instance (mono_object_class (type))) {
11826 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11827 MonoReflectionType *gtd = rgi->generic_type;
11829 if (is_sre_type_builder (mono_object_class (gtd))) {
11830 tb = (MonoReflectionTypeBuilder *)gtd;
11835 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11836 if (tb && tb->generic_container)
11837 mono_reflection_create_generic_class (tb);
11839 MonoType *t = mono_reflection_type_get_handle (type, &error);
11840 mono_error_raise_exception (&error); /* FIXME don't raise here */
11842 klass = mono_class_from_mono_type (t);
11843 if (!klass->generic_container) {
11844 mono_loader_unlock ();
11848 if (klass->wastypebuilder) {
11849 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11854 mono_loader_unlock ();
11856 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11858 return &geninst->byval_arg;
11862 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11864 MonoGenericClass *gclass;
11865 MonoGenericInst *inst;
11867 g_assert (klass->generic_container);
11869 inst = mono_metadata_get_generic_inst (type_argc, types);
11870 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11872 return mono_generic_class_get_class (gclass);
11875 MonoReflectionMethod*
11876 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11880 MonoMethod *method, *inflated;
11881 MonoMethodInflated *imethod;
11882 MonoGenericContext tmp_context;
11883 MonoGenericInst *ginst;
11884 MonoType **type_argv;
11887 /*FIXME but this no longer should happen*/
11888 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11889 #ifndef DISABLE_REFLECTION_EMIT
11890 MonoReflectionMethodBuilder *mb = NULL;
11894 mb = (MonoReflectionMethodBuilder *) rmethod;
11895 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11896 mono_error_raise_exception (&error); /* FIXME don't raise here */
11897 klass = mono_class_from_mono_type (tb);
11899 method = methodbuilder_to_mono_method (klass, mb, &error);
11901 mono_error_raise_exception (&error); /* FIXME don't raise here */
11903 g_assert_not_reached ();
11907 method = rmethod->method;
11910 klass = method->klass;
11912 if (method->is_inflated)
11913 method = ((MonoMethodInflated *) method)->declaring;
11915 count = mono_method_signature (method)->generic_param_count;
11916 if (count != mono_array_length (types))
11919 type_argv = g_new0 (MonoType *, count);
11920 for (i = 0; i < count; i++) {
11921 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11922 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11923 if (!is_ok (&error)) {
11924 g_free (type_argv);
11925 mono_error_raise_exception (&error); /* FIXME don't raise here */
11928 ginst = mono_metadata_get_generic_inst (count, type_argv);
11929 g_free (type_argv);
11931 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11932 tmp_context.method_inst = ginst;
11934 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11935 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11936 imethod = (MonoMethodInflated *) inflated;
11938 /*FIXME but I think this is no longer necessary*/
11939 if (image_is_dynamic (method->klass->image)) {
11940 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11942 * This table maps metadata structures representing inflated methods/fields
11943 * to the reflection objects representing their generic definitions.
11945 mono_image_lock ((MonoImage*)image);
11946 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11947 mono_image_unlock ((MonoImage*)image);
11950 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11951 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11953 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11954 mono_error_raise_exception (&error); /* FIXME don't raise here */
11958 #ifndef DISABLE_REFLECTION_EMIT
11960 static MonoMethod *
11961 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11963 MonoMethodInflated *imethod;
11964 MonoGenericContext *context;
11968 * With generic code sharing the klass might not be inflated.
11969 * This can happen because classes inflated with their own
11970 * type arguments are "normalized" to the uninflated class.
11972 if (!klass->generic_class)
11975 context = mono_class_get_context (klass);
11977 if (klass->method.count && klass->methods) {
11978 /* Find the already created inflated method */
11979 for (i = 0; i < klass->method.count; ++i) {
11980 g_assert (klass->methods [i]->is_inflated);
11981 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11984 g_assert (i < klass->method.count);
11985 imethod = (MonoMethodInflated*)klass->methods [i];
11988 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11989 mono_error_assert_ok (&error);
11992 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11993 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11995 mono_image_lock ((MonoImage*)image);
11996 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11997 mono_image_unlock ((MonoImage*)image);
11999 return (MonoMethod *) imethod;
12002 static MonoMethod *
12003 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12005 MonoMethod *method;
12008 mono_error_init (error);
12010 MonoClass *type_class = mono_object_class (type);
12012 if (is_sre_generic_instance (type_class)) {
12013 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12014 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12015 return_val_if_nok (error, NULL);
12016 gklass = mono_class_from_mono_type (generic_type);
12017 } else if (is_sre_type_builder (type_class)) {
12018 MonoType *t = mono_reflection_type_get_handle (type, error);
12019 return_val_if_nok (error, NULL);
12020 gklass = mono_class_from_mono_type (t);
12021 } else if (type->type) {
12022 gklass = mono_class_from_mono_type (type->type);
12023 gklass = mono_class_get_generic_type_definition (gklass);
12025 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12028 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12029 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12030 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12032 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12036 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12037 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12040 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12041 method = ((MonoReflectionMethod *) obj)->method;
12043 method = NULL; /* prevent compiler warning */
12044 g_error ("can't handle type %s", obj->vtable->klass->name);
12047 MonoType *t = mono_reflection_type_get_handle (type, error);
12048 return_val_if_nok (error, NULL);
12049 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12052 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12054 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12057 MonoGenericClass *gclass;
12058 MonoDynamicGenericClass *dgclass;
12059 MonoClass *klass, *gklass;
12063 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12064 mono_error_raise_exception (&error); /* FIXME don't raise here */
12065 klass = mono_class_from_mono_type (gtype);
12066 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12067 gclass = gtype->data.generic_class;
12069 if (!gclass->is_dynamic)
12072 dgclass = (MonoDynamicGenericClass *) gclass;
12074 if (dgclass->initialized)
12077 gklass = gclass->container_class;
12078 mono_class_init (gklass);
12080 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12082 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12083 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12084 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12086 for (i = 0; i < dgclass->count_fields; i++) {
12088 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12089 MonoClassField *field, *inflated_field = NULL;
12091 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12092 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12093 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12094 field = ((MonoReflectionField *) obj)->field;
12096 field = NULL; /* prevent compiler warning */
12097 g_assert_not_reached ();
12100 dgclass->fields [i] = *field;
12101 dgclass->fields [i].parent = klass;
12102 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12103 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12104 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12105 dgclass->field_generic_types [i] = field->type;
12106 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12107 dgclass->field_objects [i] = obj;
12109 if (inflated_field) {
12110 g_free (inflated_field);
12112 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12116 dgclass->initialized = TRUE;
12120 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12122 MonoDynamicGenericClass *dgclass;
12125 g_assert (gclass->is_dynamic);
12127 dgclass = (MonoDynamicGenericClass *)gclass;
12129 for (i = 0; i < dgclass->count_fields; ++i) {
12130 MonoClassField *field = dgclass->fields + i;
12131 mono_metadata_free_type (field->type);
12132 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12137 fix_partial_generic_class (MonoClass *klass)
12139 MonoClass *gklass = klass->generic_class->container_class;
12140 MonoDynamicGenericClass *dgclass;
12143 if (klass->wastypebuilder)
12146 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12147 if (klass->parent != gklass->parent) {
12149 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12150 if (mono_error_ok (&error)) {
12151 MonoClass *parent = mono_class_from_mono_type (parent_type);
12152 mono_metadata_free_type (parent_type);
12153 if (parent != klass->parent) {
12154 /*fool mono_class_setup_parent*/
12155 klass->supertypes = NULL;
12156 mono_class_setup_parent (klass, parent);
12159 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12160 mono_error_cleanup (&error);
12161 if (gklass->wastypebuilder)
12162 klass->wastypebuilder = TRUE;
12167 if (!dgclass->initialized)
12170 if (klass->method.count != gklass->method.count) {
12171 klass->method.count = gklass->method.count;
12172 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12174 for (i = 0; i < klass->method.count; i++) {
12176 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12177 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12178 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12182 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12183 klass->interface_count = gklass->interface_count;
12184 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12185 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12187 for (i = 0; i < gklass->interface_count; ++i) {
12189 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12190 mono_error_raise_exception (&error); /* FIXME don't raise here */
12192 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12193 mono_metadata_free_type (iface_type);
12195 ensure_runtime_vtable (klass->interfaces [i], &error);
12196 mono_error_raise_exception (&error); /* FIXME don't raise here */
12198 klass->interfaces_inited = 1;
12201 if (klass->field.count != gklass->field.count) {
12202 klass->field.count = gklass->field.count;
12203 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12205 for (i = 0; i < klass->field.count; i++) {
12207 klass->fields [i] = gklass->fields [i];
12208 klass->fields [i].parent = klass;
12209 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12210 mono_error_raise_exception (&error); /* FIXME don't raise here */
12214 /*We can only finish with this klass once it's parent has as well*/
12215 if (gklass->wastypebuilder)
12216 klass->wastypebuilder = TRUE;
12221 * ensure_generic_class_runtime_vtable:
12222 * @klass a generic class
12223 * @error set on error
12225 * Ensures that the generic container of @klass has a vtable and
12226 * returns TRUE on success. On error returns FALSE and sets @error.
12229 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12231 MonoClass *gklass = klass->generic_class->container_class;
12233 mono_error_init (error);
12235 if (!ensure_runtime_vtable (gklass, error))
12238 fix_partial_generic_class (klass);
12244 * ensure_runtime_vtable:
12246 * @error set on error
12248 * Ensures that @klass has a vtable and returns TRUE on success. On
12249 * error returns FALSE and sets @error.
12252 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12254 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12257 mono_error_init (error);
12259 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12262 if (!ensure_runtime_vtable (klass->parent, error))
12266 num = tb->ctors? mono_array_length (tb->ctors): 0;
12267 num += tb->num_methods;
12268 klass->method.count = num;
12269 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12270 num = tb->ctors? mono_array_length (tb->ctors): 0;
12271 for (i = 0; i < num; ++i) {
12272 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12275 klass->methods [i] = ctor;
12277 num = tb->num_methods;
12279 for (i = 0; i < num; ++i) {
12280 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12283 klass->methods [j++] = meth;
12286 if (tb->interfaces) {
12287 klass->interface_count = mono_array_length (tb->interfaces);
12288 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12289 for (i = 0; i < klass->interface_count; ++i) {
12290 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12291 return_val_if_nok (error, FALSE);
12292 klass->interfaces [i] = mono_class_from_mono_type (iface);
12293 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12296 klass->interfaces_inited = 1;
12298 } else if (klass->generic_class){
12299 if (!ensure_generic_class_runtime_vtable (klass, error))
12303 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12305 for (i = 0; i < klass->method.count; ++i) {
12306 MonoMethod *im = klass->methods [i];
12307 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12308 im->slot = slot_num++;
12311 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12312 mono_class_setup_interface_offsets (klass);
12313 mono_class_setup_interface_id (klass);
12317 * The generic vtable is needed even if image->run is not set since some
12318 * runtime code like ves_icall_Type_GetMethodsByName depends on
12319 * method->slot being defined.
12323 * tb->methods could not be freed since it is used for determining
12324 * overrides during dynamic vtable construction.
12331 mono_reflection_method_get_handle (MonoObject *method)
12334 MonoClass *klass = mono_object_class (method);
12335 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12336 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12337 return sr_method->method;
12339 if (is_sre_method_builder (klass)) {
12340 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12341 return mb->mhandle;
12343 if (is_sre_method_on_tb_inst (klass)) {
12344 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12345 MonoMethod *result;
12346 /*FIXME move this to a proper method and unify with resolve_object*/
12347 if (m->method_args) {
12348 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12349 mono_error_raise_exception (&error); /* FIXME don't raise here */
12351 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12352 mono_error_raise_exception (&error); /* FIXME don't raise here */
12353 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12354 MonoMethod *mono_method;
12356 if (is_sre_method_builder (mono_object_class (m->mb)))
12357 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12358 else if (is_sr_mono_method (mono_object_class (m->mb)))
12359 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12361 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)));
12363 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12368 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12373 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12375 MonoReflectionTypeBuilder *tb;
12377 MonoReflectionMethod *m;
12380 *num_overrides = 0;
12382 g_assert (image_is_dynamic (klass->image));
12384 if (!mono_class_get_ref_info (klass))
12387 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12389 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12393 for (i = 0; i < tb->num_methods; ++i) {
12394 MonoReflectionMethodBuilder *mb =
12395 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12396 if (mb->override_methods)
12397 onum += mono_array_length (mb->override_methods);
12402 *overrides = g_new0 (MonoMethod*, onum * 2);
12405 for (i = 0; i < tb->num_methods; ++i) {
12406 MonoReflectionMethodBuilder *mb =
12407 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12408 if (mb->override_methods) {
12409 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12410 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12412 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12413 (*overrides) [onum * 2 + 1] = mb->mhandle;
12415 g_assert (mb->mhandle);
12423 *num_overrides = onum;
12427 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12429 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12430 MonoReflectionFieldBuilder *fb;
12431 MonoClassField *field;
12432 MonoImage *image = klass->image;
12433 const char *p, *p2;
12435 guint32 len, idx, real_size = 0;
12437 klass->field.count = tb->num_fields;
12438 klass->field.first = 0;
12440 mono_error_init (error);
12442 if (tb->class_size) {
12443 if ((tb->packing_size & 0xffffff00) != 0) {
12444 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12445 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12448 klass->packing_size = tb->packing_size;
12449 real_size = klass->instance_size + tb->class_size;
12452 if (!klass->field.count) {
12453 klass->instance_size = MAX (klass->instance_size, real_size);
12457 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12458 mono_class_alloc_ext (klass);
12459 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12461 This is, guess what, a hack.
12462 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12463 On the static path no field class is resolved, only types are built. This is the right thing to do
12465 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12467 klass->size_inited = 1;
12469 for (i = 0; i < klass->field.count; ++i) {
12470 MonoArray *rva_data;
12471 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12472 field = &klass->fields [i];
12473 field->name = mono_string_to_utf8_image (image, fb->name, error);
12474 if (!mono_error_ok (error))
12477 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12478 return_if_nok (error);
12479 field->type = mono_metadata_type_dup (klass->image, type);
12480 field->type->attrs = fb->attrs;
12482 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12483 return_if_nok (error);
12486 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12487 char *base = mono_array_addr (rva_data, char, 0);
12488 size_t size = mono_array_length (rva_data);
12489 char *data = (char *)mono_image_alloc (klass->image, size);
12490 memcpy (data, base, size);
12491 klass->ext->field_def_values [i].data = data;
12493 if (fb->offset != -1)
12494 field->offset = fb->offset;
12495 field->parent = klass;
12496 fb->handle = field;
12497 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12499 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12500 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12502 if (fb->def_value) {
12503 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12504 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12505 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12506 /* Copy the data from the blob since it might get realloc-ed */
12507 p = assembly->blob.data + idx;
12508 len = mono_metadata_decode_blob_size (p, &p2);
12510 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12511 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12515 klass->instance_size = MAX (klass->instance_size, real_size);
12516 mono_class_layout_fields (klass);
12520 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12522 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12523 MonoReflectionPropertyBuilder *pb;
12524 MonoImage *image = klass->image;
12525 MonoProperty *properties;
12528 mono_error_init (error);
12531 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12533 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12534 klass->ext->property.first = 0;
12536 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12537 klass->ext->properties = properties;
12538 for (i = 0; i < klass->ext->property.count; ++i) {
12539 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12540 properties [i].parent = klass;
12541 properties [i].attrs = pb->attrs;
12542 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12543 if (!mono_error_ok (error))
12545 if (pb->get_method)
12546 properties [i].get = pb->get_method->mhandle;
12547 if (pb->set_method)
12548 properties [i].set = pb->set_method->mhandle;
12550 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12551 if (pb->def_value) {
12553 const char *p, *p2;
12554 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12555 if (!klass->ext->prop_def_values)
12556 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12557 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12558 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12559 /* Copy the data from the blob since it might get realloc-ed */
12560 p = assembly->blob.data + idx;
12561 len = mono_metadata_decode_blob_size (p, &p2);
12563 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12564 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12569 MonoReflectionEvent *
12570 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12573 MonoEvent *event = g_new0 (MonoEvent, 1);
12576 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12577 mono_error_raise_exception (&error); /* FIXME don't raise here */
12578 klass = mono_class_from_mono_type (type);
12580 event->parent = klass;
12581 event->attrs = eb->attrs;
12582 event->name = mono_string_to_utf8 (eb->name);
12583 if (eb->add_method)
12584 event->add = eb->add_method->mhandle;
12585 if (eb->remove_method)
12586 event->remove = eb->remove_method->mhandle;
12587 if (eb->raise_method)
12588 event->raise = eb->raise_method->mhandle;
12590 #ifndef MONO_SMALL_CONFIG
12591 if (eb->other_methods) {
12593 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12594 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12595 MonoReflectionMethodBuilder *mb =
12596 mono_array_get (eb->other_methods,
12597 MonoReflectionMethodBuilder*, j);
12598 event->other [j] = mb->mhandle;
12603 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12604 mono_error_raise_exception (&error); /* FIXME don't raise here */
12609 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12611 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12612 MonoReflectionEventBuilder *eb;
12613 MonoImage *image = klass->image;
12617 mono_error_init (error);
12620 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12622 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12623 klass->ext->event.first = 0;
12625 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12626 klass->ext->events = events;
12627 for (i = 0; i < klass->ext->event.count; ++i) {
12628 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12629 events [i].parent = klass;
12630 events [i].attrs = eb->attrs;
12631 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12632 if (!mono_error_ok (error))
12634 if (eb->add_method)
12635 events [i].add = eb->add_method->mhandle;
12636 if (eb->remove_method)
12637 events [i].remove = eb->remove_method->mhandle;
12638 if (eb->raise_method)
12639 events [i].raise = eb->raise_method->mhandle;
12641 #ifndef MONO_SMALL_CONFIG
12642 if (eb->other_methods) {
12644 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12645 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12646 MonoReflectionMethodBuilder *mb =
12647 mono_array_get (eb->other_methods,
12648 MonoReflectionMethodBuilder*, j);
12649 events [i].other [j] = mb->mhandle;
12653 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12658 remove_instantiations_of_and_ensure_contents (gpointer key,
12660 gpointer user_data)
12662 MonoType *type = (MonoType*)key;
12663 MonoClass *klass = (MonoClass*)user_data;
12665 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12666 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12673 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12675 mono_error_init (error);
12681 for (i = 0; i < mono_array_length (arr); ++i) {
12682 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12683 if (!mono_error_ok (error))
12688 MonoReflectionType*
12689 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12693 MonoDomain* domain;
12694 MonoReflectionType* res;
12697 domain = mono_object_domain (tb);
12698 klass = mono_class_from_mono_type (tb->type.type);
12701 * Check for user defined Type subclasses.
12703 RESOLVE_TYPE (tb->parent, &error);
12704 mono_error_raise_exception (&error); /* FIXME don't raise here */
12705 check_array_for_usertypes (tb->interfaces, &error);
12706 mono_error_raise_exception (&error); /*FIXME don't raise here */
12708 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12709 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12711 RESOLVE_TYPE (fb->type, &error);
12712 mono_error_raise_exception (&error); /* FIXME don't raise here */
12713 check_array_for_usertypes (fb->modreq, &error);
12714 mono_error_raise_exception (&error); /*FIXME don't raise here */
12715 check_array_for_usertypes (fb->modopt, &error);
12716 mono_error_raise_exception (&error); /*FIXME don't raise here */
12717 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12718 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12719 mono_error_raise_exception (&error); /* FIXME don't raise here */
12725 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12726 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12728 RESOLVE_TYPE (mb->rtype, &error);
12729 mono_error_raise_exception (&error); /* FIXME don't raise here */
12730 check_array_for_usertypes (mb->return_modreq, &error);
12731 mono_error_raise_exception (&error); /*FIXME don't raise here */
12732 check_array_for_usertypes (mb->return_modopt, &error);
12733 mono_error_raise_exception (&error); /*FIXME don't raise here */
12734 check_array_for_usertypes (mb->parameters, &error);
12735 mono_error_raise_exception (&error); /*FIXME don't raise here */
12736 if (mb->param_modreq)
12737 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12738 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12739 mono_error_raise_exception (&error); /*FIXME don't raise here */
12741 if (mb->param_modopt)
12742 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12743 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12744 mono_error_raise_exception (&error); /*FIXME don't raise here */
12750 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12751 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12753 check_array_for_usertypes (mb->parameters, &error);
12754 mono_error_raise_exception (&error); /*FIXME don't raise here */
12755 if (mb->param_modreq)
12756 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12757 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12758 mono_error_raise_exception (&error); /*FIXME don't raise here */
12760 if (mb->param_modopt)
12761 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12762 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12763 mono_error_raise_exception (&error); /*FIXME don't raise here */
12769 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12772 * we need to lock the domain because the lock will be taken inside
12773 * So, we need to keep the locking order correct.
12775 mono_loader_lock ();
12776 mono_domain_lock (domain);
12777 if (klass->wastypebuilder) {
12778 mono_domain_unlock (domain);
12779 mono_loader_unlock ();
12781 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12782 mono_error_raise_exception (&error); /* FIXME don't raise here */
12787 * Fields to set in klass:
12788 * the various flags: delegate/unicode/contextbound etc.
12790 klass->flags = tb->attrs;
12791 klass->has_cctor = 1;
12792 klass->has_finalize = 1;
12793 klass->has_finalize_inited = 1;
12795 mono_class_setup_parent (klass, klass->parent);
12796 /* fool mono_class_setup_supertypes */
12797 klass->supertypes = NULL;
12798 mono_class_setup_supertypes (klass);
12799 mono_class_setup_mono_type (klass);
12802 if (!((MonoDynamicImage*)klass->image)->run) {
12803 if (klass->generic_container) {
12804 /* FIXME: The code below can't handle generic classes */
12805 klass->wastypebuilder = TRUE;
12806 mono_loader_unlock ();
12807 mono_domain_unlock (domain);
12809 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12810 mono_error_raise_exception (&error); /* FIXME don't raise here */
12817 /* enums are done right away */
12818 if (!klass->enumtype)
12819 if (!ensure_runtime_vtable (klass, &error))
12822 if (tb->subtypes) {
12823 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12824 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12825 mono_class_alloc_ext (klass);
12826 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12827 if (!is_ok (&error)) goto failure;
12828 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12832 klass->nested_classes_inited = TRUE;
12834 /* fields and object layout */
12835 if (klass->parent) {
12836 if (!klass->parent->size_inited)
12837 mono_class_init (klass->parent);
12838 klass->instance_size = klass->parent->instance_size;
12839 klass->sizes.class_size = 0;
12840 klass->min_align = klass->parent->min_align;
12841 /* if the type has no fields we won't call the field_setup
12842 * routine which sets up klass->has_references.
12844 klass->has_references |= klass->parent->has_references;
12846 klass->instance_size = sizeof (MonoObject);
12847 klass->min_align = 1;
12850 /* FIXME: handle packing_size and instance_size */
12851 typebuilder_setup_fields (klass, &error);
12852 if (!mono_error_ok (&error))
12854 typebuilder_setup_properties (klass, &error);
12855 if (!mono_error_ok (&error))
12858 typebuilder_setup_events (klass, &error);
12859 if (!mono_error_ok (&error))
12862 klass->wastypebuilder = TRUE;
12865 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12866 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12867 * we want to return normal System.MonoType objects, so clear these out from the cache.
12869 * Together with this we must ensure the contents of all instances to match the created type.
12871 if (domain->type_hash && klass->generic_container)
12872 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12874 mono_domain_unlock (domain);
12875 mono_loader_unlock ();
12877 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12878 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12879 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12882 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12883 mono_error_raise_exception (&error); /* FIXME don't raise here */
12885 g_assert (res != (MonoReflectionType*)tb);
12890 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12891 klass->wastypebuilder = TRUE;
12892 mono_domain_unlock (domain);
12893 mono_loader_unlock ();
12894 mono_error_raise_exception (&error);
12899 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12901 MonoGenericParamFull *param;
12906 image = &gparam->tbuilder->module->dynamic_image->image;
12908 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12910 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12911 g_assert (mono_error_ok (&error));
12912 param->param.num = gparam->index;
12914 if (gparam->mbuilder) {
12915 if (!gparam->mbuilder->generic_container) {
12916 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12917 mono_error_raise_exception (&error); /* FIXME don't raise here */
12919 MonoClass *klass = mono_class_from_mono_type (tb);
12920 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12921 gparam->mbuilder->generic_container->is_method = TRUE;
12923 * Cannot set owner.method, since the MonoMethod is not created yet.
12924 * Set the image field instead, so type_in_image () works.
12926 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12927 gparam->mbuilder->generic_container->owner.image = klass->image;
12929 param->param.owner = gparam->mbuilder->generic_container;
12930 } else if (gparam->tbuilder) {
12931 if (!gparam->tbuilder->generic_container) {
12932 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12933 mono_error_raise_exception (&error); /* FIXME don't raise here */
12934 MonoClass *klass = mono_class_from_mono_type (tb);
12935 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12936 gparam->tbuilder->generic_container->owner.klass = klass;
12938 param->param.owner = gparam->tbuilder->generic_container;
12941 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12943 gparam->type.type = &pklass->byval_arg;
12945 mono_class_set_ref_info (pklass, gparam);
12946 mono_image_append_class_to_reflection_info_set (pklass);
12950 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12953 MonoReflectionModuleBuilder *module = sig->module;
12954 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12955 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12960 check_array_for_usertypes (sig->arguments, &error);
12961 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12963 sigbuffer_init (&buf, 32);
12965 sigbuffer_add_value (&buf, 0x07);
12966 sigbuffer_add_value (&buf, na);
12967 if (assembly != NULL){
12968 for (i = 0; i < na; ++i) {
12969 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12970 encode_reflection_type (assembly, type, &buf);
12974 buflen = buf.p - buf.buf;
12975 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12976 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12977 sigbuffer_free (&buf);
12983 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12986 MonoDynamicImage *assembly = sig->module->dynamic_image;
12987 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12992 check_array_for_usertypes (sig->arguments, &error);
12993 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12995 sigbuffer_init (&buf, 32);
12997 sigbuffer_add_value (&buf, 0x06);
12998 for (i = 0; i < na; ++i) {
12999 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13000 encode_reflection_type (assembly, type, &buf);
13003 buflen = buf.p - buf.buf;
13004 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13005 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13006 sigbuffer_free (&buf);
13012 MonoMethod *handle;
13013 MonoDomain *domain;
13014 } DynamicMethodReleaseData;
13017 * The runtime automatically clean up those after finalization.
13019 static MonoReferenceQueue *dynamic_method_queue;
13022 free_dynamic_method (void *dynamic_method)
13024 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13025 MonoDomain *domain = data->domain;
13026 MonoMethod *method = data->handle;
13029 mono_domain_lock (domain);
13030 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13031 g_hash_table_remove (domain->method_to_dyn_method, method);
13032 mono_domain_unlock (domain);
13033 g_assert (dis_link);
13034 mono_gchandle_free (dis_link);
13036 mono_runtime_free_method (domain, method);
13041 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13044 MonoReferenceQueue *queue;
13045 MonoMethod *handle;
13046 DynamicMethodReleaseData *release_data;
13047 ReflectionMethodBuilder rmb;
13048 MonoMethodSignature *sig;
13050 MonoDomain *domain;
13054 if (mono_runtime_is_shutting_down ())
13055 mono_raise_exception (mono_get_exception_invalid_operation (""));
13057 if (!(queue = dynamic_method_queue)) {
13058 mono_loader_lock ();
13059 if (!(queue = dynamic_method_queue))
13060 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13061 mono_loader_unlock ();
13064 sig = dynamic_method_to_signature (mb);
13066 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13069 * Resolve references.
13072 * Every second entry in the refs array is reserved for storing handle_class,
13073 * which is needed by the ldtoken implementation in the JIT.
13075 rmb.nrefs = mb->nrefs;
13076 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13077 for (i = 0; i < mb->nrefs; i += 2) {
13078 MonoClass *handle_class;
13080 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13082 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13083 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13085 * The referenced DynamicMethod should already be created by the managed
13086 * code, except in the case of circular references. In that case, we store
13087 * method in the refs array, and fix it up later when the referenced
13088 * DynamicMethod is created.
13090 if (method->mhandle) {
13091 ref = method->mhandle;
13093 /* FIXME: GC object stored in unmanaged memory */
13096 /* FIXME: GC object stored in unmanaged memory */
13097 method->referenced_by = g_slist_append (method->referenced_by, mb);
13099 handle_class = mono_defaults.methodhandle_class;
13101 MonoException *ex = NULL;
13102 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13104 ex = mono_get_exception_type_load (NULL, NULL);
13105 else if (mono_security_core_clr_enabled ())
13106 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13110 mono_raise_exception (ex);
13115 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13116 rmb.refs [i + 1] = handle_class;
13120 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13121 if (!is_ok (&error)) {
13123 mono_error_raise_exception (&error); /* FIXME don't raise here */
13125 klass = mono_class_from_mono_type (owner_type);
13127 klass = mono_defaults.object_class;
13130 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13131 release_data = g_new (DynamicMethodReleaseData, 1);
13132 release_data->handle = handle;
13133 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13134 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13135 g_free (release_data);
13137 /* Fix up refs entries pointing at us */
13138 for (l = mb->referenced_by; l; l = l->next) {
13139 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13140 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13143 g_assert (method->mhandle);
13145 data = (gpointer*)wrapper->method_data;
13146 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13147 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13148 data [i + 1] = mb->mhandle;
13151 g_slist_free (mb->referenced_by);
13155 /* ilgen is no longer needed */
13158 domain = mono_domain_get ();
13159 mono_domain_lock (domain);
13160 if (!domain->method_to_dyn_method)
13161 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13162 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13163 mono_domain_unlock (domain);
13166 #endif /* DISABLE_REFLECTION_EMIT */
13170 * mono_reflection_is_valid_dynamic_token:
13172 * Returns TRUE if token is valid.
13176 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13178 return lookup_dyn_token (image, token) != NULL;
13181 MonoMethodSignature *
13182 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13184 MonoMethodSignature *sig;
13185 g_assert (image_is_dynamic (image));
13187 mono_error_init (error);
13189 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13193 return mono_method_signature_checked (method, error);
13196 #ifndef DISABLE_REFLECTION_EMIT
13199 * mono_reflection_lookup_dynamic_token:
13201 * Finish the Builder object pointed to by TOKEN and return the corresponding
13202 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13203 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13206 * LOCKING: Take the loader lock
13209 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13211 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13215 obj = lookup_dyn_token (assembly, token);
13218 g_error ("Could not find required dynamic token 0x%08x", token);
13224 handle_class = &klass;
13225 return resolve_object (image, obj, handle_class, context);
13229 * ensure_complete_type:
13231 * Ensure that KLASS is completed if it is a dynamic type, or references
13235 ensure_complete_type (MonoClass *klass)
13239 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13240 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13242 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13243 mono_error_raise_exception (&error); /* FIXME don't raise here */
13245 // Asserting here could break a lot of code
13246 //g_assert (klass->wastypebuilder);
13249 if (klass->generic_class) {
13250 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13253 for (i = 0; i < inst->type_argc; ++i) {
13254 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13260 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13263 gpointer result = NULL;
13265 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13266 result = mono_string_intern_checked ((MonoString*)obj, &error);
13267 mono_error_raise_exception (&error); /* FIXME don't raise here */
13268 *handle_class = mono_defaults.string_class;
13270 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13271 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13272 mono_error_raise_exception (&error); /* FIXME don't raise here */
13273 MonoClass *mc = mono_class_from_mono_type (type);
13274 if (!mono_class_init (mc))
13275 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13278 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13279 mono_error_raise_exception (&error); /* FIXME don't raise here */
13281 result = mono_class_from_mono_type (inflated);
13282 mono_metadata_free_type (inflated);
13284 result = mono_class_from_mono_type (type);
13286 *handle_class = mono_defaults.typehandle_class;
13288 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13289 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13290 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13291 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13292 result = ((MonoReflectionMethod*)obj)->method;
13295 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13296 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13298 *handle_class = mono_defaults.methodhandle_class;
13300 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13301 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13302 result = mb->mhandle;
13304 /* Type is not yet created */
13305 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13307 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13308 mono_error_raise_exception (&error); /* FIXME don't raise here */
13311 * Hopefully this has been filled in by calling CreateType() on the
13315 * TODO: This won't work if the application finishes another
13316 * TypeBuilder instance instead of this one.
13318 result = mb->mhandle;
13322 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13323 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13325 *handle_class = mono_defaults.methodhandle_class;
13326 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13327 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13329 result = cb->mhandle;
13331 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13333 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13334 mono_error_raise_exception (&error); /* FIXME don't raise here */
13335 result = cb->mhandle;
13339 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13340 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13342 *handle_class = mono_defaults.methodhandle_class;
13343 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13344 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13346 ensure_complete_type (field->parent);
13348 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13349 mono_error_raise_exception (&error); /* FIXME don't raise here */
13351 MonoClass *klass = mono_class_from_mono_type (inflated);
13352 MonoClassField *inflated_field;
13353 gpointer iter = NULL;
13354 mono_metadata_free_type (inflated);
13355 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13356 if (!strcmp (field->name, inflated_field->name))
13359 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13360 result = inflated_field;
13364 *handle_class = mono_defaults.fieldhandle_class;
13366 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13367 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13368 result = fb->handle;
13371 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13373 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13374 mono_error_raise_exception (&error); /* FIXME don't raise here */
13375 result = fb->handle;
13378 if (fb->handle && fb->handle->parent->generic_container) {
13379 MonoClass *klass = fb->handle->parent;
13380 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13381 mono_error_raise_exception (&error); /* FIXME don't raise here */
13383 MonoClass *inflated = mono_class_from_mono_type (type);
13385 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13387 mono_metadata_free_type (type);
13389 *handle_class = mono_defaults.fieldhandle_class;
13390 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13391 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13392 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13393 mono_error_raise_exception (&error); /* FIXME don't raise here */
13396 klass = type->data.klass;
13397 if (klass->wastypebuilder) {
13398 /* Already created */
13402 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13403 mono_error_raise_exception (&error); /* FIXME don't raise here */
13404 result = type->data.klass;
13407 *handle_class = mono_defaults.typehandle_class;
13408 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13409 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13410 MonoMethodSignature *sig;
13413 if (helper->arguments)
13414 nargs = mono_array_length (helper->arguments);
13418 sig = mono_metadata_signature_alloc (image, nargs);
13419 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13420 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13422 if (helper->unmanaged_call_conv) { /* unmanaged */
13423 sig->call_convention = helper->unmanaged_call_conv - 1;
13424 sig->pinvoke = TRUE;
13425 } else if (helper->call_conv & 0x02) {
13426 sig->call_convention = MONO_CALL_VARARG;
13428 sig->call_convention = MONO_CALL_DEFAULT;
13431 sig->param_count = nargs;
13432 /* TODO: Copy type ? */
13433 sig->ret = helper->return_type->type;
13434 for (i = 0; i < nargs; ++i) {
13435 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13436 mono_error_raise_exception (&error); /* FIXME don't raise here */
13440 *handle_class = NULL;
13441 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13442 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13443 /* Already created by the managed code */
13444 g_assert (method->mhandle);
13445 result = method->mhandle;
13446 *handle_class = mono_defaults.methodhandle_class;
13447 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13448 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13449 mono_error_raise_exception (&error); /* FIXME don't raise here */
13450 type = mono_class_inflate_generic_type_checked (type, context, &error);
13451 mono_error_raise_exception (&error); /* FIXME don't raise here */
13453 result = mono_class_from_mono_type (type);
13454 *handle_class = mono_defaults.typehandle_class;
13456 mono_metadata_free_type (type);
13457 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13458 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13459 mono_error_raise_exception (&error); /* FIXME don't raise here */
13460 type = mono_class_inflate_generic_type_checked (type, context, &error);
13461 mono_error_raise_exception (&error); /* FIXME don't raise here */
13463 result = mono_class_from_mono_type (type);
13464 *handle_class = mono_defaults.typehandle_class;
13466 mono_metadata_free_type (type);
13467 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13468 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13469 MonoClass *inflated;
13471 MonoClassField *field;
13473 if (is_sre_field_builder (mono_object_class (f->fb)))
13474 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13475 else if (is_sr_mono_field (mono_object_class (f->fb)))
13476 field = ((MonoReflectionField*)f->fb)->field;
13478 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)));
13480 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13481 mono_error_raise_exception (&error); /* FIXME don't raise here */
13482 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13483 mono_error_raise_exception (&error); /* FIXME don't raise here */
13485 inflated = mono_class_from_mono_type (type);
13487 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13488 ensure_complete_type (field->parent);
13490 mono_metadata_free_type (type);
13491 *handle_class = mono_defaults.fieldhandle_class;
13492 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13493 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13494 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13495 mono_error_raise_exception (&error); /* FIXME don't raise here */
13496 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13497 mono_error_raise_exception (&error); /* FIXME don't raise here */
13499 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13500 MonoMethod *method;
13502 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13503 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13504 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13505 method = ((MonoReflectionMethod *)c->cb)->method;
13507 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)));
13509 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13510 *handle_class = mono_defaults.methodhandle_class;
13511 mono_metadata_free_type (type);
13512 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13513 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13514 if (m->method_args) {
13515 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13516 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13519 mono_error_assert_ok (&error);
13522 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13523 mono_error_raise_exception (&error); /* FIXME don't raise here */
13524 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13525 mono_error_raise_exception (&error); /* FIXME don't raise here */
13527 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13528 MonoMethod *method;
13530 if (is_sre_method_builder (mono_object_class (m->mb)))
13531 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13532 else if (is_sr_mono_method (mono_object_class (m->mb)))
13533 method = ((MonoReflectionMethod *)m->mb)->method;
13535 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)));
13537 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13538 mono_metadata_free_type (type);
13540 *handle_class = mono_defaults.methodhandle_class;
13541 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13542 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13545 MonoMethod *method;
13549 mtype = mono_reflection_type_get_handle (m->parent, &error);
13550 mono_error_raise_exception (&error); /* FIXME don't raise here */
13551 klass = mono_class_from_mono_type (mtype);
13553 /* Find the method */
13555 name = mono_string_to_utf8 (m->name);
13557 while ((method = mono_class_get_methods (klass, &iter))) {
13558 if (!strcmp (method->name, name))
13565 // FIXME: Check parameters/return value etc. match
13568 *handle_class = mono_defaults.methodhandle_class;
13569 } else if (is_sre_array (mono_object_get_class(obj)) ||
13570 is_sre_byref (mono_object_get_class(obj)) ||
13571 is_sre_pointer (mono_object_get_class(obj))) {
13572 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13573 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13574 mono_error_raise_exception (&error); /* FIXME don't raise here */
13577 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13578 mono_error_raise_exception (&error); /* FIXME don't raise here */
13580 result = mono_class_from_mono_type (inflated);
13581 mono_metadata_free_type (inflated);
13583 result = mono_class_from_mono_type (type);
13585 *handle_class = mono_defaults.typehandle_class;
13587 g_print ("%s\n", obj->vtable->klass->name);
13588 g_assert_not_reached ();
13593 #else /* DISABLE_REFLECTION_EMIT */
13596 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13598 g_assert_not_reached ();
13603 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13605 g_assert_not_reached ();
13609 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13611 g_assert_not_reached ();
13615 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13617 g_assert_not_reached ();
13621 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13623 g_assert_not_reached ();
13627 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13629 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13633 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13635 g_assert_not_reached ();
13639 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13641 g_assert_not_reached ();
13644 MonoReflectionModule *
13645 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13647 g_assert_not_reached ();
13652 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13654 g_assert_not_reached ();
13659 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13661 g_assert_not_reached ();
13666 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13667 gboolean create_open_instance, gboolean register_token, MonoError *error)
13669 g_assert_not_reached ();
13674 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13679 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13681 g_assert_not_reached ();
13685 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13688 *num_overrides = 0;
13691 MonoReflectionEvent *
13692 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13694 g_assert_not_reached ();
13698 MonoReflectionType*
13699 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13701 g_assert_not_reached ();
13706 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13708 g_assert_not_reached ();
13712 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13714 g_assert_not_reached ();
13719 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13721 g_assert_not_reached ();
13726 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13731 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13737 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
13739 mono_error_init (error);
13746 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13748 g_assert_not_reached ();
13751 #endif /* DISABLE_REFLECTION_EMIT */
13753 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13754 const static guint32 declsec_flags_map[] = {
13755 0x00000000, /* empty */
13756 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13757 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13758 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13759 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13760 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13761 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13762 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13763 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13764 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13765 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13766 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13767 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13768 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13769 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13770 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13771 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13772 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13773 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13777 * Returns flags that includes all available security action associated to the handle.
13778 * @token: metadata token (either for a class or a method)
13779 * @image: image where resides the metadata.
13782 mono_declsec_get_flags (MonoImage *image, guint32 token)
13784 int index = mono_metadata_declsec_from_index (image, token);
13785 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13786 guint32 result = 0;
13790 /* HasSecurity can be present for other, not specially encoded, attributes,
13791 e.g. SuppressUnmanagedCodeSecurityAttribute */
13795 for (i = index; i < t->rows; i++) {
13796 guint32 cols [MONO_DECL_SECURITY_SIZE];
13798 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13799 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13802 action = cols [MONO_DECL_SECURITY_ACTION];
13803 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13804 result |= declsec_flags_map [action];
13806 g_assert_not_reached ();
13813 * Get the security actions (in the form of flags) associated with the specified method.
13815 * @method: The method for which we want the declarative security flags.
13816 * Return the declarative security flags for the method (only).
13818 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13819 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13822 mono_declsec_flags_from_method (MonoMethod *method)
13824 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13825 /* FIXME: No cache (for the moment) */
13826 guint32 idx = mono_method_get_index (method);
13827 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13828 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13829 return mono_declsec_get_flags (method->klass->image, idx);
13835 * Get the security actions (in the form of flags) associated with the specified class.
13837 * @klass: The class for which we want the declarative security flags.
13838 * Return the declarative security flags for the class.
13840 * Note: We cache the flags inside the MonoClass structure as this will get
13841 * called very often (at least for each method).
13844 mono_declsec_flags_from_class (MonoClass *klass)
13846 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13847 if (!klass->ext || !klass->ext->declsec_flags) {
13850 idx = mono_metadata_token_index (klass->type_token);
13851 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13852 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13853 mono_loader_lock ();
13854 mono_class_alloc_ext (klass);
13855 mono_loader_unlock ();
13856 /* we cache the flags on classes */
13857 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13859 return klass->ext->declsec_flags;
13865 * Get the security actions (in the form of flags) associated with the specified assembly.
13867 * @assembly: The assembly for which we want the declarative security flags.
13868 * Return the declarative security flags for the assembly.
13871 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13873 guint32 idx = 1; /* there is only one assembly */
13874 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13875 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13876 return mono_declsec_get_flags (assembly->image, idx);
13881 * Fill actions for the specific index (which may either be an encoded class token or
13882 * an encoded method token) from the metadata image.
13883 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13886 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13887 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13889 MonoBoolean result = FALSE;
13891 guint32 cols [MONO_DECL_SECURITY_SIZE];
13892 int index = mono_metadata_declsec_from_index (image, token);
13895 t = &image->tables [MONO_TABLE_DECLSECURITY];
13896 for (i = index; i < t->rows; i++) {
13897 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13899 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13902 /* if present only replace (class) permissions with method permissions */
13903 /* if empty accept either class or method permissions */
13904 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13905 if (!actions->demand.blob) {
13906 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13907 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13908 actions->demand.blob = (char*) (blob + 2);
13909 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13912 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13913 if (!actions->noncasdemand.blob) {
13914 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13915 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13916 actions->noncasdemand.blob = (char*) (blob + 2);
13917 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13920 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13921 if (!actions->demandchoice.blob) {
13922 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13923 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13924 actions->demandchoice.blob = (char*) (blob + 2);
13925 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13935 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13936 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13938 guint32 idx = mono_metadata_token_index (klass->type_token);
13939 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13940 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13941 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13945 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13946 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13948 guint32 idx = mono_method_get_index (method);
13949 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13950 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13951 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13955 * Collect all actions (that requires to generate code in mini) assigned for
13956 * the specified method.
13957 * Note: Don't use the content of actions if the function return FALSE.
13960 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13962 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13963 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13964 MonoBoolean result = FALSE;
13967 /* quick exit if no declarative security is present in the metadata */
13968 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13971 /* we want the original as the wrapper is "free" of the security informations */
13972 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13973 method = mono_marshal_method_from_wrapper (method);
13978 /* First we look for method-level attributes */
13979 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13980 mono_class_init (method->klass);
13981 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13983 result = mono_declsec_get_method_demands_params (method, demands,
13984 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13987 /* Here we use (or create) the class declarative cache to look for demands */
13988 flags = mono_declsec_flags_from_class (method->klass);
13989 if (flags & mask) {
13991 mono_class_init (method->klass);
13992 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13994 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13995 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13998 /* The boolean return value is used as a shortcut in case nothing needs to
13999 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14005 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14007 * Note: Don't use the content of actions if the function return FALSE.
14010 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14012 MonoBoolean result = FALSE;
14015 /* quick exit if no declarative security is present in the metadata */
14016 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14019 /* we want the original as the wrapper is "free" of the security informations */
14020 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14021 method = mono_marshal_method_from_wrapper (method);
14026 /* results are independant - zeroize both */
14027 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14028 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14030 /* First we look for method-level attributes */
14031 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14032 mono_class_init (method->klass);
14034 result = mono_declsec_get_method_demands_params (method, cmethod,
14035 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14038 /* Here we use (or create) the class declarative cache to look for demands */
14039 flags = mono_declsec_flags_from_class (method->klass);
14040 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14041 mono_class_init (method->klass);
14043 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14044 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14051 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14053 * @klass The inherited class - this is the class that provides the security check (attributes)
14055 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14057 * Note: Don't use the content of actions if the function return FALSE.
14060 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14062 MonoBoolean result = FALSE;
14065 /* quick exit if no declarative security is present in the metadata */
14066 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14069 /* Here we use (or create) the class declarative cache to look for demands */
14070 flags = mono_declsec_flags_from_class (klass);
14071 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14072 mono_class_init (klass);
14073 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14075 result |= mono_declsec_get_class_demands_params (klass, demands,
14076 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14083 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14085 * Note: Don't use the content of actions if the function return FALSE.
14088 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14090 /* quick exit if no declarative security is present in the metadata */
14091 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14094 /* we want the original as the wrapper is "free" of the security informations */
14095 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14096 method = mono_marshal_method_from_wrapper (method);
14101 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14102 mono_class_init (method->klass);
14103 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14105 return mono_declsec_get_method_demands_params (method, demands,
14106 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14113 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14115 guint32 cols [MONO_DECL_SECURITY_SIZE];
14119 int index = mono_metadata_declsec_from_index (image, token);
14123 t = &image->tables [MONO_TABLE_DECLSECURITY];
14124 for (i = index; i < t->rows; i++) {
14125 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14127 /* shortcut - index are ordered */
14128 if (token != cols [MONO_DECL_SECURITY_PARENT])
14131 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14132 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14133 entry->blob = (char*) (metadata + 2);
14134 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14143 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14145 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14146 guint32 idx = mono_method_get_index (method);
14147 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14148 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14149 return get_declsec_action (method->klass->image, idx, action, entry);
14155 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14158 guint32 flags = mono_declsec_flags_from_class (klass);
14159 if (declsec_flags_map [action] & flags) {
14160 guint32 idx = mono_metadata_token_index (klass->type_token);
14161 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14162 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14163 return get_declsec_action (klass->image, idx, action, entry);
14169 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14171 guint32 idx = 1; /* there is only one assembly */
14172 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14173 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14175 return get_declsec_action (assembly->image, idx, action, entry);
14179 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14182 MonoObject *res, *exc;
14184 static MonoMethod *method = NULL;
14186 if (method == NULL) {
14187 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14192 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14193 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14195 g_assert (mono_class_get_ref_info (klass));
14196 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14198 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14199 mono_error_raise_exception (&error); /* FIXME don't raise here */
14201 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14203 if (exc || !mono_error_ok (&error)) {
14204 mono_error_cleanup (&error);
14207 return *(MonoBoolean*)mono_object_unbox (res);
14211 * mono_reflection_type_get_type:
14212 * @reftype: the System.Type object
14214 * Returns the MonoType* associated with the C# System.Type object @reftype.
14217 mono_reflection_type_get_type (MonoReflectionType *reftype)
14219 g_assert (reftype);
14222 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14223 mono_error_assert_ok (&error);
14228 * mono_reflection_assembly_get_assembly:
14229 * @refassembly: the System.Reflection.Assembly object
14231 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14234 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14236 g_assert (refassembly);
14238 return refassembly->assembly;