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);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 /* 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;
925 sigbuffer_add_value (buf, MONO_TYPE_VOID);
929 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
935 MONO_REQ_GC_UNSAFE_MODE;
940 for (i = 0; i < mono_array_length (modreq); ++i) {
941 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
947 for (i = 0; i < mono_array_length (modopt); ++i) {
948 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
955 #ifndef DISABLE_REFLECTION_EMIT
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
959 MONO_REQ_GC_UNSAFE_MODE;
963 guint32 nparams = sig->param_count;
969 sigbuffer_init (&buf, 32);
971 * FIXME: vararg, explicit_this, differenc call_conv values...
973 idx = sig->call_convention;
975 idx |= 0x20; /* hasthis */
976 if (sig->generic_param_count)
977 idx |= 0x10; /* generic */
978 sigbuffer_add_byte (&buf, idx);
979 if (sig->generic_param_count)
980 sigbuffer_add_value (&buf, sig->generic_param_count);
981 sigbuffer_add_value (&buf, nparams);
982 encode_type (assembly, sig->ret, &buf);
983 for (i = 0; i < nparams; ++i) {
984 if (i == sig->sentinelpos)
985 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986 encode_type (assembly, sig->params [i], &buf);
988 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989 sigbuffer_free (&buf);
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
997 MONO_REQ_GC_UNSAFE_MODE;
1000 * FIXME: reuse code from method_encode_signature().
1004 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1005 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1009 sigbuffer_init (&buf, 32);
1010 /* LAMESPEC: all the call conv spec is foobared */
1011 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012 if (mb->call_conv & 2)
1013 idx |= 0x5; /* vararg */
1014 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015 idx |= 0x20; /* hasthis */
1017 idx |= 0x10; /* generic */
1018 sigbuffer_add_byte (&buf, idx);
1020 sigbuffer_add_value (&buf, ngparams);
1021 sigbuffer_add_value (&buf, nparams + notypes);
1022 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023 encode_reflection_type (assembly, mb->rtype, &buf);
1024 for (i = 0; i < nparams; ++i) {
1025 MonoArray *modreq = NULL;
1026 MonoArray *modopt = NULL;
1027 MonoReflectionType *pt;
1029 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035 encode_reflection_type (assembly, pt, &buf);
1038 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039 for (i = 0; i < notypes; ++i) {
1040 MonoReflectionType *pt;
1042 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043 encode_reflection_type (assembly, pt, &buf);
1046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047 sigbuffer_free (&buf);
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1054 MONO_REQ_GC_UNSAFE_MODE;
1056 MonoDynamicTable *table;
1058 guint32 idx, sig_idx;
1059 guint nl = mono_array_length (ilgen->locals);
1063 sigbuffer_init (&buf, 32);
1064 sigbuffer_add_value (&buf, 0x07);
1065 sigbuffer_add_value (&buf, nl);
1066 for (i = 0; i < nl; ++i) {
1067 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1070 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1072 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1074 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075 sigbuffer_free (&buf);
1077 if (assembly->standalonesig_cache == NULL)
1078 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1083 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084 idx = table->next_idx ++;
1086 alloc_table (table, table->rows);
1087 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1089 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1091 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 guint32 num_clauses = 0;
1104 MonoILExceptionInfo *ex_info;
1105 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107 if (ex_info->handlers)
1108 num_clauses += mono_array_length (ex_info->handlers);
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1120 MONO_REQ_GC_UNSAFE_MODE;
1122 MonoExceptionClause *clauses;
1123 MonoExceptionClause *clause;
1124 MonoILExceptionInfo *ex_info;
1125 MonoILExceptionBlock *ex_block;
1126 guint32 finally_start;
1127 int i, j, clause_index;;
1129 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1132 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134 finally_start = ex_info->start + ex_info->len;
1135 if (!ex_info->handlers)
1137 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139 clause = &(clauses [clause_index]);
1141 clause->flags = ex_block->type;
1142 clause->try_offset = ex_info->start;
1144 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145 clause->try_len = finally_start - ex_info->start;
1147 clause->try_len = ex_info->len;
1148 clause->handler_offset = ex_block->start;
1149 clause->handler_len = ex_block->len;
1150 if (ex_block->extype) {
1151 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1153 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154 clause->data.filter_offset = ex_block->filter_offset;
1156 clause->data.filter_offset = 0;
1158 finally_start = ex_block->start + ex_block->len;
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1169 * method_encode_code:
1171 * @assembly the assembly
1172 * @mb the managed MethodBuilder
1173 * @error set on error
1175 * Note that the return value is not sensible if @error is set.
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1180 MONO_REQ_GC_UNSAFE_MODE;
1185 gint32 max_stack, i;
1186 gint32 num_locals = 0;
1187 gint32 num_exception = 0;
1190 char fat_header [12];
1192 guint16 short_value;
1193 guint32 local_sig = 0;
1194 guint32 header_size = 12;
1197 mono_error_init (error);
1199 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1204 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1206 code = mb->ilgen->code;
1207 code_size = mb->ilgen->code_len;
1208 max_stack = mb->ilgen->max_stack;
1209 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210 if (mb->ilgen->ex_handlers)
1211 num_exception = method_count_clauses (mb->ilgen);
1215 char *name = mono_string_to_utf8 (mb->name);
1216 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1223 code_size = mono_array_length (code);
1224 max_stack = 8; /* we probably need to run a verifier on the code... */
1227 stream_data_align (&assembly->code);
1229 /* check for exceptions, maxstack, locals */
1230 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1232 if (code_size < 64 && !(code_size & 1)) {
1233 flags = (code_size << 2) | 0x2;
1234 } else if (code_size < 32 && (code_size & 1)) {
1235 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1239 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240 /* add to the fixup todo list */
1241 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244 return assembly->text_rva + idx;
1248 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1250 * FIXME: need to set also the header size in fat_flags.
1251 * (and more sects and init locals flags)
1255 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256 if (mb->init_locals)
1257 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258 fat_header [0] = fat_flags;
1259 fat_header [1] = (header_size / 4 ) << 4;
1260 short_value = GUINT16_TO_LE (max_stack);
1261 memcpy (fat_header + 2, &short_value, 2);
1262 int_value = GUINT32_TO_LE (code_size);
1263 memcpy (fat_header + 4, &int_value, 4);
1264 int_value = GUINT32_TO_LE (local_sig);
1265 memcpy (fat_header + 8, &int_value, 4);
1266 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267 /* add to the fixup todo list */
1268 if (mb->ilgen && mb->ilgen->num_token_fixups)
1269 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1271 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272 if (num_exception) {
1273 unsigned char sheader [4];
1274 MonoILExceptionInfo * ex_info;
1275 MonoILExceptionBlock * ex_block;
1278 stream_data_align (&assembly->code);
1279 /* always use fat format for now */
1280 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281 num_exception *= 6 * sizeof (guint32);
1282 num_exception += 4; /* include the size of the header */
1283 sheader [1] = num_exception & 0xff;
1284 sheader [2] = (num_exception >> 8) & 0xff;
1285 sheader [3] = (num_exception >> 16) & 0xff;
1286 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287 /* fat header, so we are already aligned */
1289 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291 if (ex_info->handlers) {
1292 int finally_start = ex_info->start + ex_info->len;
1293 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1295 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1297 val = GUINT32_TO_LE (ex_block->type);
1298 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1300 val = GUINT32_TO_LE (ex_info->start);
1301 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302 /* need fault, too, probably */
1303 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304 val = GUINT32_TO_LE (finally_start - ex_info->start);
1306 val = GUINT32_TO_LE (ex_info->len);
1307 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308 /* handler offset */
1309 val = GUINT32_TO_LE (ex_block->start);
1310 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1312 val = GUINT32_TO_LE (ex_block->len);
1313 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314 finally_start = ex_block->start + ex_block->len;
1315 if (ex_block->extype) {
1316 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1318 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319 val = ex_block->filter_offset;
1323 val = GUINT32_TO_LE (val);
1324 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325 /*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",
1326 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);*/
1329 g_error ("No clauses for ex info block %d", i);
1333 return assembly->text_rva + idx;
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1339 MONO_REQ_GC_NEUTRAL_MODE;
1342 MonoDynamicTable *table;
1345 table = &assembly->tables [table_idx];
1347 g_assert (col < table->columns);
1349 values = table->values + table->columns;
1350 for (i = 1; i <= table->rows; ++i) {
1351 if (values [col] == token)
1353 values += table->columns;
1359 * LOCKING: Acquires the loader lock.
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1364 MONO_REQ_GC_NEUTRAL_MODE;
1366 MonoCustomAttrInfo* res;
1368 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1373 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1381 MONO_REQ_GC_UNSAFE_MODE;
1383 /* FIXME: Need to do more checks */
1384 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1387 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1397 MONO_REQ_GC_UNSAFE_MODE;
1399 int i, index, count, not_visible;
1400 MonoCustomAttrInfo *ainfo;
1401 MonoReflectionCustomAttr *cattr;
1405 /* FIXME: check in assembly the Run flag is set */
1407 count = mono_array_length (cattrs);
1409 /* Skip nonpublic attributes since MS.NET seems to do the same */
1410 /* FIXME: This needs to be done more globally */
1412 for (i = 0; i < count; ++i) {
1413 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414 if (!custom_attr_visible (image, cattr))
1417 count -= not_visible;
1419 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1421 ainfo->image = image;
1422 ainfo->num_attrs = count;
1423 ainfo->cached = alloc_img != NULL;
1425 for (i = 0; i < count; ++i) {
1426 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427 if (custom_attr_visible (image, cattr)) {
1428 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430 ainfo->attrs [index].ctor = cattr->ctor->method;
1431 ainfo->attrs [index].data = saved;
1432 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1440 #ifndef DISABLE_REFLECTION_EMIT
1442 * LOCKING: Acquires the loader lock.
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1447 MONO_REQ_GC_UNSAFE_MODE;
1449 MonoCustomAttrInfo *ainfo, *tmp;
1451 if (!cattrs || !mono_array_length (cattrs))
1454 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1456 mono_loader_lock ();
1457 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1459 mono_custom_attrs_free (tmp);
1460 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461 mono_loader_unlock ();
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1469 MONO_REQ_GC_NEUTRAL_MODE;
1471 if (ainfo && !ainfo->cached)
1476 * idx is the table index of the object
1477 * type is one of MONO_CUSTOM_ATTR_*
1480 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1482 MONO_REQ_GC_UNSAFE_MODE;
1484 MonoDynamicTable *table;
1485 MonoReflectionCustomAttr *cattr;
1487 guint32 count, i, token;
1489 char *p = blob_size;
1491 mono_error_init (error);
1493 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1496 count = mono_array_length (cattrs);
1497 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1498 table->rows += count;
1499 alloc_table (table, table->rows);
1500 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1501 idx <<= MONO_CUSTOM_ATTR_BITS;
1503 for (i = 0; i < count; ++i) {
1504 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1505 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1506 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1507 if (!mono_error_ok (error)) goto fail;
1508 type = mono_metadata_token_index (token);
1509 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1510 switch (mono_metadata_token_table (token)) {
1511 case MONO_TABLE_METHOD:
1512 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1514 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1515 * method, not the one returned by mono_image_create_token ().
1517 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1519 case MONO_TABLE_MEMBERREF:
1520 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1523 g_warning ("got wrong token in custom attr");
1526 values [MONO_CUSTOM_ATTR_TYPE] = type;
1528 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1529 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1530 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1531 values += MONO_CUSTOM_ATTR_SIZE;
1542 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1544 MONO_REQ_GC_UNSAFE_MODE;
1546 MonoDynamicTable *table;
1548 guint32 count, i, idx;
1549 MonoReflectionPermissionSet *perm;
1554 count = mono_array_length (permissions);
1555 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1556 table->rows += count;
1557 alloc_table (table, table->rows);
1559 for (i = 0; i < mono_array_length (permissions); ++i) {
1560 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1562 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1564 idx = mono_metadata_token_index (parent_token);
1565 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1566 switch (mono_metadata_token_table (parent_token)) {
1567 case MONO_TABLE_TYPEDEF:
1568 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1570 case MONO_TABLE_METHOD:
1571 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1573 case MONO_TABLE_ASSEMBLY:
1574 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1577 g_assert_not_reached ();
1580 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1581 values [MONO_DECL_SECURITY_PARENT] = idx;
1582 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1589 * Fill in the MethodDef and ParamDef tables for a method.
1590 * This is used for both normal methods and constructors.
1593 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1595 MONO_REQ_GC_UNSAFE_MODE;
1597 MonoDynamicTable *table;
1601 mono_error_init (error);
1603 /* room in this table is already allocated */
1604 table = &assembly->tables [MONO_TABLE_METHOD];
1605 *mb->table_idx = table->next_idx ++;
1606 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1607 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1608 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609 values [MONO_METHOD_FLAGS] = mb->attrs;
1610 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1611 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1612 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1613 if (!mono_error_ok (error))
1616 table = &assembly->tables [MONO_TABLE_PARAM];
1617 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1619 mono_image_add_decl_security (assembly,
1620 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1623 MonoDynamicTable *mtable;
1626 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1627 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1630 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1631 if (mono_array_get (mb->pinfo, gpointer, i))
1634 table->rows += count;
1635 alloc_table (table, table->rows);
1636 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1637 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1638 MonoReflectionParamBuilder *pb;
1639 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1640 values [MONO_PARAM_FLAGS] = pb->attrs;
1641 values [MONO_PARAM_SEQUENCE] = i;
1642 if (pb->name != NULL) {
1643 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1645 values [MONO_PARAM_NAME] = 0;
1647 values += MONO_PARAM_SIZE;
1648 if (pb->marshal_info) {
1650 alloc_table (mtable, mtable->rows);
1651 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1652 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1653 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1655 pb->table_idx = table->next_idx++;
1656 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1657 guint32 field_type = 0;
1658 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1660 alloc_table (mtable, mtable->rows);
1661 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1662 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1663 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1664 mvalues [MONO_CONSTANT_TYPE] = field_type;
1665 mvalues [MONO_CONSTANT_PADDING] = 0;
1674 #ifndef DISABLE_REFLECTION_EMIT
1676 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1678 MONO_REQ_GC_UNSAFE_MODE;
1680 mono_error_init (error);
1681 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1683 rmb->ilgen = mb->ilgen;
1684 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1685 return_val_if_nok (error, FALSE);
1686 rmb->parameters = mb->parameters;
1687 rmb->generic_params = mb->generic_params;
1688 rmb->generic_container = mb->generic_container;
1689 rmb->opt_types = NULL;
1690 rmb->pinfo = mb->pinfo;
1691 rmb->attrs = mb->attrs;
1692 rmb->iattrs = mb->iattrs;
1693 rmb->call_conv = mb->call_conv;
1694 rmb->code = mb->code;
1695 rmb->type = mb->type;
1696 rmb->name = mb->name;
1697 rmb->table_idx = &mb->table_idx;
1698 rmb->init_locals = mb->init_locals;
1699 rmb->skip_visibility = FALSE;
1700 rmb->return_modreq = mb->return_modreq;
1701 rmb->return_modopt = mb->return_modopt;
1702 rmb->param_modreq = mb->param_modreq;
1703 rmb->param_modopt = mb->param_modopt;
1704 rmb->permissions = mb->permissions;
1705 rmb->mhandle = mb->mhandle;
1710 rmb->charset = mb->charset;
1711 rmb->extra_flags = mb->extra_flags;
1712 rmb->native_cc = mb->native_cc;
1713 rmb->dllentry = mb->dllentry;
1721 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1723 MONO_REQ_GC_UNSAFE_MODE;
1725 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1727 mono_error_init (error);
1729 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1731 rmb->ilgen = mb->ilgen;
1732 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1733 return_val_if_nok (error, FALSE);
1734 rmb->parameters = mb->parameters;
1735 rmb->generic_params = NULL;
1736 rmb->generic_container = NULL;
1737 rmb->opt_types = NULL;
1738 rmb->pinfo = mb->pinfo;
1739 rmb->attrs = mb->attrs;
1740 rmb->iattrs = mb->iattrs;
1741 rmb->call_conv = mb->call_conv;
1743 rmb->type = mb->type;
1744 rmb->name = mono_string_new (mono_domain_get (), name);
1745 rmb->table_idx = &mb->table_idx;
1746 rmb->init_locals = mb->init_locals;
1747 rmb->skip_visibility = FALSE;
1748 rmb->return_modreq = NULL;
1749 rmb->return_modopt = NULL;
1750 rmb->param_modreq = mb->param_modreq;
1751 rmb->param_modopt = mb->param_modopt;
1752 rmb->permissions = mb->permissions;
1753 rmb->mhandle = mb->mhandle;
1761 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1763 MONO_REQ_GC_UNSAFE_MODE;
1765 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1767 rmb->ilgen = mb->ilgen;
1768 rmb->rtype = mb->rtype;
1769 rmb->parameters = mb->parameters;
1770 rmb->generic_params = NULL;
1771 rmb->generic_container = NULL;
1772 rmb->opt_types = NULL;
1774 rmb->attrs = mb->attrs;
1776 rmb->call_conv = mb->call_conv;
1778 rmb->type = (MonoObject *) mb->owner;
1779 rmb->name = mb->name;
1780 rmb->table_idx = NULL;
1781 rmb->init_locals = mb->init_locals;
1782 rmb->skip_visibility = mb->skip_visibility;
1783 rmb->return_modreq = NULL;
1784 rmb->return_modopt = NULL;
1785 rmb->param_modreq = NULL;
1786 rmb->param_modopt = NULL;
1787 rmb->permissions = NULL;
1788 rmb->mhandle = mb->mhandle;
1795 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1797 MONO_REQ_GC_UNSAFE_MODE;
1799 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1800 MonoDynamicTable *table;
1803 MonoReflectionMethod *m;
1806 mono_error_init (error);
1808 if (!mb->override_methods)
1811 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1812 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1814 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1816 alloc_table (table, table->rows);
1817 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1818 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1819 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1821 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1822 return_val_if_nok (error, FALSE);
1824 switch (mono_metadata_token_table (tok)) {
1825 case MONO_TABLE_MEMBERREF:
1826 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1828 case MONO_TABLE_METHOD:
1829 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1832 g_assert_not_reached ();
1834 values [MONO_METHODIMPL_DECLARATION] = tok;
1840 #ifndef DISABLE_REFLECTION_EMIT
1842 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1844 MONO_REQ_GC_UNSAFE_MODE;
1846 MonoDynamicTable *table;
1848 ReflectionMethodBuilder rmb;
1851 mono_error_init (error);
1853 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1854 !mono_image_basic_method (&rmb, assembly, error))
1857 mb->table_idx = *rmb.table_idx;
1859 if (mb->dll) { /* It's a P/Invoke method */
1861 /* map CharSet values to on-disk values */
1862 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1863 int extra_flags = mb->extra_flags;
1864 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1866 alloc_table (table, table->rows);
1867 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1869 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1870 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1872 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1874 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1875 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1876 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1877 table = &assembly->tables [MONO_TABLE_MODULEREF];
1879 alloc_table (table, table->rows);
1880 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1881 values [MONO_IMPLMAP_SCOPE] = table->rows;
1885 if (mb->generic_params) {
1886 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1887 table->rows += mono_array_length (mb->generic_params);
1888 alloc_table (table, table->rows);
1889 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1890 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1892 mono_image_get_generic_param_info (
1893 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1901 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1903 MONO_REQ_GC_UNSAFE_MODE;
1905 ReflectionMethodBuilder rmb;
1907 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1910 if (!mono_image_basic_method (&rmb, assembly, error))
1913 mb->table_idx = *rmb.table_idx;
1920 type_get_fully_qualified_name (MonoType *type)
1922 MONO_REQ_GC_NEUTRAL_MODE;
1924 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1928 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1930 MONO_REQ_GC_UNSAFE_MODE;
1935 klass = mono_class_from_mono_type (type);
1937 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1938 ta = klass->image->assembly;
1939 if (assembly_is_dynamic (ta) || (ta == ass)) {
1940 if (klass->generic_class || klass->generic_container)
1941 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1942 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1944 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1947 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1950 #ifndef DISABLE_REFLECTION_EMIT
1951 /*field_image is the image to which the eventual custom mods have been encoded against*/
1953 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1955 MONO_REQ_GC_NEUTRAL_MODE;
1958 guint32 idx, i, token;
1960 if (!assembly->save)
1963 sigbuffer_init (&buf, 32);
1965 sigbuffer_add_value (&buf, 0x06);
1966 /* encode custom attributes before the type */
1967 if (type->num_mods) {
1968 for (i = 0; i < type->num_mods; ++i) {
1971 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1972 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1974 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1976 token = type->modifiers [i].token;
1979 if (type->modifiers [i].required)
1980 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1982 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1984 sigbuffer_add_value (&buf, token);
1987 encode_type (assembly, type, &buf);
1988 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1989 sigbuffer_free (&buf);
1995 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1997 MONO_REQ_GC_UNSAFE_MODE;
2001 guint32 typespec = 0;
2005 init_type_builder_generics (fb->type);
2007 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
2008 klass = mono_class_from_mono_type (type);
2010 sigbuffer_init (&buf, 32);
2012 sigbuffer_add_value (&buf, 0x06);
2013 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2014 /* encode custom attributes before the type */
2016 if (klass->generic_container)
2017 typespec = create_typespec (assembly, type);
2020 MonoGenericClass *gclass;
2021 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2022 encode_generic_class (assembly, gclass, &buf);
2024 encode_type (assembly, type, &buf);
2026 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2027 sigbuffer_free (&buf);
2032 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2034 MONO_REQ_GC_UNSAFE_MODE;
2036 char blob_size [64];
2037 char *b = blob_size;
2040 guint32 idx = 0, len = 0, dummy = 0;
2042 buf = (char *)g_malloc (64);
2044 *ret_type = MONO_TYPE_CLASS;
2046 box_val = (char*)&dummy;
2048 box_val = ((char*)val) + sizeof (MonoObject);
2049 *ret_type = val->vtable->klass->byval_arg.type;
2052 switch (*ret_type) {
2053 case MONO_TYPE_BOOLEAN:
2058 case MONO_TYPE_CHAR:
2075 case MONO_TYPE_VALUETYPE: {
2076 MonoClass *klass = val->vtable->klass;
2078 if (klass->enumtype) {
2079 *ret_type = mono_class_enum_basetype (klass)->type;
2081 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2084 g_error ("we can't encode valuetypes, we should have never reached this line");
2087 case MONO_TYPE_CLASS:
2089 case MONO_TYPE_STRING: {
2090 MonoString *str = (MonoString*)val;
2091 /* there is no signature */
2092 len = str->length * 2;
2093 mono_metadata_encode_value (len, b, &b);
2094 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2096 char *swapped = g_malloc (2 * mono_string_length (str));
2097 const char *p = (const char*)mono_string_chars (str);
2099 swap_with_size (swapped, p, 2, mono_string_length (str));
2100 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2104 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2110 case MONO_TYPE_GENERICINST:
2111 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2114 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2117 /* there is no signature */
2118 mono_metadata_encode_value (len, b, &b);
2119 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2120 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2121 swap_with_size (blob_size, box_val, len, 1);
2122 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2124 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2132 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2134 MONO_REQ_GC_UNSAFE_MODE;
2140 sigbuffer_init (&buf, 32);
2142 sigbuffer_add_value (&buf, minfo->type);
2144 switch (minfo->type) {
2145 case MONO_NATIVE_BYVALTSTR:
2146 case MONO_NATIVE_BYVALARRAY:
2147 sigbuffer_add_value (&buf, minfo->count);
2149 case MONO_NATIVE_LPARRAY:
2150 if (minfo->eltype || minfo->has_size) {
2151 sigbuffer_add_value (&buf, minfo->eltype);
2152 if (minfo->has_size) {
2153 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2154 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2156 /* LAMESPEC: ElemMult is undocumented */
2157 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2161 case MONO_NATIVE_SAFEARRAY:
2163 sigbuffer_add_value (&buf, minfo->eltype);
2165 case MONO_NATIVE_CUSTOM:
2167 str = mono_string_to_utf8 (minfo->guid);
2169 sigbuffer_add_value (&buf, len);
2170 sigbuffer_add_mem (&buf, str, len);
2173 sigbuffer_add_value (&buf, 0);
2175 /* native type name */
2176 sigbuffer_add_value (&buf, 0);
2177 /* custom marshaler type name */
2178 if (minfo->marshaltype || minfo->marshaltyperef) {
2179 if (minfo->marshaltyperef)
2180 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2182 str = mono_string_to_utf8 (minfo->marshaltype);
2184 sigbuffer_add_value (&buf, len);
2185 sigbuffer_add_mem (&buf, str, len);
2188 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2189 sigbuffer_add_value (&buf, 0);
2191 if (minfo->mcookie) {
2192 str = mono_string_to_utf8 (minfo->mcookie);
2194 sigbuffer_add_value (&buf, len);
2195 sigbuffer_add_mem (&buf, str, len);
2198 sigbuffer_add_value (&buf, 0);
2204 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 sigbuffer_free (&buf);
2210 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2212 MONO_REQ_GC_UNSAFE_MODE;
2214 MonoDynamicTable *table;
2217 /* maybe this fixup should be done in the C# code */
2218 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2219 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2220 table = &assembly->tables [MONO_TABLE_FIELD];
2221 fb->table_idx = table->next_idx ++;
2222 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2223 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2224 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2225 values [MONO_FIELD_FLAGS] = fb->attrs;
2226 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2228 if (fb->offset != -1) {
2229 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2231 alloc_table (table, table->rows);
2232 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2233 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2234 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2236 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2237 MonoTypeEnum field_type = (MonoTypeEnum)0;
2238 table = &assembly->tables [MONO_TABLE_CONSTANT];
2240 alloc_table (table, table->rows);
2241 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2242 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2243 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2244 values [MONO_CONSTANT_TYPE] = field_type;
2245 values [MONO_CONSTANT_PADDING] = 0;
2247 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2249 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2251 alloc_table (table, table->rows);
2252 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2253 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2255 * We store it in the code section because it's simpler for now.
2258 if (mono_array_length (fb->rva_data) >= 10)
2259 stream_data_align (&assembly->code);
2260 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2262 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2263 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2265 if (fb->marshal_info) {
2266 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2268 alloc_table (table, table->rows);
2269 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2270 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2271 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2276 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2278 MONO_REQ_GC_UNSAFE_MODE;
2281 guint32 nparams = 0;
2282 MonoReflectionMethodBuilder *mb = fb->get_method;
2283 MonoReflectionMethodBuilder *smb = fb->set_method;
2286 if (mb && mb->parameters)
2287 nparams = mono_array_length (mb->parameters);
2288 if (!mb && smb && smb->parameters)
2289 nparams = mono_array_length (smb->parameters) - 1;
2290 sigbuffer_init (&buf, 32);
2291 if (fb->call_conv & 0x20)
2292 sigbuffer_add_byte (&buf, 0x28);
2294 sigbuffer_add_byte (&buf, 0x08);
2295 sigbuffer_add_value (&buf, nparams);
2297 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2298 for (i = 0; i < nparams; ++i) {
2299 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2300 encode_reflection_type (assembly, pt, &buf);
2302 } else if (smb && smb->parameters) {
2303 /* the property type is the last param */
2304 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2305 for (i = 0; i < nparams; ++i) {
2306 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2307 encode_reflection_type (assembly, pt, &buf);
2310 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2313 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2314 sigbuffer_free (&buf);
2319 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2321 MONO_REQ_GC_UNSAFE_MODE;
2323 MonoDynamicTable *table;
2325 guint num_methods = 0;
2329 * we need to set things in the following tables:
2330 * PROPERTYMAP (info already filled in _get_type_info ())
2331 * PROPERTY (rows already preallocated in _get_type_info ())
2332 * METHOD (method info already done with the generic method code)
2336 table = &assembly->tables [MONO_TABLE_PROPERTY];
2337 pb->table_idx = table->next_idx ++;
2338 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2339 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2340 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2341 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2343 /* FIXME: we still don't handle 'other' methods */
2344 if (pb->get_method) num_methods ++;
2345 if (pb->set_method) num_methods ++;
2347 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2348 table->rows += num_methods;
2349 alloc_table (table, table->rows);
2351 if (pb->get_method) {
2352 semaidx = table->next_idx ++;
2353 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2354 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2355 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2356 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2358 if (pb->set_method) {
2359 semaidx = table->next_idx ++;
2360 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2361 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2362 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2363 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2365 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2366 MonoTypeEnum field_type = (MonoTypeEnum)0;
2367 table = &assembly->tables [MONO_TABLE_CONSTANT];
2369 alloc_table (table, table->rows);
2370 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2371 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2372 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2373 values [MONO_CONSTANT_TYPE] = field_type;
2374 values [MONO_CONSTANT_PADDING] = 0;
2379 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2381 MONO_REQ_GC_UNSAFE_MODE;
2383 MonoDynamicTable *table;
2385 guint num_methods = 0;
2389 * we need to set things in the following tables:
2390 * EVENTMAP (info already filled in _get_type_info ())
2391 * EVENT (rows already preallocated in _get_type_info ())
2392 * METHOD (method info already done with the generic method code)
2395 table = &assembly->tables [MONO_TABLE_EVENT];
2396 eb->table_idx = table->next_idx ++;
2397 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2398 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2399 values [MONO_EVENT_FLAGS] = eb->attrs;
2400 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2403 * FIXME: we still don't handle 'other' methods
2405 if (eb->add_method) num_methods ++;
2406 if (eb->remove_method) num_methods ++;
2407 if (eb->raise_method) num_methods ++;
2409 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410 table->rows += num_methods;
2411 alloc_table (table, table->rows);
2413 if (eb->add_method) {
2414 semaidx = table->next_idx ++;
2415 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2417 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2418 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2420 if (eb->remove_method) {
2421 semaidx = table->next_idx ++;
2422 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2424 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2425 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2427 if (eb->raise_method) {
2428 semaidx = table->next_idx ++;
2429 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2430 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2431 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2432 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2437 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2439 MONO_REQ_GC_UNSAFE_MODE;
2441 MonoDynamicTable *table;
2442 guint32 num_constraints, i;
2446 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2447 num_constraints = gparam->iface_constraints ?
2448 mono_array_length (gparam->iface_constraints) : 0;
2449 table->rows += num_constraints;
2450 if (gparam->base_type)
2452 alloc_table (table, table->rows);
2454 if (gparam->base_type) {
2455 table_idx = table->next_idx ++;
2456 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2458 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2459 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2460 assembly, mono_reflection_type_get_handle (gparam->base_type));
2463 for (i = 0; i < num_constraints; i++) {
2464 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2465 gparam->iface_constraints, gpointer, i);
2467 table_idx = table->next_idx ++;
2468 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2470 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2471 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2472 assembly, mono_reflection_type_get_handle (constraint));
2477 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2479 MONO_REQ_GC_UNSAFE_MODE;
2481 GenericParamTableEntry *entry;
2484 * The GenericParam table must be sorted according to the `owner' field.
2485 * We need to do this sorting prior to writing the GenericParamConstraint
2486 * table, since we have to use the final GenericParam table indices there
2487 * and they must also be sorted.
2490 entry = g_new0 (GenericParamTableEntry, 1);
2491 entry->owner = owner;
2492 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2493 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2494 entry->gparam = gparam;
2496 g_ptr_array_add (assembly->gen_params, entry);
2500 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2502 MONO_REQ_GC_UNSAFE_MODE;
2504 MonoDynamicTable *table;
2505 MonoGenericParam *param;
2509 mono_error_init (error);
2511 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2512 table_idx = table->next_idx ++;
2513 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2515 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2517 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2518 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2519 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2520 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2522 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2525 encode_constraints (entry->gparam, table_idx, assembly);
2531 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2533 MONO_REQ_GC_UNSAFE_MODE;
2535 MonoDynamicTable *table;
2538 guint32 cols [MONO_ASSEMBLY_SIZE];
2542 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2545 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2546 table = &assembly->tables [MONO_TABLE_MODULEREF];
2547 token = table->next_idx ++;
2549 alloc_table (table, table->rows);
2550 values = table->values + token * MONO_MODULEREF_SIZE;
2551 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2553 token <<= MONO_RESOLUTION_SCOPE_BITS;
2554 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2555 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2560 if (assembly_is_dynamic (image->assembly))
2562 memset (cols, 0, sizeof (cols));
2564 /* image->assembly->image is the manifest module */
2565 image = image->assembly->image;
2566 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2569 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2570 token = table->next_idx ++;
2572 alloc_table (table, table->rows);
2573 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2574 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2575 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2576 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2577 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2578 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2579 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2580 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2581 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2583 if (strcmp ("", image->assembly->aname.culture)) {
2584 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2585 image->assembly->aname.culture);
2588 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2589 guchar pubtoken [9];
2591 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2592 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2594 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2596 token <<= MONO_RESOLUTION_SCOPE_BITS;
2597 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2598 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2603 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2605 MONO_REQ_GC_NEUTRAL_MODE;
2607 MonoDynamicTable *table;
2612 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2615 sigbuffer_init (&buf, 32);
2616 switch (type->type) {
2617 case MONO_TYPE_FNPTR:
2619 case MONO_TYPE_SZARRAY:
2620 case MONO_TYPE_ARRAY:
2622 case MONO_TYPE_MVAR:
2623 case MONO_TYPE_GENERICINST:
2624 encode_type (assembly, type, &buf);
2626 case MONO_TYPE_CLASS:
2627 case MONO_TYPE_VALUETYPE: {
2628 MonoClass *k = mono_class_from_mono_type (type);
2629 if (!k || !k->generic_container) {
2630 sigbuffer_free (&buf);
2633 encode_type (assembly, type, &buf);
2637 sigbuffer_free (&buf);
2641 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2642 if (assembly->save) {
2643 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2644 alloc_table (table, table->rows + 1);
2645 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2646 values [MONO_TYPESPEC_SIGNATURE] = token;
2648 sigbuffer_free (&buf);
2650 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2651 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2657 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2659 MONO_REQ_GC_UNSAFE_MODE;
2661 MonoDynamicTable *table;
2663 guint32 token, scope, enclosing;
2666 /* if the type requires a typespec, we must try that first*/
2667 if (try_typespec && (token = create_typespec (assembly, type)))
2669 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2672 klass = mono_class_from_mono_type (type);
2674 klass = mono_class_from_mono_type (type);
2677 * If it's in the same module and not a generic type parameter:
2679 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2680 (type->type != MONO_TYPE_MVAR)) {
2681 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2682 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2683 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2687 if (klass->nested_in) {
2688 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2689 /* get the typeref idx of the enclosing type */
2690 enclosing >>= MONO_TYPEDEFORREF_BITS;
2691 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2693 scope = resolution_scope_from_image (assembly, klass->image);
2695 table = &assembly->tables [MONO_TABLE_TYPEREF];
2696 if (assembly->save) {
2697 alloc_table (table, table->rows + 1);
2698 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2699 values [MONO_TYPEREF_SCOPE] = scope;
2700 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2701 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2703 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2704 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2706 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2711 * Despite the name, we handle also TypeSpec (with the above helper).
2714 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2716 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2719 #ifndef DISABLE_REFLECTION_EMIT
2721 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2723 MONO_REQ_GC_NEUTRAL_MODE;
2725 MonoDynamicTable *table;
2727 guint32 token, pclass;
2729 switch (parent & MONO_TYPEDEFORREF_MASK) {
2730 case MONO_TYPEDEFORREF_TYPEREF:
2731 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2733 case MONO_TYPEDEFORREF_TYPESPEC:
2734 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2736 case MONO_TYPEDEFORREF_TYPEDEF:
2737 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2740 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2743 /* extract the index */
2744 parent >>= MONO_TYPEDEFORREF_BITS;
2746 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2748 if (assembly->save) {
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2751 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2752 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2753 values [MONO_MEMBERREF_SIGNATURE] = sig;
2756 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2763 * Insert a memberef row into the metadata: the token that point to the memberref
2764 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2765 * mono_image_get_fieldref_token()).
2766 * The sig param is an index to an already built signature.
2769 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2771 MONO_REQ_GC_NEUTRAL_MODE;
2773 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2774 return mono_image_add_memberef_row (assembly, parent, name, sig);
2779 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2781 MONO_REQ_GC_NEUTRAL_MODE;
2784 MonoMethodSignature *sig;
2786 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2788 if (create_typespec) {
2789 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2794 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795 if (token && !create_typespec)
2798 g_assert (!method->is_inflated);
2801 * A methodref signature can't contain an unmanaged calling convention.
2803 sig = mono_metadata_signature_dup (mono_method_signature (method));
2804 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2805 sig->call_convention = MONO_CALL_DEFAULT;
2806 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2807 method->name, method_encode_signature (assembly, sig));
2809 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2812 if (create_typespec) {
2813 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2814 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2815 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2817 if (assembly->save) {
2820 alloc_table (table, table->rows + 1);
2821 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2822 values [MONO_METHODSPEC_METHOD] = token;
2823 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2826 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2828 /*methodspec and memberef tokens are diferent, */
2829 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2836 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2838 guint32 token, parent, sig;
2839 ReflectionMethodBuilder rmb;
2840 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2842 mono_error_init (error);
2843 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2847 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2851 * A methodref signature can't contain an unmanaged calling convention.
2852 * Since some flags are encoded as part of call_conv, we need to check against it.
2854 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2855 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2857 sig = method_builder_encode_signature (assembly, &rmb);
2859 if (tb->generic_params)
2860 parent = create_generic_typespec (assembly, tb);
2862 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2864 char *name = mono_string_to_utf8 (method->name);
2866 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2869 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2875 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2876 const gchar *name, guint32 sig)
2878 MonoDynamicTable *table;
2882 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2884 if (assembly->save) {
2885 alloc_table (table, table->rows + 1);
2886 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2887 values [MONO_MEMBERREF_CLASS] = original;
2888 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2889 values [MONO_MEMBERREF_SIGNATURE] = sig;
2892 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2899 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2903 guint32 nparams = mono_array_length (mb->generic_params);
2906 if (!assembly->save)
2909 sigbuffer_init (&buf, 32);
2911 sigbuffer_add_value (&buf, 0xa);
2912 sigbuffer_add_value (&buf, nparams);
2914 for (i = 0; i < nparams; i++) {
2915 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2916 sigbuffer_add_value (&buf, i);
2919 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2920 sigbuffer_free (&buf);
2925 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2927 MonoDynamicTable *table;
2929 guint32 token, mtoken = 0;
2931 mono_error_init (error);
2932 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2936 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2938 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2939 if (!mono_error_ok (error))
2942 switch (mono_metadata_token_table (mtoken)) {
2943 case MONO_TABLE_MEMBERREF:
2944 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2946 case MONO_TABLE_METHOD:
2947 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2950 g_assert_not_reached ();
2953 if (assembly->save) {
2954 alloc_table (table, table->rows + 1);
2955 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2956 values [MONO_METHODSPEC_METHOD] = mtoken;
2957 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2960 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2963 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2968 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2972 mono_error_init (error);
2974 if (mb->generic_params && create_methodspec)
2975 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2977 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2981 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2982 if (!mono_error_ok (error))
2984 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2989 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2991 guint32 token, parent, sig;
2992 ReflectionMethodBuilder rmb;
2994 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2996 mono_error_init (error);
2998 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3002 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3005 if (tb->generic_params)
3006 parent = create_generic_typespec (assembly, tb);
3008 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3010 name = mono_string_to_utf8 (rmb.name);
3011 sig = method_builder_encode_signature (assembly, &rmb);
3013 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3016 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3022 is_field_on_inst (MonoClassField *field)
3024 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3028 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3031 get_field_on_inst_generic_type (MonoClassField *field)
3033 MonoClass *klass, *gtd;
3034 MonoDynamicGenericClass *dgclass;
3037 g_assert (is_field_on_inst (field));
3039 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3041 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3042 field_index = field - dgclass->fields;
3043 return dgclass->field_generic_types [field_index];
3046 klass = field->parent;
3047 gtd = klass->generic_class->container_class;
3049 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3050 field_index = field - klass->fields;
3051 return gtd->fields [field_index].type;
3054 g_assert_not_reached ();
3058 #ifndef DISABLE_REFLECTION_EMIT
3060 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3066 g_assert (field->parent);
3068 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3072 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3073 int index = field - field->parent->fields;
3074 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3076 if (is_field_on_inst (field))
3077 type = get_field_on_inst_generic_type (field);
3079 type = mono_field_get_type (field);
3081 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3082 mono_field_get_name (field),
3083 fieldref_encode_signature (assembly, field->parent->image, type));
3084 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3089 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3093 MonoGenericClass *gclass;
3097 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3100 if (is_sre_field_builder (mono_object_class (f->fb))) {
3101 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3102 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3103 klass = mono_class_from_mono_type (type);
3104 gclass = type->data.generic_class;
3105 g_assert (gclass->is_dynamic);
3107 name = mono_string_to_utf8 (fb->name);
3108 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3109 field_encode_signature (assembly, fb));
3111 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3113 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3115 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3116 klass = mono_class_from_mono_type (type);
3118 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3119 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3121 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3122 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3125 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3130 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3134 MonoGenericClass *gclass;
3137 mono_error_init (error);
3139 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3141 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3145 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3146 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3147 ReflectionMethodBuilder rmb;
3150 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3151 klass = mono_class_from_mono_type (type);
3153 gclass = type->data.generic_class;
3154 g_assert (gclass->is_dynamic);
3156 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3159 name = mono_string_to_utf8 (rmb.name);
3161 sig = method_builder_encode_signature (assembly, &rmb);
3163 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3165 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3166 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3168 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3169 klass = mono_class_from_mono_type (type);
3171 sig = method_encode_signature (assembly, mono_method_signature (mm));
3172 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3174 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3175 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3179 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3184 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3187 MonoGenericContext tmp_context;
3188 MonoType **type_argv;
3189 MonoGenericInst *ginst;
3190 MonoMethod *method, *inflated;
3193 mono_error_init (error);
3195 init_type_builder_generics ((MonoObject*)m->inst);
3197 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3198 return_val_if_nok (error, NULL);
3200 klass = method->klass;
3202 if (m->method_args == NULL)
3205 if (method->is_inflated)
3206 method = ((MonoMethodInflated *) method)->declaring;
3208 count = mono_array_length (m->method_args);
3210 type_argv = g_new0 (MonoType *, count);
3211 for (i = 0; i < count; i++) {
3212 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3213 type_argv [i] = mono_reflection_type_get_handle (garg);
3215 ginst = mono_metadata_get_generic_inst (count, type_argv);
3218 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3219 tmp_context.method_inst = ginst;
3221 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3222 mono_error_assert_ok (error);
3227 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3229 guint32 sig, token = 0;
3233 mono_error_init (error);
3235 if (m->method_args) {
3236 MonoMethod *inflated;
3238 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3239 return_val_if_nok (error, 0);
3241 if (create_methodspec)
3242 token = mono_image_get_methodspec_token (assembly, inflated);
3244 token = mono_image_get_inflated_method_token (assembly, inflated);
3248 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3252 if (is_sre_method_builder (mono_object_class (m->mb))) {
3253 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3254 MonoGenericClass *gclass;
3255 ReflectionMethodBuilder rmb;
3258 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3259 klass = mono_class_from_mono_type (type);
3260 gclass = type->data.generic_class;
3261 g_assert (gclass->is_dynamic);
3263 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3266 name = mono_string_to_utf8 (rmb.name);
3268 sig = method_builder_encode_signature (assembly, &rmb);
3270 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3272 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3273 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3275 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3276 klass = mono_class_from_mono_type (type);
3278 sig = method_encode_signature (assembly, mono_method_signature (mm));
3279 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3281 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3282 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3285 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3290 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3294 guint32 nparams = context->method_inst->type_argc;
3297 if (!assembly->save)
3300 sigbuffer_init (&buf, 32);
3302 * FIXME: vararg, explicit_this, differenc call_conv values...
3304 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3305 sigbuffer_add_value (&buf, nparams);
3307 for (i = 0; i < nparams; i++)
3308 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3310 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3311 sigbuffer_free (&buf);
3316 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3318 MonoDynamicTable *table;
3320 guint32 token, mtoken = 0, sig;
3321 MonoMethodInflated *imethod;
3322 MonoMethod *declaring;
3324 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3326 g_assert (method->is_inflated);
3327 imethod = (MonoMethodInflated *) method;
3328 declaring = imethod->declaring;
3330 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3331 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3333 if (!mono_method_signature (declaring)->generic_param_count)
3336 switch (mono_metadata_token_table (mtoken)) {
3337 case MONO_TABLE_MEMBERREF:
3338 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3340 case MONO_TABLE_METHOD:
3341 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3344 g_assert_not_reached ();
3347 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3349 if (assembly->save) {
3350 alloc_table (table, table->rows + 1);
3351 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3352 values [MONO_METHODSPEC_METHOD] = mtoken;
3353 values [MONO_METHODSPEC_SIGNATURE] = sig;
3356 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3363 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3365 MonoMethodInflated *imethod;
3368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3372 g_assert (method->is_inflated);
3373 imethod = (MonoMethodInflated *) method;
3375 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3376 token = method_encode_methodspec (assembly, method);
3378 guint32 sig = method_encode_signature (
3379 assembly, mono_method_signature (imethod->declaring));
3380 token = mono_image_get_memberref_token (
3381 assembly, &method->klass->byval_arg, method->name, sig);
3384 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3389 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3391 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3394 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3395 token = mono_image_get_memberref_token (
3396 assembly, &m->klass->byval_arg, m->name, sig);
3402 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3404 MonoDynamicTable *table;
3413 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3414 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3415 * Because of this, we must not insert it into the `typeref' hash table.
3417 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3418 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3422 sigbuffer_init (&buf, 32);
3424 g_assert (tb->generic_params);
3425 klass = mono_class_from_mono_type (type);
3427 if (tb->generic_container)
3428 mono_reflection_create_generic_class (tb);
3430 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3431 g_assert (klass->generic_container);
3432 sigbuffer_add_value (&buf, klass->byval_arg.type);
3433 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3435 count = mono_array_length (tb->generic_params);
3436 sigbuffer_add_value (&buf, count);
3437 for (i = 0; i < count; i++) {
3438 MonoReflectionGenericParam *gparam;
3440 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3442 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3445 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3447 if (assembly->save) {
3448 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3449 alloc_table (table, table->rows + 1);
3450 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3451 values [MONO_TYPESPEC_SIGNATURE] = token;
3453 sigbuffer_free (&buf);
3455 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3456 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3462 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3465 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3467 int i, count, len, pos;
3472 count += mono_array_length (modreq);
3474 count += mono_array_length (modopt);
3477 return mono_metadata_type_dup (NULL, type);
3479 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3480 t = (MonoType *)g_malloc (len);
3481 memcpy (t, type, MONO_SIZEOF_TYPE);
3483 t->num_mods = count;
3486 for (i = 0; i < mono_array_length (modreq); ++i) {
3487 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3488 t->modifiers [pos].required = 1;
3489 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3494 for (i = 0; i < mono_array_length (modopt); ++i) {
3495 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3496 t->modifiers [pos].required = 0;
3497 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3506 init_type_builder_generics (MonoObject *type)
3508 MonoReflectionTypeBuilder *tb;
3510 if (!is_sre_type_builder(mono_object_class (type)))
3512 tb = (MonoReflectionTypeBuilder *)type;
3514 if (tb && tb->generic_container)
3515 mono_reflection_create_generic_class (tb);
3519 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3521 MonoDynamicTable *table;
3522 MonoType *custom = NULL, *type;
3524 guint32 token, pclass, parent, sig;
3527 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3531 /* FIXME: is this call necessary? */
3532 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3533 name = mono_string_to_utf8 (fb->name);
3535 /*FIXME this is one more layer of ugliness due how types are created.*/
3536 init_type_builder_generics (fb->type);
3538 /* fb->type does not include the custom modifiers */
3539 /* FIXME: We should do this in one place when a fieldbuilder is created */
3540 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3541 if (fb->modreq || fb->modopt)
3542 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3544 sig = fieldref_encode_signature (assembly, NULL, type);
3547 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3548 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3550 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3551 parent >>= MONO_TYPEDEFORREF_BITS;
3553 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3555 if (assembly->save) {
3556 alloc_table (table, table->rows + 1);
3557 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3558 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3559 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3560 values [MONO_MEMBERREF_SIGNATURE] = sig;
3563 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3565 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3571 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3577 if (!assembly->save)
3580 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3581 g_assert (helper->type == 2);
3583 if (helper->arguments)
3584 nargs = mono_array_length (helper->arguments);
3588 sigbuffer_init (&buf, 32);
3590 /* Encode calling convention */
3591 /* Change Any to Standard */
3592 if ((helper->call_conv & 0x03) == 0x03)
3593 helper->call_conv = 0x01;
3594 /* explicit_this implies has_this */
3595 if (helper->call_conv & 0x40)
3596 helper->call_conv &= 0x20;
3598 if (helper->call_conv == 0) { /* Unmanaged */
3599 idx = helper->unmanaged_call_conv - 1;
3602 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3603 if (helper->call_conv & 0x02) /* varargs */
3607 sigbuffer_add_byte (&buf, idx);
3608 sigbuffer_add_value (&buf, nargs);
3609 encode_reflection_type (assembly, helper->return_type, &buf);
3610 for (i = 0; i < nargs; ++i) {
3611 MonoArray *modreqs = NULL;
3612 MonoArray *modopts = NULL;
3613 MonoReflectionType *pt;
3615 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3616 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3617 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3618 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3620 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3621 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3622 encode_reflection_type (assembly, pt, &buf);
3624 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3625 sigbuffer_free (&buf);
3631 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3634 MonoDynamicTable *table;
3637 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3638 idx = table->next_idx ++;
3640 alloc_table (table, table->rows);
3641 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3643 values [MONO_STAND_ALONE_SIGNATURE] =
3644 mono_reflection_encode_sighelper (assembly, helper);
3650 reflection_cc_to_file (int call_conv) {
3651 switch (call_conv & 0x3) {
3653 case 1: return MONO_CALL_DEFAULT;
3654 case 2: return MONO_CALL_VARARG;
3656 g_assert_not_reached ();
3660 #endif /* !DISABLE_REFLECTION_EMIT */
3664 MonoMethodSignature *sig;
3669 #ifndef DISABLE_REFLECTION_EMIT
3671 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3676 MonoMethodSignature *sig;
3680 name = mono_string_to_utf8 (m->name);
3681 nparams = mono_array_length (m->parameters);
3682 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3684 sig->sentinelpos = -1;
3685 sig->call_convention = reflection_cc_to_file (m->call_conv);
3686 sig->param_count = nparams;
3687 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3688 mtype = mono_reflection_type_get_handle (m->parent);
3689 for (i = 0; i < nparams; ++i)
3690 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3692 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3693 am = (ArrayMethod *)tmp->data;
3694 if (strcmp (name, am->name) == 0 &&
3695 mono_metadata_type_equal (am->parent, mtype) &&
3696 mono_metadata_signature_equal (am->sig, sig)) {
3699 m->table_idx = am->token & 0xffffff;
3703 am = g_new0 (ArrayMethod, 1);
3707 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3708 method_encode_signature (assembly, sig));
3709 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3710 m->table_idx = am->token & 0xffffff;
3715 * Insert into the metadata tables all the info about the TypeBuilder tb.
3716 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3719 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3721 MonoDynamicTable *table;
3723 int i, is_object = 0, is_system = 0;
3726 mono_error_init (error);
3728 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3729 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3730 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3731 n = mono_string_to_utf8 (tb->name);
3732 if (strcmp (n, "Object") == 0)
3734 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3736 n = mono_string_to_utf8 (tb->nspace);
3737 if (strcmp (n, "System") == 0)
3739 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3741 if (tb->parent && !(is_system && is_object) &&
3742 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3743 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3745 values [MONO_TYPEDEF_EXTENDS] = 0;
3747 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3748 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3751 * if we have explicitlayout or sequentiallayouts, output data in the
3752 * ClassLayout table.
3754 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3755 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3756 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3758 alloc_table (table, table->rows);
3759 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3760 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3761 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3762 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3765 /* handle interfaces */
3766 if (tb->interfaces) {
3767 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3769 table->rows += mono_array_length (tb->interfaces);
3770 alloc_table (table, table->rows);
3771 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3772 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3773 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3774 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3775 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3776 values += MONO_INTERFACEIMPL_SIZE;
3782 table = &assembly->tables [MONO_TABLE_FIELD];
3783 table->rows += tb->num_fields;
3784 alloc_table (table, table->rows);
3785 for (i = 0; i < tb->num_fields; ++i)
3786 mono_image_get_field_info (
3787 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3790 /* handle constructors */
3792 table = &assembly->tables [MONO_TABLE_METHOD];
3793 table->rows += mono_array_length (tb->ctors);
3794 alloc_table (table, table->rows);
3795 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3796 if (!mono_image_get_ctor_info (domain,
3797 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3803 /* handle methods */
3805 table = &assembly->tables [MONO_TABLE_METHOD];
3806 table->rows += tb->num_methods;
3807 alloc_table (table, table->rows);
3808 for (i = 0; i < tb->num_methods; ++i) {
3809 if (!mono_image_get_method_info (
3810 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3815 /* Do the same with properties etc.. */
3816 if (tb->events && mono_array_length (tb->events)) {
3817 table = &assembly->tables [MONO_TABLE_EVENT];
3818 table->rows += mono_array_length (tb->events);
3819 alloc_table (table, table->rows);
3820 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3822 alloc_table (table, table->rows);
3823 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3824 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3825 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3826 for (i = 0; i < mono_array_length (tb->events); ++i)
3827 mono_image_get_event_info (
3828 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3830 if (tb->properties && mono_array_length (tb->properties)) {
3831 table = &assembly->tables [MONO_TABLE_PROPERTY];
3832 table->rows += mono_array_length (tb->properties);
3833 alloc_table (table, table->rows);
3834 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3836 alloc_table (table, table->rows);
3837 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3838 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3839 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3840 for (i = 0; i < mono_array_length (tb->properties); ++i)
3841 mono_image_get_property_info (
3842 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3845 /* handle generic parameters */
3846 if (tb->generic_params) {
3847 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3848 table->rows += mono_array_length (tb->generic_params);
3849 alloc_table (table, table->rows);
3850 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3851 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3853 mono_image_get_generic_param_info (
3854 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3858 mono_image_add_decl_security (assembly,
3859 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3862 MonoDynamicTable *ntable;
3864 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3865 ntable->rows += mono_array_length (tb->subtypes);
3866 alloc_table (ntable, ntable->rows);
3867 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3869 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3870 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3872 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3873 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3874 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3875 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3876 mono_string_to_utf8 (tb->name), tb->table_idx,
3877 ntable->next_idx, ntable->rows);*/
3878 values += MONO_NESTED_CLASS_SIZE;
3888 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3892 mono_ptr_array_append (*types, type);
3894 if (!type->subtypes)
3897 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3898 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3899 collect_types (types, subtype);
3904 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3906 if ((*type1)->table_idx < (*type2)->table_idx)
3909 if ((*type1)->table_idx > (*type2)->table_idx)
3916 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3919 mono_error_init (error);
3922 for (i = 0; i < mono_array_length (pinfo); ++i) {
3923 MonoReflectionParamBuilder *pb;
3924 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3927 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3935 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3938 mono_error_init (error);
3940 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3943 for (i = 0; i < tb->num_fields; ++i) {
3944 MonoReflectionFieldBuilder* fb;
3945 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3946 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3951 for (i = 0; i < mono_array_length (tb->events); ++i) {
3952 MonoReflectionEventBuilder* eb;
3953 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3954 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3958 if (tb->properties) {
3959 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3960 MonoReflectionPropertyBuilder* pb;
3961 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3962 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3967 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3968 MonoReflectionCtorBuilder* cb;
3969 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3970 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3971 !params_add_cattrs (assembly, cb->pinfo, error))
3977 for (i = 0; i < tb->num_methods; ++i) {
3978 MonoReflectionMethodBuilder* mb;
3979 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3980 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3981 !params_add_cattrs (assembly, mb->pinfo, error))
3987 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3988 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3997 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4001 mono_error_init (error);
4003 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4006 if (moduleb->global_methods) {
4007 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4008 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4009 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4010 !params_add_cattrs (assembly, mb->pinfo, error))
4015 if (moduleb->global_fields) {
4016 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4017 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4018 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4023 if (moduleb->types) {
4024 for (i = 0; i < moduleb->num_types; ++i) {
4025 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4034 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4036 MonoDynamicTable *table;
4040 char *b = blob_size;
4043 table = &assembly->tables [MONO_TABLE_FILE];
4045 alloc_table (table, table->rows);
4046 values = table->values + table->next_idx * MONO_FILE_SIZE;
4047 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4048 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4049 if (image_is_dynamic (module->image)) {
4050 /* This depends on the fact that the main module is emitted last */
4051 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4052 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4055 path = g_strdup (module->image->name);
4057 mono_sha1_get_digest_from_file (path, hash);
4060 mono_metadata_encode_value (20, b, &b);
4061 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4062 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4067 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4069 MonoDynamicTable *table;
4072 table = &assembly->tables [MONO_TABLE_MODULE];
4073 mb->table_idx = table->next_idx ++;
4074 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4075 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4079 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4080 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4081 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4085 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4086 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4088 MonoDynamicTable *table;
4092 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4093 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4096 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4098 alloc_table (table, table->rows);
4099 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4101 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4102 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4103 if (klass->nested_in)
4104 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4106 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4107 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4108 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4110 res = table->next_idx;
4114 /* Emit nested types */
4115 if (klass->ext && klass->ext->nested_classes) {
4118 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4119 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4126 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4127 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4132 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4134 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4136 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4137 parent_index, assembly);
4141 * We need to do this ourselves since klass->nested_classes is not set up.
4144 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4145 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4150 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4151 guint32 module_index, MonoDynamicImage *assembly)
4153 MonoImage *image = module->image;
4157 t = &image->tables [MONO_TABLE_TYPEDEF];
4159 for (i = 0; i < t->rows; ++i) {
4161 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4162 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4164 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4165 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4170 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4172 MonoDynamicTable *table;
4174 guint32 scope, scope_idx, impl, current_idx;
4175 gboolean forwarder = TRUE;
4176 gpointer iter = NULL;
4179 if (klass->nested_in) {
4180 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4183 scope = resolution_scope_from_image (assembly, klass->image);
4184 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4185 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4186 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4189 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4192 alloc_table (table, table->rows);
4193 current_idx = table->next_idx;
4194 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4196 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4197 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4198 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4199 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4200 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4204 while ((nested = mono_class_get_nested_types (klass, &iter)))
4205 add_exported_type (assemblyb, assembly, nested, current_idx);
4209 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4214 if (!assemblyb->type_forwarders)
4217 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4218 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4223 type = mono_reflection_type_get_handle (t);
4226 klass = mono_class_from_mono_type (type);
4228 add_exported_type (assemblyb, assembly, klass, 0);
4232 #define align_pointer(base,p)\
4234 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4236 (p) += 4 - (__diff & 3);\
4240 compare_constants (const void *a, const void *b)
4242 const guint32 *a_values = (const guint32 *)a;
4243 const guint32 *b_values = (const guint32 *)b;
4244 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4248 compare_semantics (const void *a, const void *b)
4250 const guint32 *a_values = (const guint32 *)a;
4251 const guint32 *b_values = (const guint32 *)b;
4252 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4255 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4259 compare_custom_attrs (const void *a, const void *b)
4261 const guint32 *a_values = (const guint32 *)a;
4262 const guint32 *b_values = (const guint32 *)b;
4264 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4268 compare_field_marshal (const void *a, const void *b)
4270 const guint32 *a_values = (const guint32 *)a;
4271 const guint32 *b_values = (const guint32 *)b;
4273 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4277 compare_nested (const void *a, const void *b)
4279 const guint32 *a_values = (const guint32 *)a;
4280 const guint32 *b_values = (const guint32 *)b;
4282 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4286 compare_genericparam (const void *a, const void *b)
4288 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4289 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4291 if ((*b_entry)->owner == (*a_entry)->owner)
4293 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4294 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4296 return (*a_entry)->owner - (*b_entry)->owner;
4300 compare_declsecurity_attrs (const void *a, const void *b)
4302 const guint32 *a_values = (const guint32 *)a;
4303 const guint32 *b_values = (const guint32 *)b;
4305 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4309 compare_interface_impl (const void *a, const void *b)
4311 const guint32 *a_values = (const guint32 *)a;
4312 const guint32 *b_values = (const guint32 *)b;
4314 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4318 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4322 pad_heap (MonoDynamicStream *sh)
4324 if (sh->index & 3) {
4325 int sz = 4 - (sh->index & 3);
4326 memset (sh->data + sh->index, 0, sz);
4333 MonoDynamicStream *stream;
4337 * build_compressed_metadata() fills in the blob of data that represents the
4338 * raw metadata as it will be saved in the PE file. The five streams are output
4339 * and the metadata tables are comnpressed from the guint32 array representation,
4340 * to the compressed on-disk format.
4343 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4345 MonoDynamicTable *table;
4347 guint64 valid_mask = 0;
4348 guint64 sorted_mask;
4349 guint32 heapt_size = 0;
4350 guint32 meta_size = 256; /* allow for header and other stuff */
4351 guint32 table_offset;
4352 guint32 ntables = 0;
4358 struct StreamDesc stream_desc [5];
4360 mono_error_init (error);
4362 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4363 for (i = 0; i < assembly->gen_params->len; i++) {
4364 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4365 if (!write_generic_param_entry (assembly, entry, error))
4369 stream_desc [0].name = "#~";
4370 stream_desc [0].stream = &assembly->tstream;
4371 stream_desc [1].name = "#Strings";
4372 stream_desc [1].stream = &assembly->sheap;
4373 stream_desc [2].name = "#US";
4374 stream_desc [2].stream = &assembly->us;
4375 stream_desc [3].name = "#Blob";
4376 stream_desc [3].stream = &assembly->blob;
4377 stream_desc [4].name = "#GUID";
4378 stream_desc [4].stream = &assembly->guid;
4380 /* tables that are sorted */
4381 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4382 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4383 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4384 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4385 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4386 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4387 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4389 /* Compute table sizes */
4390 /* the MonoImage has already been created in mono_image_basic_init() */
4391 meta = &assembly->image;
4393 /* sizes should be multiple of 4 */
4394 pad_heap (&assembly->blob);
4395 pad_heap (&assembly->guid);
4396 pad_heap (&assembly->sheap);
4397 pad_heap (&assembly->us);
4399 /* Setup the info used by compute_sizes () */
4400 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4401 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4402 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4404 meta_size += assembly->blob.index;
4405 meta_size += assembly->guid.index;
4406 meta_size += assembly->sheap.index;
4407 meta_size += assembly->us.index;
4409 for (i=0; i < MONO_TABLE_NUM; ++i)
4410 meta->tables [i].rows = assembly->tables [i].rows;
4412 for (i = 0; i < MONO_TABLE_NUM; i++){
4413 if (meta->tables [i].rows == 0)
4415 valid_mask |= (guint64)1 << i;
4417 meta->tables [i].row_size = mono_metadata_compute_size (
4418 meta, i, &meta->tables [i].size_bitfield);
4419 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4421 heapt_size += 24; /* #~ header size */
4422 heapt_size += ntables * 4;
4423 /* make multiple of 4 */
4426 meta_size += heapt_size;
4427 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4428 p = (unsigned char*)meta->raw_metadata;
4429 /* the metadata signature */
4430 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4431 /* version numbers and 4 bytes reserved */
4432 int16val = (guint16*)p;
4433 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4434 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4436 /* version string */
4437 int32val = (guint32*)p;
4438 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4440 memcpy (p, meta->version, strlen (meta->version));
4441 p += GUINT32_FROM_LE (*int32val);
4442 align_pointer (meta->raw_metadata, p);
4443 int16val = (guint16*)p;
4444 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4445 *int16val = GUINT16_TO_LE (5); /* number of streams */
4449 * write the stream info.
4451 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4452 table_offset += 3; table_offset &= ~3;
4454 assembly->tstream.index = heapt_size;
4455 for (i = 0; i < 5; ++i) {
4456 int32val = (guint32*)p;
4457 stream_desc [i].stream->offset = table_offset;
4458 *int32val++ = GUINT32_TO_LE (table_offset);
4459 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4460 table_offset += GUINT32_FROM_LE (*int32val);
4461 table_offset += 3; table_offset &= ~3;
4463 strcpy ((char*)p, stream_desc [i].name);
4464 p += strlen (stream_desc [i].name) + 1;
4465 align_pointer (meta->raw_metadata, p);
4468 * now copy the data, the table stream header and contents goes first.
4470 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4471 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4472 int32val = (guint32*)p;
4473 *int32val = GUINT32_TO_LE (0); /* reserved */
4476 *p++ = 2; /* version */
4479 if (meta->idx_string_wide)
4481 if (meta->idx_guid_wide)
4483 if (meta->idx_blob_wide)
4486 *p++ = 1; /* reserved */
4487 int64val = (guint64*)p;
4488 *int64val++ = GUINT64_TO_LE (valid_mask);
4489 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4491 int32val = (guint32*)p;
4492 for (i = 0; i < MONO_TABLE_NUM; i++){
4493 if (meta->tables [i].rows == 0)
4495 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4497 p = (unsigned char*)int32val;
4499 /* sort the tables that still need sorting */
4500 table = &assembly->tables [MONO_TABLE_CONSTANT];
4502 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4503 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4505 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4506 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4508 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4509 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4511 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4512 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4514 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4515 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4516 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4518 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4519 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4521 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4523 /* compress the tables */
4524 for (i = 0; i < MONO_TABLE_NUM; i++){
4527 guint32 bitfield = meta->tables [i].size_bitfield;
4528 if (!meta->tables [i].rows)
4530 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4531 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4532 meta->tables [i].base = (char*)p;
4533 for (row = 1; row <= meta->tables [i].rows; ++row) {
4534 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4535 for (col = 0; col < assembly->tables [i].columns; ++col) {
4536 switch (mono_metadata_table_size (bitfield, col)) {
4538 *p++ = values [col];
4541 *p++ = values [col] & 0xff;
4542 *p++ = (values [col] >> 8) & 0xff;
4545 *p++ = values [col] & 0xff;
4546 *p++ = (values [col] >> 8) & 0xff;
4547 *p++ = (values [col] >> 16) & 0xff;
4548 *p++ = (values [col] >> 24) & 0xff;
4551 g_assert_not_reached ();
4555 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4558 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4559 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4560 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4561 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4562 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4564 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4570 * Some tables in metadata need to be sorted according to some criteria, but
4571 * when methods and fields are first created with reflection, they may be assigned a token
4572 * that doesn't correspond to the final token they will get assigned after the sorting.
4573 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4574 * with the reflection objects that represent them. Once all the tables are set up, the
4575 * reflection objects will contains the correct table index. fixup_method() will fixup the
4576 * tokens for the method with ILGenerator @ilgen.
4579 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4581 guint32 code_idx = GPOINTER_TO_UINT (value);
4582 MonoReflectionILTokenInfo *iltoken;
4583 MonoReflectionFieldBuilder *field;
4584 MonoReflectionCtorBuilder *ctor;
4585 MonoReflectionMethodBuilder *method;
4586 MonoReflectionTypeBuilder *tb;
4587 MonoReflectionArrayMethod *am;
4589 unsigned char *target;
4591 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4592 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4593 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4594 switch (target [3]) {
4595 case MONO_TABLE_FIELD:
4596 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4597 field = (MonoReflectionFieldBuilder *)iltoken->member;
4598 idx = field->table_idx;
4599 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4600 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4601 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4603 g_assert_not_reached ();
4606 case MONO_TABLE_METHOD:
4607 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4608 method = (MonoReflectionMethodBuilder *)iltoken->member;
4609 idx = method->table_idx;
4610 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4611 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4612 idx = ctor->table_idx;
4613 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4614 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4615 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4618 g_assert_not_reached ();
4621 case MONO_TABLE_TYPEDEF:
4622 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4623 g_assert_not_reached ();
4624 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4625 idx = tb->table_idx;
4627 case MONO_TABLE_MEMBERREF:
4628 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4629 am = (MonoReflectionArrayMethod*)iltoken->member;
4630 idx = am->table_idx;
4631 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4632 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4633 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4634 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4635 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636 g_assert (m->klass->generic_class || m->klass->generic_container);
4638 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4640 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4641 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4642 g_assert (is_field_on_inst (f));
4644 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4645 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4647 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4649 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4651 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4654 g_assert_not_reached ();
4657 case MONO_TABLE_METHODSPEC:
4658 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4659 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4660 g_assert (mono_method_signature (m)->generic_param_count);
4662 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4664 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4667 g_assert_not_reached ();
4671 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4673 target [0] = idx & 0xff;
4674 target [1] = (idx >> 8) & 0xff;
4675 target [2] = (idx >> 16) & 0xff;
4682 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4683 * value is not known when the table is emitted.
4686 fixup_cattrs (MonoDynamicImage *assembly)
4688 MonoDynamicTable *table;
4690 guint32 type, i, idx, token;
4693 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4695 for (i = 0; i < table->rows; ++i) {
4696 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4698 type = values [MONO_CUSTOM_ATTR_TYPE];
4699 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4700 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4701 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4702 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4705 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4706 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4707 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4708 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4709 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4710 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4711 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4712 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4719 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4721 MonoDynamicTable *table;
4724 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4726 alloc_table (table, table->rows);
4727 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4728 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4729 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4730 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4731 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4736 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4738 MonoDynamicTable *table;
4742 char *b = blob_size;
4744 guint32 idx, offset;
4746 if (rsrc->filename) {
4747 name = mono_string_to_utf8 (rsrc->filename);
4748 sname = g_path_get_basename (name);
4750 table = &assembly->tables [MONO_TABLE_FILE];
4752 alloc_table (table, table->rows);
4753 values = table->values + table->next_idx * MONO_FILE_SIZE;
4754 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4755 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4758 mono_sha1_get_digest_from_file (name, hash);
4759 mono_metadata_encode_value (20, b, &b);
4760 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4761 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4763 idx = table->next_idx++;
4765 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4771 data = mono_array_addr (rsrc->data, char, 0);
4772 len = mono_array_length (rsrc->data);
4778 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4779 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4780 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4781 mono_image_add_stream_data (&assembly->resources, data, len);
4785 * The entry should be emitted into the MANIFESTRESOURCE table of
4786 * the main module, but that needs to reference the FILE table
4787 * which isn't emitted yet.
4794 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4798 set_version_from_string (MonoString *version, guint32 *values)
4800 gchar *ver, *p, *str;
4803 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4804 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4805 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4806 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4809 ver = str = mono_string_to_utf8 (version);
4810 for (i = 0; i < 4; ++i) {
4811 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4817 /* handle Revision and Build */
4827 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4831 char *b = blob_size;
4836 len = mono_array_length (pkey);
4837 mono_metadata_encode_value (len, b, &b);
4838 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4839 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4841 assembly->public_key = (guint8 *)g_malloc (len);
4842 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4843 assembly->public_key_len = len;
4845 /* Special case: check for ECMA key (16 bytes) */
4846 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4847 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4848 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4849 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4850 /* minimum key size (in 2.0) is 384 bits */
4851 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4853 /* FIXME - verifier */
4854 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4855 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4857 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4863 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4865 MonoDynamicTable *table;
4866 MonoDynamicImage *assembly;
4867 MonoReflectionAssemblyBuilder *assemblyb;
4871 guint32 module_index;
4873 assemblyb = moduleb->assemblyb;
4874 assembly = moduleb->dynamic_image;
4875 domain = mono_object_domain (assemblyb);
4877 /* Emit ASSEMBLY table */
4878 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4879 alloc_table (table, 1);
4880 values = table->values + MONO_ASSEMBLY_SIZE;
4881 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4882 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4883 if (assemblyb->culture) {
4884 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4886 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4888 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4889 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4890 set_version_from_string (assemblyb->version, values);
4892 /* Emit FILE + EXPORTED_TYPE table */
4894 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4896 MonoReflectionModuleBuilder *file_module =
4897 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4898 if (file_module != moduleb) {
4899 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4901 if (file_module->types) {
4902 for (j = 0; j < file_module->num_types; ++j) {
4903 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4904 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4909 if (assemblyb->loaded_modules) {
4910 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4911 MonoReflectionModule *file_module =
4912 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4913 mono_image_fill_file_table (domain, file_module, assembly);
4915 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4918 if (assemblyb->type_forwarders)
4919 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4921 /* Emit MANIFESTRESOURCE table */
4923 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4925 MonoReflectionModuleBuilder *file_module =
4926 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4927 /* The table for the main module is emitted later */
4928 if (file_module != moduleb) {
4930 if (file_module->resources) {
4931 int len = mono_array_length (file_module->resources);
4932 for (j = 0; j < len; ++j) {
4933 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4934 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4941 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4944 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4945 * for the modulebuilder @moduleb.
4946 * At the end of the process, method and field tokens are fixed up and the
4947 * on-disk compressed metadata representation is created.
4948 * Return TRUE on success, or FALSE on failure and sets @error
4951 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4953 MonoDynamicTable *table;
4954 MonoDynamicImage *assembly;
4955 MonoReflectionAssemblyBuilder *assemblyb;
4961 mono_error_init (error);
4963 assemblyb = moduleb->assemblyb;
4964 assembly = moduleb->dynamic_image;
4965 domain = mono_object_domain (assemblyb);
4967 if (assembly->text_rva)
4970 assembly->text_rva = START_TEXT_RVA;
4972 if (moduleb->is_main) {
4973 mono_image_emit_manifest (moduleb);
4976 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4977 table->rows = 1; /* .<Module> */
4979 alloc_table (table, table->rows);
4981 * Set the first entry.
4983 values = table->values + table->columns;
4984 values [MONO_TYPEDEF_FLAGS] = 0;
4985 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4986 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4987 values [MONO_TYPEDEF_EXTENDS] = 0;
4988 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4989 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4992 * handle global methods
4993 * FIXME: test what to do when global methods are defined in multiple modules.
4995 if (moduleb->global_methods) {
4996 table = &assembly->tables [MONO_TABLE_METHOD];
4997 table->rows += mono_array_length (moduleb->global_methods);
4998 alloc_table (table, table->rows);
4999 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5000 if (!mono_image_get_method_info (
5001 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5005 if (moduleb->global_fields) {
5006 table = &assembly->tables [MONO_TABLE_FIELD];
5007 table->rows += mono_array_length (moduleb->global_fields);
5008 alloc_table (table, table->rows);
5009 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5010 mono_image_get_field_info (
5011 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5014 table = &assembly->tables [MONO_TABLE_MODULE];
5015 alloc_table (table, 1);
5016 mono_image_fill_module_table (domain, moduleb, assembly);
5018 /* Collect all types into a list sorted by their table_idx */
5019 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5022 for (i = 0; i < moduleb->num_types; ++i) {
5023 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5024 collect_types (&types, type);
5027 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5028 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5029 table->rows += mono_ptr_array_size (types);
5030 alloc_table (table, table->rows);
5033 * Emit type names + namespaces at one place inside the string heap,
5034 * so load_class_names () needs to touch fewer pages.
5036 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5037 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5038 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5040 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5041 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5042 string_heap_insert_mstring (&assembly->sheap, tb->name);
5045 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5046 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5047 if (!mono_image_get_type_info (domain, type, assembly, error))
5052 * table->rows is already set above and in mono_image_fill_module_table.
5054 /* add all the custom attributes at the end, once all the indexes are stable */
5055 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5058 /* CAS assembly permissions */
5059 if (assemblyb->permissions_minimum)
5060 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5061 if (assemblyb->permissions_optional)
5062 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5063 if (assemblyb->permissions_refused)
5064 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5066 if (!module_add_cattrs (assembly, moduleb, error))
5070 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5072 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5073 * the final tokens and don't need another fixup pass. */
5075 if (moduleb->global_methods) {
5076 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5077 MonoReflectionMethodBuilder *mb = mono_array_get (
5078 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5079 if (!mono_image_add_methodimpl (assembly, mb, error))
5084 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5085 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5086 if (type->methods) {
5087 for (j = 0; j < type->num_methods; ++j) {
5088 MonoReflectionMethodBuilder *mb = mono_array_get (
5089 type->methods, MonoReflectionMethodBuilder*, j);
5091 if (!mono_image_add_methodimpl (assembly, mb, error))
5097 fixup_cattrs (assembly);
5100 mono_ptr_array_destroy (types);
5103 return mono_error_ok (error);
5106 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5109 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5111 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5114 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5118 guint32 import_lookup_table;
5122 guint32 import_address_table_rva;
5130 #ifndef DISABLE_REFLECTION_EMIT
5133 * mono_image_insert_string:
5134 * @module: module builder object
5137 * Insert @str into the user string stream of @module.
5140 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5142 MonoDynamicImage *assembly;
5147 if (!module->dynamic_image)
5148 mono_image_module_basic_init (module);
5150 assembly = module->dynamic_image;
5152 if (assembly->save) {
5153 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5154 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5155 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5157 char *swapped = g_malloc (2 * mono_string_length (str));
5158 const char *p = (const char*)mono_string_chars (str);
5160 swap_with_size (swapped, p, 2, mono_string_length (str));
5161 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5165 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5167 mono_image_add_stream_data (&assembly->us, "", 1);
5169 idx = assembly->us.index ++;
5172 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5174 return MONO_TOKEN_STRING | idx;
5178 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5182 MonoMethodSignature *sig;
5184 mono_error_init (error);
5186 klass = obj->vtable->klass;
5187 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5188 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5189 MonoMethodSignature *old;
5190 guint32 sig_token, parent;
5193 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5195 nargs = mono_array_length (opt_param_types);
5196 old = mono_method_signature (method);
5197 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5199 sig->hasthis = old->hasthis;
5200 sig->explicit_this = old->explicit_this;
5201 sig->call_convention = old->call_convention;
5202 sig->generic_param_count = old->generic_param_count;
5203 sig->param_count = old->param_count + nargs;
5204 sig->sentinelpos = old->param_count;
5205 sig->ret = old->ret;
5207 for (i = 0; i < old->param_count; i++)
5208 sig->params [i] = old->params [i];
5210 for (i = 0; i < nargs; i++) {
5211 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5212 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5215 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5216 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5217 parent >>= MONO_TYPEDEFORREF_BITS;
5219 parent <<= MONO_MEMBERREF_PARENT_BITS;
5220 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5222 sig_token = method_encode_signature (assembly, sig);
5223 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5224 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5225 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5226 ReflectionMethodBuilder rmb;
5227 guint32 parent, sig_token;
5228 int nopt_args, nparams, ngparams, i;
5230 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5233 rmb.opt_types = opt_param_types;
5234 nopt_args = mono_array_length (opt_param_types);
5236 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5237 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5238 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5240 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5241 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5242 sig->call_convention = rmb.call_conv;
5243 sig->generic_param_count = ngparams;
5244 sig->param_count = nparams + nopt_args;
5245 sig->sentinelpos = nparams;
5246 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5248 for (i = 0; i < nparams; i++) {
5249 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5250 sig->params [i] = mono_reflection_type_get_handle (rt);
5253 for (i = 0; i < nopt_args; i++) {
5254 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5255 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5258 sig_token = method_builder_encode_signature (assembly, &rmb);
5260 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5261 if (!mono_error_ok (error))
5263 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5265 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5266 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5268 char *name = mono_string_to_utf8 (rmb.name);
5269 token = mono_image_get_varargs_method_token (
5270 assembly, parent, name, sig_token);
5273 g_error ("requested method token for %s\n", klass->name);
5276 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5277 register_dyn_token (assembly, token, obj);
5280 g_assert (!mono_error_ok (error));
5285 * mono_image_create_token:
5286 * @assembly: a dynamic assembly
5288 * @register_token: Whenever to register the token in the assembly->tokens hash.
5290 * Get a token to insert in the IL code stream for the given MemberInfo.
5291 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5292 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5296 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5297 gboolean create_open_instance, gboolean register_token,
5303 mono_error_init (error);
5305 klass = obj->vtable->klass;
5307 /* Check for user defined reflection objects */
5308 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5309 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5310 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5314 if (strcmp (klass->name, "MethodBuilder") == 0) {
5315 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5318 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5319 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5321 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5322 if (!mono_error_ok (error))
5325 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5326 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5327 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5328 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5330 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5331 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5333 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5334 if (!mono_error_ok (error))
5337 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5338 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5339 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5340 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5341 if (tb->generic_params) {
5342 token = mono_image_get_generic_field_token (assembly, fb);
5344 if (tb->module->dynamic_image == assembly) {
5345 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5347 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5350 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5351 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5352 if (create_open_instance && tb->generic_params) {
5354 init_type_builder_generics (obj);
5355 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5356 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5357 token = mono_metadata_token_from_dor (token);
5358 } else if (tb->module->dynamic_image == assembly) {
5359 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5362 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5363 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5365 } else if (strcmp (klass->name, "MonoType") == 0) {
5366 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5367 MonoClass *mc = mono_class_from_mono_type (type);
5368 token = mono_metadata_token_from_dor (
5369 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5370 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5371 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5372 token = mono_metadata_token_from_dor (
5373 mono_image_typedef_or_ref (assembly, type));
5374 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5375 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5376 token = mono_metadata_token_from_dor (
5377 mono_image_typedef_or_ref (assembly, type));
5378 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5379 strcmp (klass->name, "MonoMethod") == 0 ||
5380 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5381 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5382 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5383 if (m->method->is_inflated) {
5384 if (create_open_instance)
5385 token = mono_image_get_methodspec_token (assembly, m->method);
5387 token = mono_image_get_inflated_method_token (assembly, m->method);
5388 } else if ((m->method->klass->image == &assembly->image) &&
5389 !m->method->klass->generic_class) {
5390 static guint32 method_table_idx = 0xffffff;
5391 if (m->method->klass->wastypebuilder) {
5392 /* we use the same token as the one that was assigned
5393 * to the Methodbuilder.
5394 * FIXME: do the equivalent for Fields.
5396 token = m->method->token;
5399 * Each token should have a unique index, but the indexes are
5400 * assigned by managed code, so we don't know about them. An
5401 * easy solution is to count backwards...
5403 method_table_idx --;
5404 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5407 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5409 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5410 } else if (strcmp (klass->name, "MonoField") == 0) {
5411 MonoReflectionField *f = (MonoReflectionField *)obj;
5412 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5413 static guint32 field_table_idx = 0xffffff;
5415 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5417 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5419 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5420 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5421 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5422 token = mono_image_get_array_token (assembly, m);
5423 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5424 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5425 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5426 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5427 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5428 token = mono_metadata_token_from_dor (
5429 mono_image_typedef_or_ref (assembly, type));
5430 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5431 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5432 token = mono_image_get_field_on_inst_token (assembly, f);
5433 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5434 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5435 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5436 if (!mono_error_ok (error))
5438 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5439 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5440 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5441 if (!mono_error_ok (error))
5443 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5444 MonoReflectionType *type = (MonoReflectionType *)obj;
5445 token = mono_metadata_token_from_dor (
5446 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5448 g_error ("requested token for %s\n", klass->name);
5452 mono_image_register_token (assembly, token, obj);
5458 * mono_image_register_token:
5460 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5461 * the Module.ResolveXXXToken () methods to work.
5464 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5468 dynamic_image_lock (assembly);
5469 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5471 /* There could be multiple MethodInfo objects with the same token */
5472 //g_assert (prev == obj);
5474 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5476 dynamic_image_unlock (assembly);
5479 static MonoDynamicImage*
5480 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5482 static const guchar entrycode [16] = {0xff, 0x25, 0};
5483 MonoDynamicImage *image;
5486 const char *version;
5488 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5489 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5491 version = mono_get_runtime_info ()->runtime_version;
5494 /* The MonoGHashTable's need GC tracking */
5495 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5497 image = g_new0 (MonoDynamicImage, 1);
5500 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5502 /*g_print ("created image %p\n", image);*/
5503 /* keep in sync with image.c */
5504 image->image.name = assembly_name;
5505 image->image.assembly_name = image->image.name; /* they may be different */
5506 image->image.module_name = module_name;
5507 image->image.version = g_strdup (version);
5508 image->image.md_version_major = 1;
5509 image->image.md_version_minor = 1;
5510 image->image.dynamic = TRUE;
5512 image->image.references = g_new0 (MonoAssembly*, 1);
5513 image->image.references [0] = NULL;
5515 mono_image_init (&image->image);
5517 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");
5518 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5519 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5520 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5521 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5522 image->handleref = g_hash_table_new (NULL, NULL);
5523 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");
5524 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5525 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");
5526 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");
5527 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5528 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5529 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5530 image->gen_params = g_ptr_array_new ();
5531 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5533 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5534 string_heap_init (&image->sheap);
5535 mono_image_add_stream_data (&image->us, "", 1);
5536 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5537 /* import tables... */
5538 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5539 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5540 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5541 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5542 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5543 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5544 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5545 stream_data_align (&image->code);
5547 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5549 for (i=0; i < MONO_TABLE_NUM; ++i) {
5550 image->tables [i].next_idx = 1;
5551 image->tables [i].columns = table_sizes [i];
5554 image->image.assembly = (MonoAssembly*)assembly;
5555 image->run = assembly->run;
5556 image->save = assembly->save;
5557 image->pe_kind = 0x1; /* ILOnly */
5558 image->machine = 0x14c; /* I386 */
5560 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5562 dynamic_images_lock ();
5564 if (!dynamic_images)
5565 dynamic_images = g_ptr_array_new ();
5567 g_ptr_array_add (dynamic_images, image);
5569 dynamic_images_unlock ();
5576 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5582 release_hashtable (MonoGHashTable **hash)
5585 mono_g_hash_table_destroy (*hash);
5591 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5593 release_hashtable (&image->token_fixups);
5594 release_hashtable (&image->handleref_managed);
5595 release_hashtable (&image->tokens);
5596 release_hashtable (&image->remapped_tokens);
5597 release_hashtable (&image->generic_def_objects);
5598 release_hashtable (&image->methodspec);
5601 // Free dynamic image pass one: Free resources but not image itself
5603 mono_dynamic_image_free (MonoDynamicImage *image)
5605 MonoDynamicImage *di = image;
5610 mono_g_hash_table_destroy (di->methodspec);
5612 g_hash_table_destroy (di->typespec);
5614 g_hash_table_destroy (di->typeref);
5616 g_hash_table_destroy (di->handleref);
5617 if (di->handleref_managed)
5618 mono_g_hash_table_destroy (di->handleref_managed);
5620 mono_g_hash_table_destroy (di->tokens);
5621 if (di->remapped_tokens)
5622 mono_g_hash_table_destroy (di->remapped_tokens);
5623 if (di->generic_def_objects)
5624 mono_g_hash_table_destroy (di->generic_def_objects);
5625 if (di->blob_cache) {
5626 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5627 g_hash_table_destroy (di->blob_cache);
5629 if (di->standalonesig_cache)
5630 g_hash_table_destroy (di->standalonesig_cache);
5631 for (list = di->array_methods; list; list = list->next) {
5632 ArrayMethod *am = (ArrayMethod *)list->data;
5637 g_list_free (di->array_methods);
5638 if (di->gen_params) {
5639 for (i = 0; i < di->gen_params->len; i++) {
5640 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5641 mono_gc_deregister_root ((char*) &entry->gparam);
5644 g_ptr_array_free (di->gen_params, TRUE);
5646 if (di->token_fixups)
5647 mono_g_hash_table_destroy (di->token_fixups);
5648 if (di->method_to_table_idx)
5649 g_hash_table_destroy (di->method_to_table_idx);
5650 if (di->field_to_table_idx)
5651 g_hash_table_destroy (di->field_to_table_idx);
5652 if (di->method_aux_hash)
5653 g_hash_table_destroy (di->method_aux_hash);
5654 if (di->vararg_aux_hash)
5655 g_hash_table_destroy (di->vararg_aux_hash);
5656 g_free (di->strong_name);
5657 g_free (di->win32_res);
5659 g_free (di->public_key);
5661 /*g_print ("string heap destroy for image %p\n", di);*/
5662 mono_dynamic_stream_reset (&di->sheap);
5663 mono_dynamic_stream_reset (&di->code);
5664 mono_dynamic_stream_reset (&di->resources);
5665 mono_dynamic_stream_reset (&di->us);
5666 mono_dynamic_stream_reset (&di->blob);
5667 mono_dynamic_stream_reset (&di->tstream);
5668 mono_dynamic_stream_reset (&di->guid);
5669 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5670 g_free (di->tables [i].values);
5673 dynamic_images_lock ();
5676 g_ptr_array_remove (dynamic_images, di);
5678 dynamic_images_unlock ();
5681 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5683 mono_dynamic_image_free_image (MonoDynamicImage *image)
5685 /* See create_dynamic_mono_image () */
5687 /* Allocated using GC_MALLOC */
5693 #ifndef DISABLE_REFLECTION_EMIT
5696 * mono_image_basic_init:
5697 * @assembly: an assembly builder object
5699 * Create the MonoImage that represents the assembly builder and setup some
5700 * of the helper hash table and the basic metadata streams.
5703 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5705 MonoDynamicAssembly *assembly;
5706 MonoDynamicImage *image;
5707 MonoDomain *domain = mono_object_domain (assemblyb);
5709 if (assemblyb->dynamic_assembly)
5713 /* assembly->assembly.image might be GC allocated */
5714 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5716 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5719 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5721 assembly->assembly.ref_count = 1;
5722 assembly->assembly.dynamic = TRUE;
5723 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5724 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5725 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5726 if (assemblyb->culture)
5727 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5729 assembly->assembly.aname.culture = g_strdup ("");
5731 if (assemblyb->version) {
5732 char *vstr = mono_string_to_utf8 (assemblyb->version);
5733 char **version = g_strsplit (vstr, ".", 4);
5734 char **parts = version;
5735 assembly->assembly.aname.major = atoi (*parts++);
5736 assembly->assembly.aname.minor = atoi (*parts++);
5737 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5738 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5740 g_strfreev (version);
5743 assembly->assembly.aname.major = 0;
5744 assembly->assembly.aname.minor = 0;
5745 assembly->assembly.aname.build = 0;
5746 assembly->assembly.aname.revision = 0;
5749 assembly->run = assemblyb->access != 2;
5750 assembly->save = assemblyb->access != 1;
5751 assembly->domain = domain;
5753 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5754 image->initial_image = TRUE;
5755 assembly->assembly.aname.name = image->image.name;
5756 assembly->assembly.image = &image->image;
5757 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5758 /* -1 to correct for the trailing NULL byte */
5759 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5760 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5762 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5765 mono_domain_assemblies_lock (domain);
5766 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5767 mono_domain_assemblies_unlock (domain);
5769 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5771 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5773 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5776 #endif /* !DISABLE_REFLECTION_EMIT */
5778 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5781 calc_section_size (MonoDynamicImage *assembly)
5785 /* alignment constraints */
5786 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5787 g_assert ((assembly->code.index % 4) == 0);
5788 assembly->meta_size += 3;
5789 assembly->meta_size &= ~3;
5790 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5791 g_assert ((assembly->resources.index % 4) == 0);
5793 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5794 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5797 if (assembly->win32_res) {
5798 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5800 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5801 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5805 assembly->sections [MONO_SECTION_RELOC].size = 12;
5806 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5816 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5822 ResTreeNode *t1 = (ResTreeNode*)a;
5823 ResTreeNode *t2 = (ResTreeNode*)b;
5825 return t1->id - t2->id;
5829 * resource_tree_create:
5831 * Organize the resources into a resource tree.
5833 static ResTreeNode *
5834 resource_tree_create (MonoArray *win32_resources)
5836 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5840 tree = g_new0 (ResTreeNode, 1);
5842 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5843 MonoReflectionWin32Resource *win32_res =
5844 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5848 /* FIXME: BUG: this stores managed references in unmanaged memory */
5849 lang_node = g_new0 (ResTreeNode, 1);
5850 lang_node->id = win32_res->lang_id;
5851 lang_node->win32_res = win32_res;
5853 /* Create type node if neccesary */
5855 for (l = tree->children; l; l = l->next)
5856 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5857 type_node = (ResTreeNode*)l->data;
5862 type_node = g_new0 (ResTreeNode, 1);
5863 type_node->id = win32_res->res_type;
5866 * The resource types have to be sorted otherwise
5867 * Windows Explorer can't display the version information.
5869 tree->children = g_slist_insert_sorted (tree->children,
5870 type_node, resource_tree_compare_by_id);
5873 /* Create res node if neccesary */
5875 for (l = type_node->children; l; l = l->next)
5876 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5877 res_node = (ResTreeNode*)l->data;
5882 res_node = g_new0 (ResTreeNode, 1);
5883 res_node->id = win32_res->res_id;
5884 type_node->children = g_slist_append (type_node->children, res_node);
5887 res_node->children = g_slist_append (res_node->children, lang_node);
5894 * resource_tree_encode:
5896 * Encode the resource tree into the format used in the PE file.
5899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5902 MonoPEResourceDir dir;
5903 MonoPEResourceDirEntry dir_entry;
5904 MonoPEResourceDataEntry data_entry;
5906 guint32 res_id_entries;
5909 * For the format of the resource directory, see the article
5910 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5914 memset (&dir, 0, sizeof (dir));
5915 memset (&dir_entry, 0, sizeof (dir_entry));
5916 memset (&data_entry, 0, sizeof (data_entry));
5918 g_assert (sizeof (dir) == 16);
5919 g_assert (sizeof (dir_entry) == 8);
5920 g_assert (sizeof (data_entry) == 16);
5922 node->offset = p - begin;
5924 /* IMAGE_RESOURCE_DIRECTORY */
5925 res_id_entries = g_slist_length (node->children);
5926 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5928 memcpy (p, &dir, sizeof (dir));
5931 /* Reserve space for entries */
5933 p += sizeof (dir_entry) * res_id_entries;
5935 /* Write children */
5936 for (l = node->children; l; l = l->next) {
5937 ResTreeNode *child = (ResTreeNode*)l->data;
5939 if (child->win32_res) {
5942 child->offset = p - begin;
5944 /* IMAGE_RESOURCE_DATA_ENTRY */
5945 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5946 size = mono_array_length (child->win32_res->res_data);
5947 data_entry.rde_size = GUINT32_TO_LE (size);
5949 memcpy (p, &data_entry, sizeof (data_entry));
5950 p += sizeof (data_entry);
5952 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5955 resource_tree_encode (child, begin, p, &p);
5959 /* IMAGE_RESOURCE_ENTRY */
5960 for (l = node->children; l; l = l->next) {
5961 ResTreeNode *child = (ResTreeNode*)l->data;
5963 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5964 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5966 memcpy (entries, &dir_entry, sizeof (dir_entry));
5967 entries += sizeof (dir_entry);
5974 resource_tree_free (ResTreeNode * node)
5977 for (list = node->children; list; list = list->next)
5978 resource_tree_free ((ResTreeNode*)list->data);
5979 g_slist_free(node->children);
5984 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5989 MonoReflectionWin32Resource *win32_res;
5992 if (!assemblyb->win32_resources)
5996 * Resources are stored in a three level tree inside the PE file.
5997 * - level one contains a node for each type of resource
5998 * - level two contains a node for each resource
5999 * - level three contains a node for each instance of a resource for a
6000 * specific language.
6003 tree = resource_tree_create (assemblyb->win32_resources);
6005 /* Estimate the size of the encoded tree */
6007 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6008 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6009 size += mono_array_length (win32_res->res_data);
6011 /* Directory structure */
6012 size += mono_array_length (assemblyb->win32_resources) * 256;
6013 p = buf = (char *)g_malloc (size);
6015 resource_tree_encode (tree, p, p, &p);
6017 g_assert (p - buf <= size);
6019 assembly->win32_res = (char *)g_malloc (p - buf);
6020 assembly->win32_res_size = p - buf;
6021 memcpy (assembly->win32_res, buf, p - buf);
6024 resource_tree_free (tree);
6028 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6030 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6033 p += sizeof (MonoPEResourceDir);
6034 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6035 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6036 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6037 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6038 fixup_resource_directory (res_section, child, rva);
6040 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6041 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6044 p += sizeof (MonoPEResourceDirEntry);
6049 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6052 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6053 g_error ("WriteFile returned %d\n", GetLastError ());
6057 * mono_image_create_pefile:
6058 * @mb: a module builder object
6060 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6061 * assembly->pefile where it can be easily retrieved later in chunks.
6064 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6066 MonoMSDOSHeader *msdos;
6067 MonoDotNetHeader *header;
6068 MonoSectionTable *section;
6069 MonoCLIHeader *cli_header;
6070 guint32 size, image_size, virtual_base, text_offset;
6071 guint32 header_start, section_start, file_offset, virtual_offset;
6072 MonoDynamicImage *assembly;
6073 MonoReflectionAssemblyBuilder *assemblyb;
6074 MonoDynamicStream pefile_stream = {0};
6075 MonoDynamicStream *pefile = &pefile_stream;
6077 guint32 *rva, value;
6079 static const unsigned char msheader[] = {
6080 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6081 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6084 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6085 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6086 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6087 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6090 mono_error_init (error);
6092 assemblyb = mb->assemblyb;
6094 mono_image_basic_init (assemblyb);
6095 assembly = mb->dynamic_image;
6097 assembly->pe_kind = assemblyb->pe_kind;
6098 assembly->machine = assemblyb->machine;
6099 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6100 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6102 if (!mono_image_build_metadata (mb, error))
6106 if (mb->is_main && assemblyb->resources) {
6107 int len = mono_array_length (assemblyb->resources);
6108 for (i = 0; i < len; ++i)
6109 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6112 if (mb->resources) {
6113 int len = mono_array_length (mb->resources);
6114 for (i = 0; i < len; ++i)
6115 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6118 if (!build_compressed_metadata (assembly, error))
6122 assembly_add_win32_resources (assembly, assemblyb);
6124 nsections = calc_section_size (assembly);
6126 /* The DOS header and stub */
6127 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6128 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6130 /* the dotnet header */
6131 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6133 /* the section tables */
6134 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6136 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6137 virtual_offset = VIRT_ALIGN;
6140 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6141 if (!assembly->sections [i].size)
6144 file_offset += FILE_ALIGN - 1;
6145 file_offset &= ~(FILE_ALIGN - 1);
6146 virtual_offset += VIRT_ALIGN - 1;
6147 virtual_offset &= ~(VIRT_ALIGN - 1);
6149 assembly->sections [i].offset = file_offset;
6150 assembly->sections [i].rva = virtual_offset;
6152 file_offset += assembly->sections [i].size;
6153 virtual_offset += assembly->sections [i].size;
6154 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6157 file_offset += FILE_ALIGN - 1;
6158 file_offset &= ~(FILE_ALIGN - 1);
6160 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6162 /* back-patch info */
6163 msdos = (MonoMSDOSHeader*)pefile->data;
6164 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6166 header = (MonoDotNetHeader*)(pefile->data + header_start);
6167 header->pesig [0] = 'P';
6168 header->pesig [1] = 'E';
6170 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6171 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6172 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6173 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6174 if (assemblyb->pekind == 1) {
6176 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6179 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6182 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6184 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6185 header->pe.pe_major = 6;
6186 header->pe.pe_minor = 0;
6187 size = assembly->sections [MONO_SECTION_TEXT].size;
6188 size += FILE_ALIGN - 1;
6189 size &= ~(FILE_ALIGN - 1);
6190 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6191 size = assembly->sections [MONO_SECTION_RSRC].size;
6192 size += FILE_ALIGN - 1;
6193 size &= ~(FILE_ALIGN - 1);
6194 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6195 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6196 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6197 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6198 /* pe_rva_entry_point always at the beginning of the text section */
6199 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6201 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6202 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6203 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6204 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6205 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6206 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6207 size = section_start;
6208 size += FILE_ALIGN - 1;
6209 size &= ~(FILE_ALIGN - 1);
6210 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6212 size += VIRT_ALIGN - 1;
6213 size &= ~(VIRT_ALIGN - 1);
6214 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6217 // Translate the PEFileKind value to the value expected by the Windows loader
6223 // PEFileKinds.Dll == 1
6224 // PEFileKinds.ConsoleApplication == 2
6225 // PEFileKinds.WindowApplication == 3
6228 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6229 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6231 if (assemblyb->pekind == 3)
6236 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6238 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6239 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6240 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6241 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6242 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6243 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6245 /* fill data directory entries */
6247 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6248 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6250 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6251 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6253 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6254 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6255 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6256 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6257 /* patch entrypoint name */
6258 if (assemblyb->pekind == 1)
6259 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6261 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6262 /* patch imported function RVA name */
6263 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6264 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6266 /* the import table */
6267 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6268 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6269 /* patch imported dll RVA name and other entries in the dir */
6270 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6271 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6272 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6273 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6274 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6275 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6277 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6278 value = (assembly->text_rva + assembly->imp_names_offset);
6279 *p++ = (value) & 0xff;
6280 *p++ = (value >> 8) & (0xff);
6281 *p++ = (value >> 16) & (0xff);
6282 *p++ = (value >> 24) & (0xff);
6284 /* the CLI header info */
6285 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6286 cli_header->ch_size = GUINT32_FROM_LE (72);
6287 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6288 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6289 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6290 if (assemblyb->entry_point) {
6291 guint32 table_idx = 0;
6292 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6293 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6294 table_idx = methodb->table_idx;
6296 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6298 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6300 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6302 /* The embedded managed resources */
6303 text_offset = assembly->text_rva + assembly->code.index;
6304 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6305 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6306 text_offset += assembly->resources.index;
6307 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6308 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6309 text_offset += assembly->meta_size;
6310 if (assembly->strong_name_size) {
6311 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6312 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6313 text_offset += assembly->strong_name_size;
6316 /* write the section tables and section content */
6317 section = (MonoSectionTable*)(pefile->data + section_start);
6318 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6319 static const char section_names [][7] = {
6320 ".text", ".rsrc", ".reloc"
6322 if (!assembly->sections [i].size)
6324 strcpy (section->st_name, section_names [i]);
6325 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6326 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6327 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6328 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6329 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6330 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6331 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6335 checked_write_file (file, pefile->data, pefile->index);
6337 mono_dynamic_stream_reset (pefile);
6339 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6340 if (!assembly->sections [i].size)
6343 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6344 g_error ("SetFilePointer returned %d\n", GetLastError ());
6347 case MONO_SECTION_TEXT:
6348 /* patch entry point */
6349 p = (guchar*)(assembly->code.data + 2);
6350 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6351 *p++ = (value) & 0xff;
6352 *p++ = (value >> 8) & 0xff;
6353 *p++ = (value >> 16) & 0xff;
6354 *p++ = (value >> 24) & 0xff;
6356 checked_write_file (file, assembly->code.data, assembly->code.index);
6357 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6358 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6359 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6362 g_free (assembly->image.raw_metadata);
6364 case MONO_SECTION_RELOC: {
6368 guint16 type_and_offset;
6372 g_assert (sizeof (reloc) == 12);
6374 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6375 reloc.block_size = GUINT32_FROM_LE (12);
6378 * the entrypoint is always at the start of the text section
6379 * 3 is IMAGE_REL_BASED_HIGHLOW
6380 * 2 is patch_size_rva - text_rva
6382 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6385 checked_write_file (file, &reloc, sizeof (reloc));
6389 case MONO_SECTION_RSRC:
6390 if (assembly->win32_res) {
6392 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6393 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6394 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6398 g_assert_not_reached ();
6402 /* check that the file is properly padded */
6403 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6404 g_error ("SetFilePointer returned %d\n", GetLastError ());
6405 if (! SetEndOfFile (file))
6406 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6408 mono_dynamic_stream_reset (&assembly->code);
6409 mono_dynamic_stream_reset (&assembly->us);
6410 mono_dynamic_stream_reset (&assembly->blob);
6411 mono_dynamic_stream_reset (&assembly->guid);
6412 mono_dynamic_stream_reset (&assembly->sheap);
6414 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6415 g_hash_table_destroy (assembly->blob_cache);
6416 assembly->blob_cache = NULL;
6421 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6424 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6426 g_assert_not_reached ();
6429 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6431 #ifndef DISABLE_REFLECTION_EMIT
6433 MonoReflectionModule *
6434 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6437 MonoReflectionModule *result = NULL;
6440 MonoImageOpenStatus status;
6441 MonoDynamicAssembly *assembly;
6442 guint32 module_count;
6443 MonoImage **new_modules;
6444 gboolean *new_modules_loaded;
6446 name = mono_string_to_utf8 (fileName);
6448 image = mono_image_open (name, &status);
6451 if (status == MONO_IMAGE_ERROR_ERRNO)
6452 exc = mono_get_exception_file_not_found (fileName);
6454 exc = mono_get_exception_bad_image_format (name);
6456 mono_raise_exception (exc);
6461 assembly = ab->dynamic_assembly;
6462 image->assembly = (MonoAssembly*)assembly;
6464 module_count = image->assembly->image->module_count;
6465 new_modules = g_new0 (MonoImage *, module_count + 1);
6466 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6468 if (image->assembly->image->modules)
6469 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6470 if (image->assembly->image->modules_loaded)
6471 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6472 new_modules [module_count] = image;
6473 new_modules_loaded [module_count] = TRUE;
6474 mono_image_addref (image);
6476 g_free (image->assembly->image->modules);
6477 image->assembly->image->modules = new_modules;
6478 image->assembly->image->modules_loaded = new_modules_loaded;
6479 image->assembly->image->module_count ++;
6481 mono_assembly_load_references (image, &status);
6483 mono_image_close (image);
6484 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6487 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6488 mono_error_raise_exception (&error); /* FIXME don't raise here */
6492 #endif /* DISABLE_REFLECTION_EMIT */
6495 * We need to return always the same object for MethodInfo, FieldInfo etc..
6496 * but we need to consider the reflected type.
6497 * type uses a different hash, since it uses custom hash/equal functions.
6502 MonoClass *refclass;
6506 reflected_equal (gconstpointer a, gconstpointer b) {
6507 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6508 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6510 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6514 reflected_hash (gconstpointer a) {
6515 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6516 return mono_aligned_addr_hash (ea->item);
6519 #define CHECK_OBJECT(t,p,k) \
6525 mono_domain_lock (domain); \
6526 if (!domain->refobject_hash) \
6527 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"); \
6528 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6529 mono_domain_unlock (domain); \
6532 mono_domain_unlock (domain); \
6535 #ifdef HAVE_BOEHM_GC
6536 /* ReflectedEntry doesn't need to be GC tracked */
6537 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6538 #define FREE_REFENTRY(entry) g_free ((entry))
6539 #define REFENTRY_REQUIRES_CLEANUP
6541 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6543 #define FREE_REFENTRY(entry)
6546 #define CACHE_OBJECT(t,p,o,k) \
6549 ReflectedEntry pe; \
6551 pe.refclass = (k); \
6552 mono_domain_lock (domain); \
6553 if (!domain->refobject_hash) \
6554 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"); \
6555 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6557 ReflectedEntry *e = ALLOC_REFENTRY; \
6559 e->refclass = (k); \
6560 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6563 mono_domain_unlock (domain); \
6568 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6570 mono_domain_lock (domain);
6571 if (domain->refobject_hash) {
6573 gpointer orig_pe, orig_value;
6576 pe.refclass = klass;
6577 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6578 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6579 FREE_REFENTRY (orig_pe);
6582 mono_domain_unlock (domain);
6585 #ifdef REFENTRY_REQUIRES_CLEANUP
6587 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6589 FREE_REFENTRY (key);
6594 mono_reflection_cleanup_domain (MonoDomain *domain)
6596 if (domain->refobject_hash) {
6597 /*let's avoid scanning the whole hashtable if not needed*/
6598 #ifdef REFENTRY_REQUIRES_CLEANUP
6599 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6601 mono_g_hash_table_destroy (domain->refobject_hash);
6602 domain->refobject_hash = NULL;
6606 #ifndef DISABLE_REFLECTION_EMIT
6608 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6610 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6614 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6616 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6620 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6622 MonoDynamicImage *image = moduleb->dynamic_image;
6623 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6627 MonoImage **new_modules;
6629 char *name, *fqname;
6631 * FIXME: we already created an image in mono_image_basic_init (), but
6632 * we don't know which module it belongs to, since that is only
6633 * determined at assembly save time.
6635 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6636 name = mono_string_to_utf8 (ab->name);
6637 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6638 if (!mono_error_ok (&error)) {
6640 mono_error_raise_exception (&error);
6642 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6644 moduleb->module.image = &image->image;
6645 moduleb->dynamic_image = image;
6646 register_module (mono_object_domain (moduleb), moduleb, image);
6648 /* register the module with the assembly */
6649 ass = ab->dynamic_assembly->assembly.image;
6650 module_count = ass->module_count;
6651 new_modules = g_new0 (MonoImage *, module_count + 1);
6654 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6655 new_modules [module_count] = &image->image;
6656 mono_image_addref (&image->image);
6658 g_free (ass->modules);
6659 ass->modules = new_modules;
6660 ass->module_count ++;
6665 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6667 MonoDynamicImage *image = moduleb->dynamic_image;
6669 g_assert (type->type);
6670 image->wrappers_type = mono_class_from_mono_type (type->type);
6676 * mono_assembly_get_object:
6677 * @domain: an app domain
6678 * @assembly: an assembly
6680 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6682 MonoReflectionAssembly*
6683 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6686 MonoReflectionAssembly *result;
6687 result = mono_assembly_get_object_checked (domain, assembly, &error);
6688 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6692 * mono_assembly_get_object_checked:
6693 * @domain: an app domain
6694 * @assembly: an assembly
6696 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6698 MonoReflectionAssembly*
6699 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6701 MonoReflectionAssembly *res;
6703 mono_error_init (error);
6705 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6706 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6709 res->assembly = assembly;
6711 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6716 MonoReflectionModule*
6717 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6720 MonoReflectionModule *result;
6721 result = mono_module_get_object_checked (domain, image, &error);
6722 mono_error_raise_exception (&error);
6726 MonoReflectionModule*
6727 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6729 MonoReflectionModule *res;
6732 mono_error_init (error);
6733 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6734 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6739 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6742 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6744 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6745 basename = g_path_get_basename (image->name);
6746 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6747 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6751 if (image->assembly->image == image) {
6752 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6756 if (image->assembly->image->modules) {
6757 for (i = 0; i < image->assembly->image->module_count; i++) {
6758 if (image->assembly->image->modules [i] == image)
6759 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6761 g_assert (res->token);
6765 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6768 MonoReflectionModule*
6769 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6772 MonoReflectionModule *result;
6773 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6774 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6778 MonoReflectionModule*
6779 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6781 MonoReflectionModule *res;
6782 MonoTableInfo *table;
6783 guint32 cols [MONO_FILE_SIZE];
6785 guint32 i, name_idx;
6788 mono_error_init (error);
6790 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6794 table = &image->tables [MONO_TABLE_FILE];
6795 g_assert (table_index < table->rows);
6796 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6799 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6802 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6805 /* Check whenever the row has a corresponding row in the moduleref table */
6806 table = &image->tables [MONO_TABLE_MODULEREF];
6807 for (i = 0; i < table->rows; ++i) {
6808 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809 val = mono_metadata_string_heap (image, name_idx);
6810 if (strcmp (val, name) == 0)
6811 res->image = image->modules [i];
6814 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6824 verify_safe_for_managed_space (MonoType *type)
6826 switch (type->type) {
6828 case MONO_TYPE_ARRAY:
6829 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6831 return verify_safe_for_managed_space (type->data.type);
6832 case MONO_TYPE_SZARRAY:
6833 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834 case MONO_TYPE_GENERICINST: {
6835 MonoGenericInst *inst = type->data.generic_class->inst;
6839 for (i = 0; i < inst->type_argc; ++i)
6840 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6846 case MONO_TYPE_MVAR:
6854 mono_type_normalize (MonoType *type)
6857 MonoGenericClass *gclass;
6858 MonoGenericInst *ginst;
6860 MonoGenericContainer *gcontainer;
6861 MonoType **argv = NULL;
6862 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6864 if (type->type != MONO_TYPE_GENERICINST)
6867 gclass = type->data.generic_class;
6868 ginst = gclass->context.class_inst;
6869 if (!ginst->is_open)
6872 gtd = gclass->container_class;
6873 gcontainer = gtd->generic_container;
6874 argv = g_newa (MonoType*, ginst->type_argc);
6876 for (i = 0; i < ginst->type_argc; ++i) {
6877 MonoType *t = ginst->type_argv [i], *norm;
6878 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879 is_denorm_gtd = FALSE;
6880 norm = mono_type_normalize (t);
6883 requires_rebind = TRUE;
6887 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6889 if (requires_rebind) {
6890 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6897 * mono_type_get_object:
6898 * @domain: an app domain
6901 * Return an System.MonoType object representing the type @type.
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6907 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908 mono_error_raise_exception (&error);
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6916 MonoType *norm_type;
6917 MonoReflectionType *res;
6920 mono_error_init (error);
6922 klass = mono_class_from_mono_type (type);
6924 /*we must avoid using @type as it might have come
6925 * from a mono_metadata_type_dup and the caller
6926 * expects that is can be freed.
6927 * Using the right type from
6929 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6931 /* void is very common */
6932 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933 return (MonoReflectionType*)domain->typeof_void;
6936 * If the vtable of the given class was already created, we can use
6937 * the MonoType from there and avoid all locking and hash table lookups.
6939 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940 * that the resulting object is different.
6942 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944 if (vtable && vtable->type)
6945 return (MonoReflectionType *)vtable->type;
6948 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949 mono_domain_lock (domain);
6950 if (!domain->type_hash)
6951 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6952 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954 mono_domain_unlock (domain);
6955 mono_loader_unlock ();
6959 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963 * artifact of how generics are encoded and should be transparent to managed code so we
6964 * need to weed out this diference when retrieving managed System.Type objects.
6966 norm_type = mono_type_normalize (type);
6967 if (norm_type != type) {
6968 res = mono_type_get_object_checked (domain, norm_type, error);
6969 if (!mono_error_ok (error))
6971 mono_g_hash_table_insert (domain->type_hash, type, res);
6972 mono_domain_unlock (domain);
6973 mono_loader_unlock ();
6977 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6981 if (!verify_safe_for_managed_space (type)) {
6982 mono_domain_unlock (domain);
6983 mono_loader_unlock ();
6984 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6988 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989 gboolean is_type_done = TRUE;
6990 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6994 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6997 if (gparam->owner && gparam->owner->is_method) {
6998 MonoMethod *method = gparam->owner->owner.method;
6999 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000 is_type_done = FALSE;
7001 } else if (gparam->owner && !gparam->owner->is_method) {
7002 MonoClass *klass = gparam->owner->owner.klass;
7003 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004 is_type_done = FALSE;
7008 /* g_assert_not_reached (); */
7009 /* should this be considered an error condition? */
7010 if (is_type_done && !type->byref) {
7011 mono_domain_unlock (domain);
7012 mono_loader_unlock ();
7013 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7016 /* This is stored in vtables/JITted code so it has to be pinned */
7017 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018 if (!mono_error_ok (error))
7022 mono_g_hash_table_insert (domain->type_hash, type, res);
7024 if (type->type == MONO_TYPE_VOID)
7025 domain->typeof_void = (MonoObject*)res;
7027 mono_domain_unlock (domain);
7028 mono_loader_unlock ();
7033 * mono_method_get_object:
7034 * @domain: an app domain
7036 * @refclass: the reflected type (can be NULL)
7038 * Return an System.Reflection.MonoMethod object representing the method @method.
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7044 MonoReflectionMethod *ret = NULL;
7045 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046 mono_error_raise_exception (&error);
7051 * mono_method_get_object_checked:
7052 * @domain: an app domain
7054 * @refclass: the reflected type (can be NULL)
7055 * @error: set on error.
7057 * Return an System.Reflection.MonoMethod object representing the method @method.
7058 * Returns NULL and sets @error on error.
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7064 * We use the same C representation for methods and constructors, but the type
7065 * name in C# is different.
7067 MonoReflectionType *rt;
7069 MonoReflectionMethod *ret;
7071 mono_error_init (error);
7073 if (method->is_inflated) {
7074 MonoReflectionGenericMethod *gret;
7077 refclass = method->klass;
7078 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7079 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7080 klass = mono_class_get_mono_generic_cmethod_class ();
7082 klass = mono_class_get_mono_generic_method_class ();
7084 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7085 if (!mono_error_ok (error))
7087 gret->method.method = method;
7089 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7091 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7092 if (!mono_error_ok (error))
7095 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7097 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7101 refclass = method->klass;
7103 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7104 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7105 klass = mono_class_get_mono_cmethod_class ();
7108 klass = mono_class_get_mono_method_class ();
7110 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7111 if (!mono_error_ok (error))
7113 ret->method = method;
7115 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7116 if (!mono_error_ok (error))
7119 MONO_OBJECT_SETREF (ret, reftype, rt);
7121 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7124 g_assert (!mono_error_ok (error));
7129 * mono_method_clear_object:
7131 * Clear the cached reflection objects for the dynamic method METHOD.
7134 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7137 g_assert (method_is_dynamic (method));
7139 klass = method->klass;
7141 clear_cached_object (domain, method, klass);
7142 klass = klass->parent;
7144 /* Added by mono_param_get_objects () */
7145 clear_cached_object (domain, &(method->signature), NULL);
7146 klass = method->klass;
7148 clear_cached_object (domain, &(method->signature), klass);
7149 klass = klass->parent;
7154 * mono_field_get_object:
7155 * @domain: an app domain
7159 * Return an System.Reflection.MonoField object representing the field @field
7162 MonoReflectionField*
7163 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7166 MonoReflectionField *result;
7167 result = mono_field_get_object_checked (domain, klass, field, &error);
7168 mono_error_raise_exception (&error);
7173 * mono_field_get_object_checked:
7174 * @domain: an app domain
7177 * @error: set on error
7179 * Return an System.Reflection.MonoField object representing the field @field
7180 * in class @klass. On error, returns NULL and sets @error.
7182 MonoReflectionField*
7183 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7185 MonoReflectionType *rt;
7186 MonoReflectionField *res;
7188 mono_error_init (error);
7190 CHECK_OBJECT (MonoReflectionField *, field, klass);
7191 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7196 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7198 if (is_field_on_inst (field)) {
7199 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7201 rt = mono_type_get_object_checked (domain, field->type, error);
7202 if (!mono_error_ok (error))
7205 MONO_OBJECT_SETREF (res, type, rt);
7208 rt = mono_type_get_object_checked (domain, field->type, error);
7209 if (!mono_error_ok (error))
7212 MONO_OBJECT_SETREF (res, type, rt);
7214 res->attrs = mono_field_get_flags (field);
7216 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7220 * mono_property_get_object:
7221 * @domain: an app domain
7223 * @property: a property
7225 * Return an System.Reflection.MonoProperty object representing the property @property
7228 MonoReflectionProperty*
7229 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7232 MonoReflectionProperty *result;
7233 result = mono_property_get_object_checked (domain, klass, property, &error);
7234 mono_error_raise_exception (&error);
7239 * mono_property_get_object:
7240 * @domain: an app domain
7242 * @property: a property
7243 * @error: set on error
7245 * Return an System.Reflection.MonoProperty object representing the property @property
7246 * in class @klass. On error returns NULL and sets @error.
7248 MonoReflectionProperty*
7249 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7251 MonoReflectionProperty *res;
7253 mono_error_init (error);
7255 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7256 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7260 res->property = property;
7261 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7265 * mono_event_get_object:
7266 * @domain: an app domain
7270 * Return an System.Reflection.MonoEvent object representing the event @event
7273 MonoReflectionEvent*
7274 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7277 MonoReflectionEvent *result;
7278 result = mono_event_get_object_checked (domain, klass, event, &error);
7279 mono_error_raise_exception (&error);
7284 * mono_event_get_object_checked:
7285 * @domain: an app domain
7288 * @error: set on error
7290 * Return an System.Reflection.MonoEvent object representing the event @event
7291 * in class @klass. On failure sets @error and returns NULL
7293 MonoReflectionEvent*
7294 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7296 MonoReflectionEvent *res;
7297 MonoReflectionMonoEvent *mono_event;
7299 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7300 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7303 mono_event->klass = klass;
7304 mono_event->event = event;
7305 res = (MonoReflectionEvent*)mono_event;
7306 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7310 * mono_get_reflection_missing_object:
7311 * @domain: Domain where the object lives
7313 * Returns the System.Reflection.Missing.Value singleton object
7314 * (of type System.Reflection.Missing).
7316 * Used as the value for ParameterInfo.DefaultValue when Optional
7320 mono_get_reflection_missing_object (MonoDomain *domain)
7323 static MonoClassField *missing_value_field = NULL;
7325 if (!missing_value_field) {
7326 MonoClass *missing_klass;
7327 missing_klass = mono_class_get_missing_class ();
7328 mono_class_init (missing_klass);
7329 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7330 g_assert (missing_value_field);
7332 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7338 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7341 *dbnull = mono_get_dbnull_object (domain);
7346 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7348 if (!*reflection_missing)
7349 *reflection_missing = mono_get_reflection_missing_object (domain);
7350 return *reflection_missing;
7354 * mono_param_get_objects:
7355 * @domain: an app domain
7358 * Return an System.Reflection.ParameterInfo array object representing the parameters
7359 * in the method @method.
7362 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7364 static MonoClass *System_Reflection_ParameterInfo;
7365 static MonoClass *System_Reflection_ParameterInfo_array;
7366 MonoArray *res = NULL;
7367 MonoReflectionMethod *member = NULL;
7368 MonoReflectionParameter *param = NULL;
7369 char **names = NULL, **blobs = NULL;
7370 guint32 *types = NULL;
7371 MonoType *type = NULL;
7372 MonoObject *dbnull = NULL;
7373 MonoObject *missing = NULL;
7374 MonoMarshalSpec **mspecs = NULL;
7375 MonoMethodSignature *sig = NULL;
7376 MonoVTable *pinfo_vtable;
7377 MonoReflectionType *rt;
7380 mono_error_init (error);
7382 if (!System_Reflection_ParameterInfo_array) {
7385 klass = mono_class_get_mono_parameter_info_class ();
7387 mono_memory_barrier ();
7388 System_Reflection_ParameterInfo = klass;
7391 klass = mono_array_class_get (klass, 1);
7392 mono_memory_barrier ();
7393 System_Reflection_ParameterInfo_array = klass;
7396 sig = mono_method_signature_checked (method, error);
7397 if (!mono_error_ok (error))
7400 if (!sig->param_count) {
7401 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7408 /* Note: the cache is based on the address of the signature into the method
7409 * since we already cache MethodInfos with the method as keys.
7411 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7413 member = mono_method_get_object_checked (domain, method, refclass, error);
7416 names = g_new (char *, sig->param_count);
7417 mono_method_get_param_names (method, (const char **) names);
7419 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7420 mono_method_get_marshal_info (method, mspecs);
7422 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7426 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7427 for (i = 0; i < sig->param_count; ++i) {
7428 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7432 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7436 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7438 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7440 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7442 param->PositionImpl = i;
7443 param->AttrsImpl = sig->params [i]->attrs;
7445 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7446 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7447 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7449 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7453 blobs = g_new0 (char *, sig->param_count);
7454 types = g_new0 (guint32, sig->param_count);
7455 get_default_param_value_blobs (method, blobs, types);
7458 /* Build MonoType for the type from the Constant Table */
7460 type = g_new0 (MonoType, 1);
7461 type->type = (MonoTypeEnum)types [i];
7462 type->data.klass = NULL;
7463 if (types [i] == MONO_TYPE_CLASS)
7464 type->data.klass = mono_defaults.object_class;
7465 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7466 /* For enums, types [i] contains the base type */
7468 type->type = MONO_TYPE_VALUETYPE;
7469 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7471 type->data.klass = mono_class_from_mono_type (type);
7473 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7476 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7478 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7479 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7480 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7481 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7483 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7488 if (mspecs [i + 1]) {
7489 MonoReflectionMarshalAsAttribute* mobj;
7490 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7493 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7496 mono_array_setref (res, i, param);
7506 for (i = sig->param_count; i >= 0; i--) {
7508 mono_metadata_free_marshal_spec (mspecs [i]);
7516 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7520 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7523 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7524 mono_error_assert_ok (&error);
7529 * mono_method_body_get_object:
7530 * @domain: an app domain
7533 * Return an System.Reflection.MethodBody object representing the method @method.
7535 MonoReflectionMethodBody*
7536 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7539 MonoReflectionMethodBody *ret;
7540 MonoMethodHeader *header;
7542 MonoReflectionType *rt;
7543 guint32 method_rva, local_var_sig_token;
7545 unsigned char format, flags;
7548 /* for compatibility with .net */
7549 if (method_is_dynamic (method))
7550 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7552 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7554 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7555 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7556 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7557 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7558 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7561 image = method->klass->image;
7562 header = mono_method_get_header (method);
7564 if (!image_is_dynamic (image)) {
7565 /* Obtain local vars signature token */
7566 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7567 ptr = mono_image_rva_map (image, method_rva);
7568 flags = *(const unsigned char *) ptr;
7569 format = flags & METHOD_HEADER_FORMAT_MASK;
7571 case METHOD_HEADER_TINY_FORMAT:
7572 local_var_sig_token = 0;
7574 case METHOD_HEADER_FAT_FORMAT:
7578 local_var_sig_token = read32 (ptr);
7581 g_assert_not_reached ();
7584 local_var_sig_token = 0; //FIXME
7586 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7587 mono_error_raise_exception (&error); /* FIXME don't raise here */
7589 ret->init_locals = header->init_locals;
7590 ret->max_stack = header->max_stack;
7591 ret->local_var_sig_token = local_var_sig_token;
7592 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7593 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7596 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7597 for (i = 0; i < header->num_locals; ++i) {
7598 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7599 mono_error_raise_exception (&error); /* FIXME don't raise here */
7601 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7602 mono_error_raise_exception (&error); /* FIXME don't raise here */
7604 MONO_OBJECT_SETREF (info, local_type, rt);
7606 info->is_pinned = header->locals [i]->pinned;
7607 info->local_index = i;
7608 mono_array_setref (ret->locals, i, info);
7612 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7613 for (i = 0; i < header->num_clauses; ++i) {
7614 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7615 mono_error_raise_exception (&error); /* FIXME don't raise here */
7616 MonoExceptionClause *clause = &header->clauses [i];
7618 info->flags = clause->flags;
7619 info->try_offset = clause->try_offset;
7620 info->try_length = clause->try_len;
7621 info->handler_offset = clause->handler_offset;
7622 info->handler_length = clause->handler_len;
7623 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7624 info->filter_offset = clause->data.filter_offset;
7625 else if (clause->data.catch_class) {
7626 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7627 mono_error_raise_exception (&error); /* FIXME don't raise here */
7629 MONO_OBJECT_SETREF (info, catch_type, rt);
7632 mono_array_setref (ret->clauses, i, info);
7635 mono_metadata_free_mh (header);
7636 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7641 * mono_get_dbnull_object:
7642 * @domain: Domain where the object lives
7644 * Returns the System.DBNull.Value singleton object
7646 * Used as the value for ParameterInfo.DefaultValue
7649 mono_get_dbnull_object (MonoDomain *domain)
7652 static MonoClassField *dbnull_value_field = NULL;
7654 if (!dbnull_value_field) {
7655 MonoClass *dbnull_klass;
7656 dbnull_klass = mono_class_get_dbnull_class ();
7657 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7658 g_assert (dbnull_value_field);
7660 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7666 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7668 guint32 param_index, i, lastp, crow = 0;
7669 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7672 MonoClass *klass = method->klass;
7673 MonoImage *image = klass->image;
7674 MonoMethodSignature *methodsig = mono_method_signature (method);
7676 MonoTableInfo *constt;
7677 MonoTableInfo *methodt;
7678 MonoTableInfo *paramt;
7680 if (!methodsig->param_count)
7683 mono_class_init (klass);
7685 if (image_is_dynamic (klass->image)) {
7686 MonoReflectionMethodAux *aux;
7687 if (method->is_inflated)
7688 method = ((MonoMethodInflated*)method)->declaring;
7689 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7690 if (aux && aux->param_defaults) {
7691 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7692 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7697 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7698 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7699 constt = &image->tables [MONO_TABLE_CONSTANT];
7701 idx = mono_method_get_index (method) - 1;
7702 g_assert (idx != -1);
7704 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7705 if (idx + 1 < methodt->rows)
7706 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7708 lastp = paramt->rows + 1;
7710 for (i = param_index; i < lastp; ++i) {
7713 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7714 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7716 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7719 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7724 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7725 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7726 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7733 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
7738 MonoType *basetype = type;
7740 mono_error_init (error);
7745 klass = mono_class_from_mono_type (type);
7746 if (klass->valuetype) {
7747 object = mono_object_new_checked (domain, klass, error);
7748 return_val_if_nok (error, NULL);
7749 retval = ((gchar *) object + sizeof (MonoObject));
7750 if (klass->enumtype)
7751 basetype = mono_class_enum_basetype (klass);
7756 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7763 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7766 gboolean quoted = FALSE;
7768 memset (assembly, 0, sizeof (MonoAssemblyName));
7769 assembly->culture = "";
7770 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7777 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7788 /* Remove trailing whitespace */
7790 while (*s && g_ascii_isspace (*s))
7793 while (g_ascii_isspace (*p))
7796 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7798 assembly->major = strtoul (p, &s, 10);
7799 if (s == p || *s != '.')
7802 assembly->minor = strtoul (p, &s, 10);
7803 if (s == p || *s != '.')
7806 assembly->build = strtoul (p, &s, 10);
7807 if (s == p || *s != '.')
7810 assembly->revision = strtoul (p, &s, 10);
7814 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7816 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7817 assembly->culture = "";
7820 assembly->culture = p;
7821 while (*p && *p != ',') {
7825 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7827 if (strncmp (p, "null", 4) == 0) {
7832 while (*p && *p != ',') {
7835 len = (p - start + 1);
7836 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7837 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7838 g_strlcpy ((char*)assembly->public_key_token, start, len);
7841 while (*p && *p != ',')
7845 while (g_ascii_isspace (*p) || *p == ',') {
7859 * mono_reflection_parse_type:
7862 * Parse a type name as accepted by the GetType () method and output the info
7863 * extracted in the info structure.
7864 * the name param will be mangled, so, make a copy before passing it to this function.
7865 * The fields in info will be valid until the memory pointed to by name is valid.
7867 * See also mono_type_get_name () below.
7869 * Returns: 0 on parse error.
7872 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7873 MonoTypeNameParse *info)
7875 char *start, *p, *w, *last_point, *startn;
7876 int in_modifiers = 0;
7877 int isbyref = 0, rank = 0, isptr = 0;
7879 start = p = w = name;
7881 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7882 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7883 info->name = info->name_space = NULL;
7884 info->nested = NULL;
7885 info->modifiers = NULL;
7886 info->type_arguments = NULL;
7888 /* last_point separates the namespace from the name */
7891 while (*p == ' ') p++, start++, w++, name++;
7896 *p = 0; /* NULL terminate the name */
7898 info->nested = g_list_append (info->nested, startn);
7899 /* we have parsed the nesting namespace + name */
7903 info->name_space = start;
7905 info->name = last_point + 1;
7907 info->name_space = (char *)"";
7935 info->name_space = start;
7937 info->name = last_point + 1;
7939 info->name_space = (char *)"";
7946 if (isbyref) /* only one level allowed by the spec */
7950 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7954 if (isbyref) /* pointer to ref not okay */
7956 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7961 if (isbyref) /* array of ref and generic ref are not okay */
7963 //Decide if it's an array of a generic argument list
7968 if (*p == ',' || *p == '*' || *p == ']') { //array
7976 else if (*p == '*') /* '*' means unknown lower bound */
7977 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7984 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7986 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7989 info->type_arguments = g_ptr_array_new ();
7991 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7992 gboolean fqname = FALSE;
7994 g_ptr_array_add (info->type_arguments, subinfo);
7996 while (*p == ' ') p++;
8002 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8005 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8006 if (fqname && (*p != ']')) {
8014 while (*p && (*p != ']'))
8022 if (g_ascii_isspace (*aname)) {
8029 !assembly_name_to_aname (&subinfo->assembly, aname))
8031 } else if (fqname && (*p == ']')) {
8053 if (g_ascii_isspace (*p)) {
8060 return 0; /* missing assembly name */
8061 if (!assembly_name_to_aname (&info->assembly, p))
8067 if (info->assembly.name)
8070 // *w = 0; /* terminate class name */
8072 if (!info->name || !*info->name)
8076 /* add other consistency checks */
8082 * mono_identifier_unescape_type_name_chars:
8083 * @identifier: the display name of a mono type
8086 * The name in internal form, that is without escaping backslashes.
8088 * The string is modified in place!
8091 mono_identifier_unescape_type_name_chars(char* identifier)
8096 for (w = r = identifier; *r != 0; r++)
8114 mono_identifier_unescape_info (MonoTypeNameParse* info);
8117 unescape_each_type_argument(void* data, void* user_data)
8119 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8120 mono_identifier_unescape_info (info);
8124 unescape_each_nested_name (void* data, void* user_data)
8126 char* nested_name = (char*) data;
8127 mono_identifier_unescape_type_name_chars(nested_name);
8131 * mono_identifier_unescape_info:
8133 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8137 * Destructively updates the info by unescaping the identifiers that
8138 * comprise the type namespace, name, nested types (if any) and
8139 * generic type arguments (if any).
8141 * The resulting info has the names in internal form.
8145 mono_identifier_unescape_info (MonoTypeNameParse *info)
8149 mono_identifier_unescape_type_name_chars(info->name_space);
8150 mono_identifier_unescape_type_name_chars(info->name);
8151 // but don't escape info->assembly
8152 if (info->type_arguments)
8153 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8155 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8159 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8161 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8163 mono_identifier_unescape_info (info);
8169 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8171 gboolean type_resolve = FALSE;
8173 MonoImage *rootimage = image;
8175 if (info->assembly.name) {
8176 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8177 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8179 * This could happen in the AOT compiler case when the search hook is not
8182 assembly = image->assembly;
8184 /* then we must load the assembly ourselve - see #60439 */
8185 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8189 image = assembly->image;
8190 } else if (!image) {
8191 image = mono_defaults.corlib;
8194 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8195 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8196 image = mono_defaults.corlib;
8197 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8204 * mono_reflection_get_type_internal:
8206 * Returns: may return NULL on success, sets error on failure.
8209 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8214 gboolean bounded = FALSE;
8216 mono_error_init (error);
8218 image = mono_defaults.corlib;
8221 rootimage = mono_defaults.corlib;
8224 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8226 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8231 for (mod = info->nested; mod; mod = mod->next) {
8232 gpointer iter = NULL;
8236 mono_class_init (parent);
8238 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8240 char *nested_name, *nested_nspace;
8241 gboolean match = TRUE;
8243 lastp = strrchr ((const char *)mod->data, '.');
8245 /* Nested classes can have namespaces */
8248 nested_name = g_strdup (lastp + 1);
8249 nspace_len = lastp - (char*)mod->data;
8250 nested_nspace = (char *)g_malloc (nspace_len + 1);
8251 memcpy (nested_nspace, mod->data, nspace_len);
8252 nested_nspace [nspace_len] = '\0';
8255 nested_name = (char *)mod->data;
8256 nested_nspace = NULL;
8259 if (nested_nspace) {
8261 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8264 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8270 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8273 if (strcmp (klass->name, nested_name) != 0)
8278 g_free (nested_name);
8279 g_free (nested_nspace);
8291 if (info->type_arguments) {
8292 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8293 MonoReflectionType *the_type;
8297 for (i = 0; i < info->type_arguments->len; i++) {
8298 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8300 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8301 if (!type_args [i]) {
8307 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8311 instance = mono_reflection_bind_generic_parameters (
8312 the_type, info->type_arguments->len, type_args);
8318 klass = mono_class_from_mono_type (instance);
8321 for (mod = info->modifiers; mod; mod = mod->next) {
8322 modval = GPOINTER_TO_UINT (mod->data);
8323 if (!modval) { /* byref: must be last modifier */
8324 return &klass->this_arg;
8325 } else if (modval == -1) {
8326 klass = mono_ptr_class_get (&klass->byval_arg);
8327 } else if (modval == -2) {
8329 } else { /* array rank */
8330 klass = mono_bounded_array_class_get (klass, modval, bounded);
8334 return &klass->byval_arg;
8338 * mono_reflection_get_type:
8339 * @image: a metadata context
8340 * @info: type description structure
8341 * @ignorecase: flag for case-insensitive string compares
8342 * @type_resolve: whenever type resolve was already tried
8344 * Build a MonoType from the type description in @info.
8349 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8350 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8354 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8356 MonoReflectionAssemblyBuilder *abuilder;
8360 mono_error_init (error);
8361 g_assert (assembly_is_dynamic (assembly));
8362 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8366 /* Enumerate all modules */
8369 if (abuilder->modules) {
8370 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8371 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8372 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8375 if (!mono_error_ok (error))
8380 if (!type && abuilder->loaded_modules) {
8381 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8382 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8383 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8386 if (!mono_error_ok (error))
8395 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8399 MonoReflectionAssembly *assembly;
8403 if (image && image_is_dynamic (image))
8404 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8406 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8408 if (!mono_error_ok (&error))
8409 mono_error_raise_exception (&error); /* FIXME don't raise here */
8413 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8420 *type_resolve = TRUE;
8423 /* Reconstruct the type name */
8424 fullName = g_string_new ("");
8425 if (info->name_space && (info->name_space [0] != '\0'))
8426 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8428 g_string_printf (fullName, "%s", info->name);
8429 for (mod = info->nested; mod; mod = mod->next)
8430 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8432 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8433 mono_error_raise_exception (&error); /* FIXME don't raise here */
8436 if (assembly_is_dynamic (assembly->assembly))
8437 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8438 info, ignorecase, &error);
8440 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8441 info, ignorecase, &error);
8443 g_string_free (fullName, TRUE);
8444 if (!mono_error_ok (&error))
8445 mono_error_raise_exception (&error); /* FIXME don't raise here */
8450 mono_reflection_free_type_info (MonoTypeNameParse *info)
8452 g_list_free (info->modifiers);
8453 g_list_free (info->nested);
8455 if (info->type_arguments) {
8458 for (i = 0; i < info->type_arguments->len; i++) {
8459 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8461 mono_reflection_free_type_info (subinfo);
8462 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8466 g_ptr_array_free (info->type_arguments, TRUE);
8471 * mono_reflection_type_from_name:
8473 * @image: a metadata context (can be NULL).
8475 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8476 * it defaults to get the type from @image or, if @image is NULL or loading
8477 * from it fails, uses corlib.
8481 mono_reflection_type_from_name (char *name, MonoImage *image)
8483 MonoType *type = NULL;
8484 MonoTypeNameParse info;
8487 /* Make a copy since parse_type modifies its argument */
8488 tmp = g_strdup (name);
8490 /*g_print ("requested type %s\n", str);*/
8491 if (mono_reflection_parse_type (tmp, &info)) {
8492 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8496 mono_reflection_free_type_info (&info);
8501 * mono_reflection_get_token:
8503 * Return the metadata token of OBJ which should be an object
8504 * representing a metadata element.
8507 mono_reflection_get_token (MonoObject *obj)
8512 klass = obj->vtable->klass;
8514 if (strcmp (klass->name, "MethodBuilder") == 0) {
8515 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8517 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8518 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8519 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8521 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8522 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8523 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8525 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8526 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8527 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8528 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8529 } else if (strcmp (klass->name, "MonoType") == 0) {
8530 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8531 MonoClass *mc = mono_class_from_mono_type (type);
8532 if (!mono_class_init (mc))
8533 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8535 token = mc->type_token;
8536 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8537 strcmp (klass->name, "MonoMethod") == 0 ||
8538 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8539 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8540 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8541 if (m->method->is_inflated) {
8542 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8543 return inflated->declaring->token;
8545 token = m->method->token;
8547 } else if (strcmp (klass->name, "MonoField") == 0) {
8548 MonoReflectionField *f = (MonoReflectionField*)obj;
8550 if (is_field_on_inst (f->field)) {
8551 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8553 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8554 int field_index = f->field - dgclass->fields;
8557 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8558 obj = dgclass->field_objects [field_index];
8559 return mono_reflection_get_token (obj);
8562 token = mono_class_get_field_token (f->field);
8563 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8564 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8566 token = mono_class_get_property_token (p->property);
8567 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8568 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8570 token = mono_class_get_event_token (p->event);
8571 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8572 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8573 MonoClass *member_class = mono_object_class (p->MemberImpl);
8574 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8576 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8577 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8578 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8581 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8582 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8584 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8585 MonoException *ex = mono_get_exception_not_implemented (msg);
8587 mono_raise_exception (ex);
8594 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8598 int slen = mono_metadata_decode_value (p, &p);
8600 mono_error_init (error);
8602 n = (char *)g_memdup (p, slen + 1);
8604 t = mono_reflection_type_from_name (n, image);
8606 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8607 /* We don't free n, it's consumed by mono_error */
8608 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8614 return mono_class_from_mono_type (t);
8618 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8620 int slen, type = t->type;
8621 MonoClass *tklass = t->data.klass;
8623 mono_error_init (error);
8629 case MONO_TYPE_BOOLEAN: {
8630 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8635 case MONO_TYPE_CHAR:
8637 case MONO_TYPE_I2: {
8638 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8643 #if SIZEOF_VOID_P == 4
8649 case MONO_TYPE_I4: {
8650 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8655 #if SIZEOF_VOID_P == 8
8656 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8660 case MONO_TYPE_I8: {
8661 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8666 case MONO_TYPE_R8: {
8667 double *val = (double *)g_malloc (sizeof (double));
8672 case MONO_TYPE_VALUETYPE:
8673 if (t->data.klass->enumtype) {
8674 type = mono_class_enum_basetype (t->data.klass)->type;
8677 MonoClass *k = t->data.klass;
8679 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8680 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8686 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8689 case MONO_TYPE_STRING:
8690 if (*p == (char)0xFF) {
8694 slen = mono_metadata_decode_value (p, &p);
8696 return mono_string_new_len (mono_domain_get (), p, slen);
8697 case MONO_TYPE_CLASS: {
8698 MonoReflectionType *rt;
8701 if (*p == (char)0xFF) {
8706 slen = mono_metadata_decode_value (p, &p);
8707 n = (char *)g_memdup (p, slen + 1);
8709 t = mono_reflection_type_from_name (n, image);
8711 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8712 /* We don't free n, it's consumed by mono_error */
8713 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8719 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8720 if (!mono_error_ok (error))
8725 case MONO_TYPE_OBJECT: {
8728 MonoClass *subc = NULL;
8733 } else if (subt == 0x0E) {
8734 type = MONO_TYPE_STRING;
8736 } else if (subt == 0x1D) {
8737 MonoType simple_type = {{0}};
8741 type = MONO_TYPE_SZARRAY;
8742 if (etype == 0x50) {
8743 tklass = mono_defaults.systemtype_class;
8744 } else if (etype == 0x55) {
8745 tklass = load_cattr_enum_type (image, p, &p, error);
8746 if (!mono_error_ok (error))
8750 /* See Partition II, Appendix B3 */
8751 etype = MONO_TYPE_OBJECT;
8752 simple_type.type = (MonoTypeEnum)etype;
8753 tklass = mono_class_from_mono_type (&simple_type);
8756 } else if (subt == 0x55) {
8759 slen = mono_metadata_decode_value (p, &p);
8760 n = (char *)g_memdup (p, slen + 1);
8762 t = mono_reflection_type_from_name (n, image);
8764 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8765 /* We don't free n, it's consumed by mono_error */
8766 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8771 subc = mono_class_from_mono_type (t);
8772 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8773 MonoType simple_type = {{0}};
8774 simple_type.type = (MonoTypeEnum)subt;
8775 subc = mono_class_from_mono_type (&simple_type);
8777 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8779 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8781 if (mono_error_ok (error)) {
8782 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8783 g_assert (!subc->has_references);
8784 if (mono_error_ok (error))
8785 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8791 case MONO_TYPE_SZARRAY: {
8793 guint32 i, alen, basetype;
8796 if (alen == 0xffffffff) {
8800 arr = mono_array_new (mono_domain_get(), tklass, alen);
8801 basetype = tklass->byval_arg.type;
8802 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8803 basetype = mono_class_enum_basetype (tklass)->type;
8808 case MONO_TYPE_BOOLEAN:
8809 for (i = 0; i < alen; i++) {
8810 MonoBoolean val = *p++;
8811 mono_array_set (arr, MonoBoolean, i, val);
8814 case MONO_TYPE_CHAR:
8817 for (i = 0; i < alen; i++) {
8818 guint16 val = read16 (p);
8819 mono_array_set (arr, guint16, i, val);
8826 for (i = 0; i < alen; i++) {
8827 guint32 val = read32 (p);
8828 mono_array_set (arr, guint32, i, val);
8833 for (i = 0; i < alen; i++) {
8836 mono_array_set (arr, double, i, val);
8842 for (i = 0; i < alen; i++) {
8843 guint64 val = read64 (p);
8844 mono_array_set (arr, guint64, i, val);
8848 case MONO_TYPE_CLASS:
8849 case MONO_TYPE_OBJECT:
8850 case MONO_TYPE_STRING:
8851 case MONO_TYPE_SZARRAY:
8852 for (i = 0; i < alen; i++) {
8853 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8854 if (!mono_error_ok (error))
8856 mono_array_setref (arr, i, item);
8860 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8866 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8872 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8874 static MonoMethod *ctor;
8876 void *params [2], *unboxed;
8878 mono_error_init (error);
8881 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8883 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8884 return_val_if_nok (error, NULL);
8887 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8888 return_val_if_nok (error, NULL);
8889 unboxed = mono_object_unbox (retval);
8891 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8892 return_val_if_nok (error, NULL);
8898 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8900 static MonoMethod *ctor;
8902 void *unboxed, *params [2];
8904 mono_error_init (error);
8907 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8910 params [1] = typedarg;
8911 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8912 return_val_if_nok (error, NULL);
8914 unboxed = mono_object_unbox (retval);
8916 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8917 return_val_if_nok (error, NULL);
8923 type_is_reference (MonoType *type)
8925 switch (type->type) {
8926 case MONO_TYPE_BOOLEAN:
8927 case MONO_TYPE_CHAR:
8940 case MONO_TYPE_VALUETYPE:
8948 free_param_data (MonoMethodSignature *sig, void **params) {
8950 for (i = 0; i < sig->param_count; ++i) {
8951 if (!type_is_reference (sig->params [i]))
8952 g_free (params [i]);
8957 * Find the field index in the metadata FieldDef table.
8960 find_field_index (MonoClass *klass, MonoClassField *field) {
8963 for (i = 0; i < klass->field.count; ++i) {
8964 if (field == &klass->fields [i])
8965 return klass->field.first + 1 + i;
8971 * Find the property index in the metadata Property table.
8974 find_property_index (MonoClass *klass, MonoProperty *property) {
8977 for (i = 0; i < klass->ext->property.count; ++i) {
8978 if (property == &klass->ext->properties [i])
8979 return klass->ext->property.first + 1 + i;
8985 * Find the event index in the metadata Event table.
8988 find_event_index (MonoClass *klass, MonoEvent *event) {
8991 for (i = 0; i < klass->ext->event.count; ++i) {
8992 if (event == &klass->ext->events [i])
8993 return klass->ext->event.first + 1 + i;
8999 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9001 const char *p = (const char*)data;
9003 guint32 i, j, num_named;
9005 void *params_buf [32];
9006 void **params = NULL;
9007 MonoMethodSignature *sig;
9008 MonoObject *exc = NULL;
9010 mono_error_init (error);
9012 mono_class_init (method->klass);
9014 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9015 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9020 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9021 if (!mono_error_ok (error)) return NULL;
9023 mono_runtime_invoke_checked (method, attr, NULL, error);
9024 if (!mono_error_ok (error))
9030 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9033 /*g_print ("got attr %s\n", method->klass->name);*/
9035 sig = mono_method_signature (method);
9036 if (sig->param_count < 32) {
9037 params = params_buf;
9038 memset (params, 0, sizeof (void*) * sig->param_count);
9040 /* Allocate using GC so it gets GC tracking */
9041 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9046 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9047 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9048 if (!mono_error_ok (error))
9053 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9054 if (!mono_error_ok (error)) goto fail;
9056 mono_runtime_try_invoke (method, attr, params, &exc, error);
9057 if (!mono_error_ok (error))
9062 num_named = read16 (named);
9064 for (j = 0; j < num_named; j++) {
9066 char *name, named_type, data_type;
9067 named_type = *named++;
9068 data_type = *named++; /* type of data */
9069 if (data_type == MONO_TYPE_SZARRAY)
9070 data_type = *named++;
9071 if (data_type == MONO_TYPE_ENUM) {
9074 type_len = mono_metadata_decode_blob_size (named, &named);
9075 type_name = (char *)g_malloc (type_len + 1);
9076 memcpy (type_name, named, type_len);
9077 type_name [type_len] = 0;
9079 /* FIXME: lookup the type and check type consistency */
9082 name_len = mono_metadata_decode_blob_size (named, &named);
9083 name = (char *)g_malloc (name_len + 1);
9084 memcpy (name, named, name_len);
9085 name [name_len] = 0;
9087 if (named_type == 0x53) {
9088 MonoClassField *field;
9091 /* how this fail is a blackbox */
9092 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9094 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9099 val = load_cattr_value (image, field->type, named, &named, error);
9100 if (!mono_error_ok (error)) {
9102 if (!type_is_reference (field->type))
9107 mono_field_set_value (attr, field, val);
9108 if (!type_is_reference (field->type))
9110 } else if (named_type == 0x54) {
9113 MonoType *prop_type;
9115 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9118 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9124 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9129 /* can we have more that 1 arg in a custom attr named property? */
9130 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9131 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9133 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9134 if (!mono_error_ok (error)) {
9136 if (!type_is_reference (prop_type))
9137 g_free (pparams [0]);
9142 mono_property_set_value (prop, attr, pparams, NULL);
9143 if (!type_is_reference (prop_type))
9144 g_free (pparams [0]);
9149 free_param_data (method->signature, params);
9150 if (params != params_buf)
9151 mono_gc_free_fixed (params);
9156 free_param_data (method->signature, params);
9157 if (params != params_buf)
9158 mono_gc_free_fixed (params);
9160 mono_raise_exception ((MonoException*)exc);
9165 * mono_reflection_create_custom_attr_data_args:
9167 * Create an array of typed and named arguments from the cattr blob given by DATA.
9168 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9169 * NAMED_ARG_INFO will contain information about the named arguments.
9172 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)
9174 MonoArray *typedargs, *namedargs;
9175 MonoClass *attrklass;
9177 const char *p = (const char*)data;
9179 guint32 i, j, num_named;
9180 CattrNamedArg *arginfo = NULL;
9184 *named_arg_info = NULL;
9186 mono_error_init (error);
9188 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9189 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9193 mono_class_init (method->klass);
9195 domain = mono_domain_get ();
9197 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9200 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9204 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9208 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9209 if (!mono_error_ok (error)) {
9210 if (!type_is_reference (mono_method_signature (method)->params [i]))
9215 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9216 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9217 mono_array_setref (typedargs, i, obj);
9219 if (!type_is_reference (mono_method_signature (method)->params [i]))
9224 num_named = read16 (named);
9225 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9227 attrklass = method->klass;
9229 arginfo = g_new0 (CattrNamedArg, num_named);
9230 *named_arg_info = arginfo;
9232 for (j = 0; j < num_named; j++) {
9234 char *name, named_type, data_type;
9235 named_type = *named++;
9236 data_type = *named++; /* type of data */
9237 if (data_type == MONO_TYPE_SZARRAY)
9238 data_type = *named++;
9239 if (data_type == MONO_TYPE_ENUM) {
9242 type_len = mono_metadata_decode_blob_size (named, &named);
9243 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9246 type_name = (char *)g_malloc (type_len + 1);
9247 memcpy (type_name, named, type_len);
9248 type_name [type_len] = 0;
9250 /* FIXME: lookup the type and check type consistency */
9253 name_len = mono_metadata_decode_blob_size (named, &named);
9254 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9256 name = (char *)g_malloc (name_len + 1);
9257 memcpy (name, named, name_len);
9258 name [name_len] = 0;
9260 if (named_type == 0x53) {
9262 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9270 arginfo [j].type = field->type;
9271 arginfo [j].field = field;
9273 val = load_cattr_value (image, field->type, named, &named, error);
9274 if (!mono_error_ok (error)) {
9275 if (!type_is_reference (field->type))
9281 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9282 mono_array_setref (namedargs, j, obj);
9283 if (!type_is_reference (field->type))
9285 } else if (named_type == 0x54) {
9287 MonoType *prop_type;
9288 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9291 if (!prop || !prop->set) {
9296 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9297 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9299 arginfo [j].type = prop_type;
9300 arginfo [j].prop = prop;
9302 val = load_cattr_value (image, prop_type, named, &named, error);
9303 if (!mono_error_ok (error)) {
9304 if (!type_is_reference (prop_type))
9310 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9311 mono_array_setref (namedargs, j, obj);
9312 if (!type_is_reference (prop_type))
9318 *typed_args = typedargs;
9319 *named_args = namedargs;
9322 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9324 *named_arg_info = NULL;
9328 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9331 MonoArray *typedargs, *namedargs;
9334 CattrNamedArg *arginfo = NULL;
9338 mono_error_init (&error);
9346 image = assembly->assembly->image;
9347 method = ref_method->method;
9348 domain = mono_object_domain (ref_method);
9350 if (!mono_class_init (method->klass))
9351 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9353 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9354 if (!mono_error_ok (&error))
9357 if (mono_loader_get_last_error ()) {
9358 mono_error_set_from_loader_error (&error);
9362 if (!typedargs || !namedargs)
9365 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9366 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9367 MonoObject *typedarg;
9369 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9370 if (!is_ok (&error))
9372 mono_array_setref (typedargs, i, typedarg);
9375 for (i = 0; i < mono_array_length (namedargs); ++i) {
9376 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9377 MonoObject *typedarg, *namedarg, *minfo;
9379 if (arginfo [i].prop) {
9380 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9384 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9385 if (!mono_error_ok (&error))
9389 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9390 if (!is_ok (&error))
9392 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9393 if (!is_ok (&error))
9396 mono_array_setref (namedargs, i, namedarg);
9399 *ctor_args = typedargs;
9400 *named_args = namedargs;
9403 mono_error_raise_exception (&error);
9408 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9410 static MonoMethod *ctor;
9416 mono_error_init (error);
9418 g_assert (image->assembly);
9421 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9423 domain = mono_domain_get ();
9424 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9425 return_val_if_nok (error, NULL);
9426 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9427 return_val_if_nok (error, NULL);
9428 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9429 return_val_if_nok (error, NULL);
9430 params [2] = (gpointer)&cattr->data;
9431 params [3] = &cattr->data_size;
9433 mono_runtime_invoke_checked (ctor, attr, params, error);
9434 return_val_if_nok (error, NULL);
9439 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9445 mono_error_init (error);
9448 for (i = 0; i < cinfo->num_attrs; ++i) {
9449 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9453 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9455 for (i = 0; i < cinfo->num_attrs; ++i) {
9456 if (!cinfo->attrs [i].ctor) {
9457 /* The cattr type is not finished yet */
9458 /* We should include the type name but cinfo doesn't contain it */
9459 mono_error_set_type_load_name (error, NULL, NULL, "");
9462 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9463 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9464 if (!mono_error_ok (error))
9466 mono_array_setref (result, n, attr);
9474 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9477 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9478 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9484 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9490 mono_error_init (error);
9491 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9492 for (i = 0; i < cinfo->num_attrs; ++i) {
9493 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9494 return_val_if_nok (error, NULL);
9495 mono_array_setref (result, i, attr);
9501 * mono_custom_attrs_from_index:
9503 * Returns: NULL if no attributes are found or if a loading error occurs.
9506 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9509 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9510 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9514 * mono_custom_attrs_from_index_checked:
9516 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9519 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9521 guint32 mtoken, i, len;
9522 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9524 MonoCustomAttrInfo *ainfo;
9525 GList *tmp, *list = NULL;
9527 MonoCustomAttrEntry* attr;
9529 mono_error_init (error);
9531 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9533 i = mono_metadata_custom_attrs_from_index (image, idx);
9537 while (i < ca->rows) {
9538 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9540 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9543 len = g_list_length (list);
9546 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9547 ainfo->num_attrs = len;
9548 ainfo->image = image;
9549 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9550 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9551 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9552 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9553 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9554 mtoken |= MONO_TOKEN_METHOD_DEF;
9556 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9557 mtoken |= MONO_TOKEN_MEMBER_REF;
9560 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9563 attr = &ainfo->attrs [i - 1];
9564 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9566 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9572 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9573 /*FIXME raising an exception here doesn't make any sense*/
9574 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9579 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9580 attr->data_size = mono_metadata_decode_value (data, &data);
9581 attr->data = (guchar*)data;
9589 mono_custom_attrs_from_method (MonoMethod *method)
9592 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9593 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9598 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9602 mono_error_init (error);
9605 * An instantiated method has the same cattrs as the generic method definition.
9607 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9608 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9610 if (method->is_inflated)
9611 method = ((MonoMethodInflated *) method)->declaring;
9613 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9614 return lookup_custom_attr (method->klass->image, method);
9617 /* Synthetic methods */
9620 idx = mono_method_get_index (method);
9621 idx <<= MONO_CUSTOM_ATTR_BITS;
9622 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9623 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9627 mono_custom_attrs_from_class (MonoClass *klass)
9630 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9631 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9636 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9640 mono_error_init (error);
9642 if (klass->generic_class)
9643 klass = klass->generic_class->container_class;
9645 if (image_is_dynamic (klass->image))
9646 return lookup_custom_attr (klass->image, klass);
9648 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9649 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9650 idx <<= MONO_CUSTOM_ATTR_BITS;
9651 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9653 idx = mono_metadata_token_index (klass->type_token);
9654 idx <<= MONO_CUSTOM_ATTR_BITS;
9655 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9657 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9661 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9664 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9665 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9670 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9674 mono_error_init (error);
9676 if (image_is_dynamic (assembly->image))
9677 return lookup_custom_attr (assembly->image, assembly);
9678 idx = 1; /* there is only one assembly */
9679 idx <<= MONO_CUSTOM_ATTR_BITS;
9680 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9681 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9684 static MonoCustomAttrInfo*
9685 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9689 if (image_is_dynamic (image))
9690 return lookup_custom_attr (image, image);
9691 idx = 1; /* there is only one module */
9692 idx <<= MONO_CUSTOM_ATTR_BITS;
9693 idx |= MONO_CUSTOM_ATTR_MODULE;
9694 return mono_custom_attrs_from_index_checked (image, idx, error);
9698 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9701 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9702 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9707 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9711 if (image_is_dynamic (klass->image)) {
9712 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9713 return lookup_custom_attr (klass->image, property);
9715 idx = find_property_index (klass, property);
9716 idx <<= MONO_CUSTOM_ATTR_BITS;
9717 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9718 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9722 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9725 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9726 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9731 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9735 if (image_is_dynamic (klass->image)) {
9736 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9737 return lookup_custom_attr (klass->image, event);
9739 idx = find_event_index (klass, event);
9740 idx <<= MONO_CUSTOM_ATTR_BITS;
9741 idx |= MONO_CUSTOM_ATTR_EVENT;
9742 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9746 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9749 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9750 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9755 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9758 mono_error_init (error);
9760 if (image_is_dynamic (klass->image)) {
9761 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9762 return lookup_custom_attr (klass->image, field);
9764 idx = find_field_index (klass, field);
9765 idx <<= MONO_CUSTOM_ATTR_BITS;
9766 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9767 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9771 * mono_custom_attrs_from_param:
9772 * @method: handle to the method that we want to retrieve custom parameter information from
9773 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9775 * The result must be released with mono_custom_attrs_free().
9777 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9780 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9783 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9784 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9789 * mono_custom_attrs_from_param_checked:
9790 * @method: handle to the method that we want to retrieve custom parameter information from
9791 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9792 * @error: set on error
9794 * The result must be released with mono_custom_attrs_free().
9796 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9799 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9802 guint32 i, idx, method_index;
9803 guint32 param_list, param_last, param_pos, found;
9805 MonoReflectionMethodAux *aux;
9807 mono_error_init (error);
9810 * An instantiated method has the same cattrs as the generic method definition.
9812 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9813 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9815 if (method->is_inflated)
9816 method = ((MonoMethodInflated *) method)->declaring;
9818 if (image_is_dynamic (method->klass->image)) {
9819 MonoCustomAttrInfo *res, *ainfo;
9822 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9823 if (!aux || !aux->param_cattr)
9826 /* Need to copy since it will be freed later */
9827 ainfo = aux->param_cattr [param];
9830 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9831 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9832 memcpy (res, ainfo, size);
9836 image = method->klass->image;
9837 method_index = mono_method_get_index (method);
9840 ca = &image->tables [MONO_TABLE_METHOD];
9842 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9843 if (method_index == ca->rows) {
9844 ca = &image->tables [MONO_TABLE_PARAM];
9845 param_last = ca->rows + 1;
9847 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9848 ca = &image->tables [MONO_TABLE_PARAM];
9851 for (i = param_list; i < param_last; ++i) {
9852 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9853 if (param_pos == param) {
9861 idx <<= MONO_CUSTOM_ATTR_BITS;
9862 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9863 return mono_custom_attrs_from_index_checked (image, idx, error);
9867 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9871 for (i = 0; i < ainfo->num_attrs; ++i) {
9872 klass = ainfo->attrs [i].ctor->klass;
9873 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9880 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9883 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9884 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9889 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9895 mono_error_init (error);
9898 for (i = 0; i < ainfo->num_attrs; ++i) {
9899 klass = ainfo->attrs [i].ctor->klass;
9900 if (mono_class_has_parent (klass, attr_klass)) {
9905 if (attr_index == -1)
9908 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9909 if (!mono_error_ok (error))
9911 return mono_array_get (attrs, MonoObject*, attr_index);
9915 * mono_reflection_get_custom_attrs_info:
9916 * @obj: a reflection object handle
9918 * Return the custom attribute info for attributes defined for the
9919 * reflection handle @obj. The objects.
9921 * FIXME this function leaks like a sieve for SRE objects.
9924 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9927 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9928 mono_error_assert_ok (&error);
9933 * mono_reflection_get_custom_attrs_info_checked:
9934 * @obj: a reflection object handle
9935 * @error: set on error
9937 * Return the custom attribute info for attributes defined for the
9938 * reflection handle @obj. The objects.
9940 * On failure returns NULL and sets @error.
9942 * FIXME this function leaks like a sieve for SRE objects.
9945 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9948 MonoCustomAttrInfo *cinfo = NULL;
9950 mono_error_init (error);
9952 klass = obj->vtable->klass;
9953 if (klass == mono_defaults.monotype_class) {
9954 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9955 klass = mono_class_from_mono_type (type);
9956 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9957 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9958 return_val_if_nok (error, NULL);
9959 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9960 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9961 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9962 return_val_if_nok (error, NULL);
9963 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9964 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9965 cinfo = mono_custom_attrs_from_module (module->image, error);
9966 return_val_if_nok (error, NULL);
9967 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9968 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9969 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9970 return_val_if_nok (error, NULL);
9971 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9972 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9973 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9974 return_val_if_nok (error, NULL);
9975 } else if (strcmp ("MonoField", klass->name) == 0) {
9976 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9977 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9978 return_val_if_nok (error, NULL);
9979 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9980 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9981 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9982 return_val_if_nok (error, NULL);
9983 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9984 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9985 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9986 return_val_if_nok (error, NULL);
9987 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9988 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9989 MonoClass *member_class = mono_object_class (param->MemberImpl);
9990 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9991 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9992 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
9993 return_val_if_nok (error, NULL);
9994 } else if (is_sr_mono_property (member_class)) {
9995 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9997 if (!(method = prop->property->get))
9998 method = prop->property->set;
10001 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10002 return_val_if_nok (error, NULL);
10004 #ifndef DISABLE_REFLECTION_EMIT
10005 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10006 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10007 return_val_if_nok (error, NULL);
10008 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10009 return_val_if_nok (error, NULL);
10010 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10011 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10012 MonoMethod *method = NULL;
10013 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10014 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10015 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10016 method = ((MonoReflectionMethod *)c->cb)->method;
10018 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));
10020 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10021 return_val_if_nok (error, NULL);
10025 char *type_name = mono_type_get_full_name (member_class);
10026 mono_error_set_generic_error (error, "System", "NotSupportedException",
10027 "Custom attributes on a ParamInfo with member %s are not supported",
10029 g_free (type_name);
10032 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10033 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10034 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10035 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10036 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10037 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10038 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10039 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10040 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10041 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10042 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10043 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10044 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10045 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10046 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10047 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10048 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10049 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10050 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10051 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10052 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10053 return_val_if_nok (error, NULL);
10054 } else { /* handle other types here... */
10055 g_error ("get custom attrs not yet supported for %s", klass->name);
10062 * mono_reflection_get_custom_attrs_by_type:
10063 * @obj: a reflection object handle
10065 * Return an array with all the custom attributes defined of the
10066 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10067 * of that type are returned. The objects are fully build. Return NULL if a loading error
10071 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10074 MonoCustomAttrInfo *cinfo;
10076 mono_error_init (error);
10078 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10079 return_val_if_nok (error, NULL);
10081 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10084 if (!cinfo->cached)
10085 mono_custom_attrs_free (cinfo);
10087 mono_loader_assert_no_error ();
10088 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10095 * mono_reflection_get_custom_attrs:
10096 * @obj: a reflection object handle
10098 * Return an array with all the custom attributes defined of the
10099 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10103 mono_reflection_get_custom_attrs (MonoObject *obj)
10107 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10111 * mono_reflection_get_custom_attrs_data:
10112 * @obj: a reflection obj handle
10114 * Returns an array of System.Reflection.CustomAttributeData,
10115 * which include information about attributes reflected on
10116 * types loaded using the Reflection Only methods
10119 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10123 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10124 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10129 * mono_reflection_get_custom_attrs_data_checked:
10130 * @obj: a reflection obj handle
10131 * @error: set on error
10133 * Returns an array of System.Reflection.CustomAttributeData,
10134 * which include information about attributes reflected on
10135 * types loaded using the Reflection Only methods
10138 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10141 MonoCustomAttrInfo *cinfo;
10143 mono_error_init (error);
10145 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10146 return_val_if_nok (error, NULL);
10148 result = mono_custom_attrs_data_construct (cinfo, error);
10149 return_val_if_nok (error, NULL);
10150 if (!cinfo->cached)
10151 mono_custom_attrs_free (cinfo);
10153 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10155 if (mono_loader_get_last_error ())
10156 mono_error_set_from_loader_error (error);
10161 static MonoReflectionType*
10162 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10164 static MonoMethod *method_get_underlying_system_type = NULL;
10165 MonoReflectionType *rt;
10166 MonoMethod *usertype_method;
10168 mono_error_init (error);
10170 if (!method_get_underlying_system_type)
10171 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10173 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10175 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10182 is_corlib_type (MonoClass *klass)
10184 return klass->image == mono_defaults.corlib;
10187 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10188 static MonoClass *cached_class; \
10189 if (cached_class) \
10190 return cached_class == _class; \
10191 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10192 cached_class = _class; \
10199 #ifndef DISABLE_REFLECTION_EMIT
10201 is_sre_array (MonoClass *klass)
10203 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10207 is_sre_byref (MonoClass *klass)
10209 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10213 is_sre_pointer (MonoClass *klass)
10215 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10219 is_sre_generic_instance (MonoClass *klass)
10221 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10225 is_sre_type_builder (MonoClass *klass)
10227 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10231 is_sre_method_builder (MonoClass *klass)
10233 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10237 is_sre_ctor_builder (MonoClass *klass)
10239 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10243 is_sre_field_builder (MonoClass *klass)
10245 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10249 is_sre_method_on_tb_inst (MonoClass *klass)
10251 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10255 is_sre_ctor_on_tb_inst (MonoClass *klass)
10257 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10261 mono_reflection_type_get_handle (MonoReflectionType* ref)
10270 if (is_usertype (ref)) {
10271 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10272 mono_error_raise_exception (&error); /* FIXME don't raise here */
10273 if (ref == NULL || is_usertype (ref))
10279 klass = mono_object_class (ref);
10281 if (is_sre_array (klass)) {
10283 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10284 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10286 if (sre_array->rank == 0) //single dimentional array
10287 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10289 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10290 sre_array->type.type = res;
10292 } else if (is_sre_byref (klass)) {
10294 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10295 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10297 res = &mono_class_from_mono_type (base)->this_arg;
10298 sre_byref->type.type = res;
10300 } else if (is_sre_pointer (klass)) {
10302 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10303 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10305 res = &mono_ptr_class_get (base)->byval_arg;
10306 sre_pointer->type.type = res;
10308 } else if (is_sre_generic_instance (klass)) {
10309 MonoType *res, **types;
10310 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10313 count = mono_array_length (gclass->type_arguments);
10314 types = g_new0 (MonoType*, count);
10315 for (i = 0; i < count; ++i) {
10316 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10317 types [i] = mono_reflection_type_get_handle (t);
10324 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10327 gclass->type.type = res;
10331 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10338 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10340 mono_reflection_type_get_handle (type);
10344 mono_reflection_register_with_runtime (MonoReflectionType *type)
10346 MonoType *res = mono_reflection_type_get_handle (type);
10347 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10351 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10353 klass = mono_class_from_mono_type (res);
10355 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10356 mono_domain_lock (domain);
10358 if (!image_is_dynamic (klass->image)) {
10359 mono_class_setup_supertypes (klass);
10361 if (!domain->type_hash)
10362 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10363 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10364 mono_g_hash_table_insert (domain->type_hash, res, type);
10366 mono_domain_unlock (domain);
10367 mono_loader_unlock ();
10371 * LOCKING: Assumes the loader lock is held.
10373 static MonoMethodSignature*
10374 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10375 MonoMethodSignature *sig;
10378 count = parameters? mono_array_length (parameters): 0;
10380 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10381 sig->param_count = count;
10382 sig->sentinelpos = -1; /* FIXME */
10383 for (i = 0; i < count; ++i)
10384 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10389 * LOCKING: Assumes the loader lock is held.
10391 static MonoMethodSignature*
10392 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10393 MonoMethodSignature *sig;
10395 sig = parameters_to_signature (image, ctor->parameters);
10396 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10397 sig->ret = &mono_defaults.void_class->byval_arg;
10402 * LOCKING: Assumes the loader lock is held.
10404 static MonoMethodSignature*
10405 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10406 MonoMethodSignature *sig;
10408 sig = parameters_to_signature (image, method->parameters);
10409 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10410 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10411 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10415 static MonoMethodSignature*
10416 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10417 MonoMethodSignature *sig;
10419 sig = parameters_to_signature (NULL, method->parameters);
10420 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10421 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10422 sig->generic_param_count = 0;
10427 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10429 MonoClass *klass = mono_object_class (prop);
10430 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10431 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10432 *name = mono_string_to_utf8 (pb->name);
10433 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10435 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10436 *name = g_strdup (p->property->name);
10437 if (p->property->get)
10438 *type = mono_method_signature (p->property->get)->ret;
10440 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10445 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10447 MonoClass *klass = mono_object_class (field);
10448 if (strcmp (klass->name, "FieldBuilder") == 0) {
10449 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10450 *name = mono_string_to_utf8 (fb->name);
10451 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10453 MonoReflectionField *f = (MonoReflectionField *)field;
10454 *name = g_strdup (mono_field_get_name (f->field));
10455 *type = f->field->type;
10459 #else /* DISABLE_REFLECTION_EMIT */
10462 mono_reflection_register_with_runtime (MonoReflectionType *type)
10464 /* This is empty */
10468 is_sre_type_builder (MonoClass *klass)
10474 is_sre_generic_instance (MonoClass *klass)
10480 init_type_builder_generics (MonoObject *type)
10484 #endif /* !DISABLE_REFLECTION_EMIT */
10488 is_sr_mono_field (MonoClass *klass)
10490 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10494 is_sr_mono_property (MonoClass *klass)
10496 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10500 is_sr_mono_method (MonoClass *klass)
10502 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10506 is_sr_mono_cmethod (MonoClass *klass)
10508 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10512 is_sr_mono_generic_method (MonoClass *klass)
10514 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10518 is_sr_mono_generic_cmethod (MonoClass *klass)
10520 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10524 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10526 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10530 is_usertype (MonoReflectionType *ref)
10532 MonoClass *klass = mono_object_class (ref);
10533 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10536 static MonoReflectionType*
10537 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10539 mono_error_init (error);
10540 if (!type || type->type)
10543 if (is_usertype (type)) {
10544 type = mono_reflection_type_get_underlying_system_type (type, error);
10545 return_val_if_nok (error, NULL);
10546 if (is_usertype (type)) {
10547 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10555 * Encode a value in a custom attribute stream of bytes.
10556 * The value to encode is either supplied as an object in argument val
10557 * (valuetypes are boxed), or as a pointer to the data in the
10559 * @type represents the type of the value
10560 * @buffer is the start of the buffer
10561 * @p the current position in the buffer
10562 * @buflen contains the size of the buffer and is used to return the new buffer size
10563 * if this needs to be realloced.
10564 * @retbuffer and @retp return the start and the position of the buffer
10567 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10569 MonoTypeEnum simple_type;
10571 if ((p-buffer) + 10 >= *buflen) {
10574 newbuf = (char *)g_realloc (buffer, *buflen);
10575 p = newbuf + (p-buffer);
10579 argval = ((char*)arg + sizeof (MonoObject));
10580 simple_type = type->type;
10582 switch (simple_type) {
10583 case MONO_TYPE_BOOLEAN:
10588 case MONO_TYPE_CHAR:
10591 swap_with_size (p, argval, 2, 1);
10597 swap_with_size (p, argval, 4, 1);
10601 swap_with_size (p, argval, 8, 1);
10606 swap_with_size (p, argval, 8, 1);
10609 case MONO_TYPE_VALUETYPE:
10610 if (type->data.klass->enumtype) {
10611 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10614 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10617 case MONO_TYPE_STRING: {
10624 str = mono_string_to_utf8 ((MonoString*)arg);
10625 slen = strlen (str);
10626 if ((p-buffer) + 10 + slen >= *buflen) {
10630 newbuf = (char *)g_realloc (buffer, *buflen);
10631 p = newbuf + (p-buffer);
10634 mono_metadata_encode_value (slen, p, &p);
10635 memcpy (p, str, slen);
10640 case MONO_TYPE_CLASS: {
10648 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10649 slen = strlen (str);
10650 if ((p-buffer) + 10 + slen >= *buflen) {
10654 newbuf = (char *)g_realloc (buffer, *buflen);
10655 p = newbuf + (p-buffer);
10658 mono_metadata_encode_value (slen, p, &p);
10659 memcpy (p, str, slen);
10664 case MONO_TYPE_SZARRAY: {
10666 MonoClass *eclass, *arg_eclass;
10669 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10672 len = mono_array_length ((MonoArray*)arg);
10674 *p++ = (len >> 8) & 0xff;
10675 *p++ = (len >> 16) & 0xff;
10676 *p++ = (len >> 24) & 0xff;
10678 *retbuffer = buffer;
10679 eclass = type->data.klass;
10680 arg_eclass = mono_object_class (arg)->element_class;
10683 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10684 eclass = mono_defaults.object_class;
10686 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10687 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10688 int elsize = mono_class_array_element_size (arg_eclass);
10689 for (i = 0; i < len; ++i) {
10690 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10693 } else if (eclass->valuetype && arg_eclass->valuetype) {
10694 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10695 int elsize = mono_class_array_element_size (eclass);
10696 for (i = 0; i < len; ++i) {
10697 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10701 for (i = 0; i < len; ++i) {
10702 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10707 case MONO_TYPE_OBJECT: {
10713 * The parameter type is 'object' but the type of the actual
10714 * argument is not. So we have to add type information to the blob
10715 * too. This is completely undocumented in the spec.
10719 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10724 klass = mono_object_class (arg);
10726 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10729 } else if (klass->enumtype) {
10731 } else if (klass == mono_defaults.string_class) {
10732 simple_type = MONO_TYPE_STRING;
10735 } else if (klass->rank == 1) {
10737 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10738 /* See Partition II, Appendix B3 */
10741 *p++ = klass->element_class->byval_arg.type;
10742 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10744 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10745 *p++ = simple_type = klass->byval_arg.type;
10748 g_error ("unhandled type in custom attr");
10750 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10751 slen = strlen (str);
10752 if ((p-buffer) + 10 + slen >= *buflen) {
10756 newbuf = (char *)g_realloc (buffer, *buflen);
10757 p = newbuf + (p-buffer);
10760 mono_metadata_encode_value (slen, p, &p);
10761 memcpy (p, str, slen);
10764 simple_type = mono_class_enum_basetype (klass)->type;
10768 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10771 *retbuffer = buffer;
10775 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10777 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10778 char *str = type_get_qualified_name (type, NULL);
10779 int slen = strlen (str);
10783 * This seems to be optional...
10786 mono_metadata_encode_value (slen, p, &p);
10787 memcpy (p, str, slen);
10790 } else if (type->type == MONO_TYPE_OBJECT) {
10792 } else if (type->type == MONO_TYPE_CLASS) {
10793 /* it should be a type: encode_cattr_value () has the check */
10796 mono_metadata_encode_value (type->type, p, &p);
10797 if (type->type == MONO_TYPE_SZARRAY)
10798 /* See the examples in Partition VI, Annex B */
10799 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10805 #ifndef DISABLE_REFLECTION_EMIT
10807 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10810 /* Preallocate a large enough buffer */
10811 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10812 char *str = type_get_qualified_name (type, NULL);
10813 len = strlen (str);
10815 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10816 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10817 len = strlen (str);
10822 len += strlen (name);
10824 if ((p-buffer) + 20 + len >= *buflen) {
10828 newbuf = (char *)g_realloc (buffer, *buflen);
10829 p = newbuf + (p-buffer);
10833 encode_field_or_prop_type (type, p, &p);
10835 len = strlen (name);
10836 mono_metadata_encode_value (len, p, &p);
10837 memcpy (p, name, len);
10839 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10841 *retbuffer = buffer;
10845 * mono_reflection_get_custom_attrs_blob:
10846 * @ctor: custom attribute constructor
10847 * @ctorArgs: arguments o the constructor
10853 * Creates the blob of data that needs to be saved in the metadata and that represents
10854 * the custom attributed described by @ctor, @ctorArgs etc.
10855 * Returns: a Byte array representing the blob of data.
10858 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10861 MonoMethodSignature *sig;
10866 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10867 /* sig is freed later so allocate it in the heap */
10868 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10870 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10873 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10875 p = buffer = (char *)g_malloc (buflen);
10876 /* write the prolog */
10879 for (i = 0; i < sig->param_count; ++i) {
10880 arg = mono_array_get (ctorArgs, MonoObject*, i);
10881 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10885 i += mono_array_length (properties);
10887 i += mono_array_length (fields);
10889 *p++ = (i >> 8) & 0xff;
10892 for (i = 0; i < mono_array_length (properties); ++i) {
10896 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10897 get_prop_name_and_type (prop, &pname, &ptype);
10898 *p++ = 0x54; /* PROPERTY signature */
10899 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10906 for (i = 0; i < mono_array_length (fields); ++i) {
10910 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10911 get_field_name_and_type (field, &fname, &ftype);
10912 *p++ = 0x53; /* FIELD signature */
10913 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10918 g_assert (p - buffer <= buflen);
10919 buflen = p - buffer;
10920 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10921 p = mono_array_addr (result, char, 0);
10922 memcpy (p, buffer, buflen);
10924 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10930 * mono_reflection_setup_internal_class:
10931 * @tb: a TypeBuilder object
10933 * Creates a MonoClass that represents the TypeBuilder.
10934 * This is a trick that lets us simplify a lot of reflection code
10935 * (and will allow us to support Build and Run assemblies easier).
10938 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10941 MonoClass *klass, *parent;
10943 RESOLVE_TYPE (tb->parent, &error);
10944 mono_error_raise_exception (&error); /* FIXME don't raise here */
10946 mono_loader_lock ();
10949 /* check so we can compile corlib correctly */
10950 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10951 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10952 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10954 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10960 /* the type has already being created: it means we just have to change the parent */
10961 if (tb->type.type) {
10962 klass = mono_class_from_mono_type (tb->type.type);
10963 klass->parent = NULL;
10964 /* fool mono_class_setup_parent */
10965 klass->supertypes = NULL;
10966 mono_class_setup_parent (klass, parent);
10967 mono_class_setup_mono_type (klass);
10968 mono_loader_unlock ();
10972 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10974 klass->image = &tb->module->dynamic_image->image;
10976 klass->inited = 1; /* we lie to the runtime */
10977 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10978 if (!mono_error_ok (&error))
10980 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10981 if (!mono_error_ok (&error))
10983 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10984 klass->flags = tb->attrs;
10986 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10988 klass->element_class = klass;
10990 if (mono_class_get_ref_info (klass) == NULL) {
10992 mono_class_set_ref_info (klass, tb);
10994 /* Put into cache so mono_class_get_checked () will find it.
10995 Skip nested types as those should not be available on the global scope. */
10996 if (!tb->nesting_type)
10997 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11000 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11001 by performing a mono_class_get which does the full resolution.
11003 Working around this semantics would require us to write a lot of code for no clear advantage.
11005 mono_image_append_class_to_reflection_info_set (klass);
11007 g_assert (mono_class_get_ref_info (klass) == tb);
11010 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11012 if (parent != NULL) {
11013 mono_class_setup_parent (klass, parent);
11014 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11015 const char *old_n = klass->name;
11016 /* trick to get relative numbering right when compiling corlib */
11017 klass->name = "BuildingObject";
11018 mono_class_setup_parent (klass, mono_defaults.object_class);
11019 klass->name = old_n;
11022 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11023 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11024 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11025 klass->instance_size = sizeof (MonoObject);
11026 klass->size_inited = 1;
11027 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11030 mono_class_setup_mono_type (klass);
11032 mono_class_setup_supertypes (klass);
11035 * FIXME: handle interfaces.
11038 tb->type.type = &klass->byval_arg;
11040 if (tb->nesting_type) {
11041 g_assert (tb->nesting_type->type);
11042 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11045 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11047 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11049 mono_loader_unlock ();
11053 mono_loader_unlock ();
11054 mono_error_raise_exception (&error);
11058 * mono_reflection_setup_generic_class:
11059 * @tb: a TypeBuilder object
11061 * Setup the generic class before adding the first generic parameter.
11064 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11069 * mono_reflection_create_generic_class:
11070 * @tb: a TypeBuilder object
11072 * Creates the generic class after all generic parameters have been added.
11075 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11080 klass = mono_class_from_mono_type (tb->type.type);
11082 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11084 if (klass->generic_container || (count == 0))
11087 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11089 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11091 klass->generic_container->owner.klass = klass;
11092 klass->generic_container->type_argc = count;
11093 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11095 klass->is_generic = 1;
11097 for (i = 0; i < count; i++) {
11098 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11099 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11100 klass->generic_container->type_params [i] = *param;
11101 /*Make sure we are a diferent type instance */
11102 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11103 klass->generic_container->type_params [i].info.pklass = NULL;
11104 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11106 g_assert (klass->generic_container->type_params [i].param.owner);
11109 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11113 * mono_reflection_create_internal_class:
11114 * @tb: a TypeBuilder object
11116 * Actually create the MonoClass that is associated with the TypeBuilder.
11119 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11123 klass = mono_class_from_mono_type (tb->type.type);
11125 mono_loader_lock ();
11126 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11127 MonoReflectionFieldBuilder *fb;
11129 MonoType *enum_basetype;
11131 g_assert (tb->fields != NULL);
11132 g_assert (mono_array_length (tb->fields) >= 1);
11134 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11136 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11137 mono_loader_unlock ();
11141 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11142 klass->element_class = mono_class_from_mono_type (enum_basetype);
11143 if (!klass->element_class)
11144 klass->element_class = mono_class_from_mono_type (enum_basetype);
11147 * get the element_class from the current corlib.
11149 ec = default_class_from_mono_type (enum_basetype);
11150 klass->instance_size = ec->instance_size;
11151 klass->size_inited = 1;
11153 * this is almost safe to do with enums and it's needed to be able
11154 * to create objects of the enum type (for use in SetConstant).
11156 /* FIXME: Does this mean enums can't have method overrides ? */
11157 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11159 mono_loader_unlock ();
11162 static MonoMarshalSpec*
11163 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11164 MonoReflectionMarshal *minfo)
11166 MonoMarshalSpec *res;
11168 res = image_g_new0 (image, MonoMarshalSpec, 1);
11169 res->native = (MonoMarshalNative)minfo->type;
11171 switch (minfo->type) {
11172 case MONO_NATIVE_LPARRAY:
11173 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11174 if (minfo->has_size) {
11175 res->data.array_data.param_num = minfo->param_num;
11176 res->data.array_data.num_elem = minfo->count;
11177 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11180 res->data.array_data.param_num = -1;
11181 res->data.array_data.num_elem = -1;
11182 res->data.array_data.elem_mult = -1;
11186 case MONO_NATIVE_BYVALTSTR:
11187 case MONO_NATIVE_BYVALARRAY:
11188 res->data.array_data.num_elem = minfo->count;
11191 case MONO_NATIVE_CUSTOM:
11192 if (minfo->marshaltyperef)
11193 res->data.custom_data.custom_name =
11194 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11195 if (minfo->mcookie)
11196 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11205 #endif /* !DISABLE_REFLECTION_EMIT */
11207 MonoReflectionMarshalAsAttribute*
11208 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11209 MonoMarshalSpec *spec, MonoError *error)
11211 MonoReflectionType *rt;
11212 MonoReflectionMarshalAsAttribute *minfo;
11215 mono_error_init (error);
11217 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11220 minfo->utype = spec->native;
11222 switch (minfo->utype) {
11223 case MONO_NATIVE_LPARRAY:
11224 minfo->array_subtype = spec->data.array_data.elem_type;
11225 minfo->size_const = spec->data.array_data.num_elem;
11226 if (spec->data.array_data.param_num != -1)
11227 minfo->size_param_index = spec->data.array_data.param_num;
11230 case MONO_NATIVE_BYVALTSTR:
11231 case MONO_NATIVE_BYVALARRAY:
11232 minfo->size_const = spec->data.array_data.num_elem;
11235 case MONO_NATIVE_CUSTOM:
11236 if (spec->data.custom_data.custom_name) {
11237 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11239 rt = mono_type_get_object_checked (domain, mtype, error);
11243 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11246 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11248 if (spec->data.custom_data.cookie)
11249 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11259 #ifndef DISABLE_REFLECTION_EMIT
11261 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11262 ReflectionMethodBuilder *rmb,
11263 MonoMethodSignature *sig)
11267 MonoMethodWrapper *wrapperm;
11268 MonoMarshalSpec **specs;
11269 MonoReflectionMethodAux *method_aux;
11274 mono_error_init (&error);
11276 * Methods created using a MethodBuilder should have their memory allocated
11277 * inside the image mempool, while dynamic methods should have their memory
11280 dynamic = rmb->refs != NULL;
11281 image = dynamic ? NULL : klass->image;
11284 g_assert (!klass->generic_class);
11286 mono_loader_lock ();
11288 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11289 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11290 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11292 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11294 wrapperm = (MonoMethodWrapper*)m;
11296 m->dynamic = dynamic;
11298 m->flags = rmb->attrs;
11299 m->iflags = rmb->iattrs;
11300 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11302 m->signature = sig;
11303 m->sre_method = TRUE;
11304 m->skip_visibility = rmb->skip_visibility;
11305 if (rmb->table_idx)
11306 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11308 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11309 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11310 m->string_ctor = 1;
11312 m->signature->pinvoke = 1;
11313 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11314 m->signature->pinvoke = 1;
11316 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11318 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11319 g_assert (mono_error_ok (&error));
11320 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11321 g_assert (mono_error_ok (&error));
11323 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11325 if (image_is_dynamic (klass->image))
11326 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11328 mono_loader_unlock ();
11331 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11332 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11333 MonoMethodHeader *header;
11335 gint32 max_stack, i;
11336 gint32 num_locals = 0;
11337 gint32 num_clauses = 0;
11341 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11342 code_size = rmb->ilgen->code_len;
11343 max_stack = rmb->ilgen->max_stack;
11344 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11345 if (rmb->ilgen->ex_handlers)
11346 num_clauses = method_count_clauses (rmb->ilgen);
11349 code = mono_array_addr (rmb->code, guint8, 0);
11350 code_size = mono_array_length (rmb->code);
11351 /* we probably need to run a verifier on the code... */
11361 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11362 header->code_size = code_size;
11363 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11364 memcpy ((char*)header->code, code, code_size);
11365 header->max_stack = max_stack;
11366 header->init_locals = rmb->init_locals;
11367 header->num_locals = num_locals;
11369 for (i = 0; i < num_locals; ++i) {
11370 MonoReflectionLocalBuilder *lb =
11371 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11373 header->locals [i] = image_g_new0 (image, MonoType, 1);
11374 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11377 header->num_clauses = num_clauses;
11379 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11380 rmb->ilgen, num_clauses);
11383 wrapperm->header = header;
11386 if (rmb->generic_params) {
11387 int count = mono_array_length (rmb->generic_params);
11388 MonoGenericContainer *container = rmb->generic_container;
11390 g_assert (container);
11392 container->type_argc = count;
11393 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11394 container->owner.method = m;
11395 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11397 m->is_generic = TRUE;
11398 mono_method_set_generic_container (m, container);
11400 for (i = 0; i < count; i++) {
11401 MonoReflectionGenericParam *gp =
11402 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11403 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11404 container->type_params [i] = *param;
11408 * The method signature might have pointers to generic parameters that belong to other methods.
11409 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11410 * generic parameters.
11412 for (i = 0; i < m->signature->param_count; ++i) {
11413 MonoType *t = m->signature->params [i];
11414 if (t->type == MONO_TYPE_MVAR) {
11415 MonoGenericParam *gparam = t->data.generic_param;
11416 if (gparam->num < count) {
11417 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11418 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11424 if (klass->generic_container) {
11425 container->parent = klass->generic_container;
11426 container->context.class_inst = klass->generic_container->context.class_inst;
11428 container->context.method_inst = mono_get_shared_generic_inst (container);
11432 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11436 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11438 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11439 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11440 for (i = 0; i < rmb->nrefs; ++i)
11441 data [i + 1] = rmb->refs [i];
11446 /* Parameter info */
11449 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11450 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11451 for (i = 0; i <= m->signature->param_count; ++i) {
11452 MonoReflectionParamBuilder *pb;
11453 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11454 if ((i > 0) && (pb->attrs)) {
11455 /* Make a copy since it might point to a shared type structure */
11456 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11457 m->signature->params [i - 1]->attrs = pb->attrs;
11460 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11461 MonoDynamicImage *assembly;
11463 MonoTypeEnum def_type;
11467 if (!method_aux->param_defaults) {
11468 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11469 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11471 assembly = (MonoDynamicImage*)klass->image;
11472 idx = encode_constant (assembly, pb->def_value, &def_type);
11473 /* Copy the data from the blob since it might get realloc-ed */
11474 p = assembly->blob.data + idx;
11475 len = mono_metadata_decode_blob_size (p, &p2);
11477 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11478 method_aux->param_default_types [i] = def_type;
11479 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11483 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11484 g_assert (mono_error_ok (&error));
11487 if (!method_aux->param_cattr)
11488 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11489 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11495 /* Parameter marshalling */
11498 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11499 MonoReflectionParamBuilder *pb;
11500 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11501 if (pb->marshal_info) {
11503 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11504 specs [pb->position] =
11505 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11509 if (specs != NULL) {
11511 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11512 method_aux->param_marshall = specs;
11515 if (image_is_dynamic (klass->image) && method_aux)
11516 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11518 mono_loader_unlock ();
11524 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11526 ReflectionMethodBuilder rmb;
11527 MonoMethodSignature *sig;
11529 mono_loader_lock ();
11530 sig = ctor_builder_to_signature (klass->image, mb);
11531 mono_loader_unlock ();
11533 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11536 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11537 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11539 /* If we are in a generic class, we might be called multiple times from inflate_method */
11540 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11541 /* ilgen is no longer needed */
11545 return mb->mhandle;
11549 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11551 ReflectionMethodBuilder rmb;
11552 MonoMethodSignature *sig;
11554 mono_error_init (error);
11556 mono_loader_lock ();
11557 sig = method_builder_to_signature (klass->image, mb);
11558 mono_loader_unlock ();
11560 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11563 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11564 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11566 /* If we are in a generic class, we might be called multiple times from inflate_method */
11567 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11568 /* ilgen is no longer needed */
11571 return mb->mhandle;
11574 static MonoClassField*
11575 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11577 MonoClassField *field;
11581 field = g_new0 (MonoClassField, 1);
11583 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11584 g_assert (mono_error_ok (&error));
11585 if (fb->attrs || fb->modreq || fb->modopt) {
11586 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11587 field->type->attrs = fb->attrs;
11589 g_assert (image_is_dynamic (klass->image));
11590 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11591 g_free (field->type);
11592 field->type = mono_metadata_type_dup (klass->image, custom);
11595 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11597 if (fb->offset != -1)
11598 field->offset = fb->offset;
11599 field->parent = klass;
11600 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11602 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11609 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11612 MonoReflectionTypeBuilder *tb = NULL;
11613 gboolean is_dynamic = FALSE;
11614 MonoClass *geninst;
11616 mono_loader_lock ();
11618 if (is_sre_type_builder (mono_object_class (type))) {
11619 tb = (MonoReflectionTypeBuilder *) type;
11622 } else if (is_sre_generic_instance (mono_object_class (type))) {
11623 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11624 MonoReflectionType *gtd = rgi->generic_type;
11626 if (is_sre_type_builder (mono_object_class (gtd))) {
11627 tb = (MonoReflectionTypeBuilder *)gtd;
11632 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11633 if (tb && tb->generic_container)
11634 mono_reflection_create_generic_class (tb);
11636 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11637 if (!klass->generic_container) {
11638 mono_loader_unlock ();
11642 if (klass->wastypebuilder) {
11643 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11648 mono_loader_unlock ();
11650 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11652 return &geninst->byval_arg;
11656 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11658 MonoGenericClass *gclass;
11659 MonoGenericInst *inst;
11661 g_assert (klass->generic_container);
11663 inst = mono_metadata_get_generic_inst (type_argc, types);
11664 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11666 return mono_generic_class_get_class (gclass);
11669 MonoReflectionMethod*
11670 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11674 MonoMethod *method, *inflated;
11675 MonoMethodInflated *imethod;
11676 MonoGenericContext tmp_context;
11677 MonoGenericInst *ginst;
11678 MonoType **type_argv;
11681 /*FIXME but this no longer should happen*/
11682 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11683 #ifndef DISABLE_REFLECTION_EMIT
11684 MonoReflectionMethodBuilder *mb = NULL;
11685 MonoReflectionTypeBuilder *tb;
11688 mb = (MonoReflectionMethodBuilder *) rmethod;
11689 tb = (MonoReflectionTypeBuilder *) mb->type;
11690 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11692 method = methodbuilder_to_mono_method (klass, mb, &error);
11694 mono_error_raise_exception (&error); /* FIXME don't raise here */
11696 g_assert_not_reached ();
11700 method = rmethod->method;
11703 klass = method->klass;
11705 if (method->is_inflated)
11706 method = ((MonoMethodInflated *) method)->declaring;
11708 count = mono_method_signature (method)->generic_param_count;
11709 if (count != mono_array_length (types))
11712 type_argv = g_new0 (MonoType *, count);
11713 for (i = 0; i < count; i++) {
11714 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11715 type_argv [i] = mono_reflection_type_get_handle (garg);
11717 ginst = mono_metadata_get_generic_inst (count, type_argv);
11718 g_free (type_argv);
11720 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11721 tmp_context.method_inst = ginst;
11723 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11724 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11725 imethod = (MonoMethodInflated *) inflated;
11727 /*FIXME but I think this is no longer necessary*/
11728 if (image_is_dynamic (method->klass->image)) {
11729 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11731 * This table maps metadata structures representing inflated methods/fields
11732 * to the reflection objects representing their generic definitions.
11734 mono_image_lock ((MonoImage*)image);
11735 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11736 mono_image_unlock ((MonoImage*)image);
11739 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11740 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11742 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11743 mono_error_raise_exception (&error); /* FIXME don't raise here */
11747 #ifndef DISABLE_REFLECTION_EMIT
11749 static MonoMethod *
11750 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11752 MonoMethodInflated *imethod;
11753 MonoGenericContext *context;
11757 * With generic code sharing the klass might not be inflated.
11758 * This can happen because classes inflated with their own
11759 * type arguments are "normalized" to the uninflated class.
11761 if (!klass->generic_class)
11764 context = mono_class_get_context (klass);
11766 if (klass->method.count && klass->methods) {
11767 /* Find the already created inflated method */
11768 for (i = 0; i < klass->method.count; ++i) {
11769 g_assert (klass->methods [i]->is_inflated);
11770 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11773 g_assert (i < klass->method.count);
11774 imethod = (MonoMethodInflated*)klass->methods [i];
11777 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11778 mono_error_assert_ok (&error);
11781 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11782 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11784 mono_image_lock ((MonoImage*)image);
11785 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11786 mono_image_unlock ((MonoImage*)image);
11788 return (MonoMethod *) imethod;
11791 static MonoMethod *
11792 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11794 MonoMethod *method;
11797 mono_error_init (error);
11799 MonoClass *type_class = mono_object_class (type);
11801 if (is_sre_generic_instance (type_class)) {
11802 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11803 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11804 } else if (is_sre_type_builder (type_class)) {
11805 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11806 } else if (type->type) {
11807 gklass = mono_class_from_mono_type (type->type);
11808 gklass = mono_class_get_generic_type_definition (gklass);
11810 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11813 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11814 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11815 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11817 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11821 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11822 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11825 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11826 method = ((MonoReflectionMethod *) obj)->method;
11828 method = NULL; /* prevent compiler warning */
11829 g_error ("can't handle type %s", obj->vtable->klass->name);
11832 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11835 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11837 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11839 MonoGenericClass *gclass;
11840 MonoDynamicGenericClass *dgclass;
11841 MonoClass *klass, *gklass;
11845 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11846 klass = mono_class_from_mono_type (gtype);
11847 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11848 gclass = gtype->data.generic_class;
11850 if (!gclass->is_dynamic)
11853 dgclass = (MonoDynamicGenericClass *) gclass;
11855 if (dgclass->initialized)
11858 gklass = gclass->container_class;
11859 mono_class_init (gklass);
11861 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11863 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11864 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11865 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11867 for (i = 0; i < dgclass->count_fields; i++) {
11868 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11869 MonoClassField *field, *inflated_field = NULL;
11871 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11872 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11873 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11874 field = ((MonoReflectionField *) obj)->field;
11876 field = NULL; /* prevent compiler warning */
11877 g_assert_not_reached ();
11880 dgclass->fields [i] = *field;
11881 dgclass->fields [i].parent = klass;
11882 dgclass->fields [i].type = mono_class_inflate_generic_type (
11883 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11884 dgclass->field_generic_types [i] = field->type;
11885 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11886 dgclass->field_objects [i] = obj;
11888 if (inflated_field) {
11889 g_free (inflated_field);
11891 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11895 dgclass->initialized = TRUE;
11899 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11901 MonoDynamicGenericClass *dgclass;
11904 g_assert (gclass->is_dynamic);
11906 dgclass = (MonoDynamicGenericClass *)gclass;
11908 for (i = 0; i < dgclass->count_fields; ++i) {
11909 MonoClassField *field = dgclass->fields + i;
11910 mono_metadata_free_type (field->type);
11911 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11916 fix_partial_generic_class (MonoClass *klass)
11918 MonoClass *gklass = klass->generic_class->container_class;
11919 MonoDynamicGenericClass *dgclass;
11922 if (klass->wastypebuilder)
11925 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11926 if (klass->parent != gklass->parent) {
11928 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11929 if (mono_error_ok (&error)) {
11930 MonoClass *parent = mono_class_from_mono_type (parent_type);
11931 mono_metadata_free_type (parent_type);
11932 if (parent != klass->parent) {
11933 /*fool mono_class_setup_parent*/
11934 klass->supertypes = NULL;
11935 mono_class_setup_parent (klass, parent);
11938 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11939 mono_error_cleanup (&error);
11940 if (gklass->wastypebuilder)
11941 klass->wastypebuilder = TRUE;
11946 if (!dgclass->initialized)
11949 if (klass->method.count != gklass->method.count) {
11950 klass->method.count = gklass->method.count;
11951 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11953 for (i = 0; i < klass->method.count; i++) {
11955 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11956 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11957 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11961 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11962 klass->interface_count = gklass->interface_count;
11963 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11964 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11966 for (i = 0; i < gklass->interface_count; ++i) {
11968 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11969 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11970 mono_metadata_free_type (iface_type);
11972 ensure_runtime_vtable (klass->interfaces [i], &error);
11973 mono_error_raise_exception (&error); /* FIXME don't raise here */
11975 klass->interfaces_inited = 1;
11978 if (klass->field.count != gklass->field.count) {
11979 klass->field.count = gklass->field.count;
11980 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11982 for (i = 0; i < klass->field.count; i++) {
11983 klass->fields [i] = gklass->fields [i];
11984 klass->fields [i].parent = klass;
11985 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11989 /*We can only finish with this klass once it's parent has as well*/
11990 if (gklass->wastypebuilder)
11991 klass->wastypebuilder = TRUE;
11996 * ensure_generic_class_runtime_vtable:
11997 * @klass a generic class
11998 * @error set on error
12000 * Ensures that the generic container of @klass has a vtable and
12001 * returns TRUE on success. On error returns FALSE and sets @error.
12004 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12006 MonoClass *gklass = klass->generic_class->container_class;
12008 mono_error_init (error);
12010 if (!ensure_runtime_vtable (gklass, error))
12013 fix_partial_generic_class (klass);
12019 * ensure_runtime_vtable:
12021 * @error set on error
12023 * Ensures that @klass has a vtable and returns TRUE on success. On
12024 * error returns FALSE and sets @error.
12027 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12029 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12032 mono_error_init (error);
12034 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12037 if (!ensure_runtime_vtable (klass->parent, error))
12041 num = tb->ctors? mono_array_length (tb->ctors): 0;
12042 num += tb->num_methods;
12043 klass->method.count = num;
12044 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12045 num = tb->ctors? mono_array_length (tb->ctors): 0;
12046 for (i = 0; i < num; ++i) {
12047 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12050 klass->methods [i] = ctor;
12052 num = tb->num_methods;
12054 for (i = 0; i < num; ++i) {
12055 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12058 klass->methods [j++] = meth;
12061 if (tb->interfaces) {
12062 klass->interface_count = mono_array_length (tb->interfaces);
12063 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12064 for (i = 0; i < klass->interface_count; ++i) {
12065 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12066 klass->interfaces [i] = mono_class_from_mono_type (iface);
12067 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12070 klass->interfaces_inited = 1;
12072 } else if (klass->generic_class){
12073 if (!ensure_generic_class_runtime_vtable (klass, error))
12077 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12079 for (i = 0; i < klass->method.count; ++i) {
12080 MonoMethod *im = klass->methods [i];
12081 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12082 im->slot = slot_num++;
12085 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12086 mono_class_setup_interface_offsets (klass);
12087 mono_class_setup_interface_id (klass);
12091 * The generic vtable is needed even if image->run is not set since some
12092 * runtime code like ves_icall_Type_GetMethodsByName depends on
12093 * method->slot being defined.
12097 * tb->methods could not be freed since it is used for determining
12098 * overrides during dynamic vtable construction.
12105 mono_reflection_method_get_handle (MonoObject *method)
12108 MonoClass *klass = mono_object_class (method);
12109 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12110 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12111 return sr_method->method;
12113 if (is_sre_method_builder (klass)) {
12114 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12115 return mb->mhandle;
12117 if (is_sre_method_on_tb_inst (klass)) {
12118 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12119 MonoMethod *result;
12120 /*FIXME move this to a proper method and unify with resolve_object*/
12121 if (m->method_args) {
12122 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12123 mono_error_raise_exception (&error); /* FIXME don't raise here */
12125 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12126 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12127 MonoMethod *mono_method;
12129 if (is_sre_method_builder (mono_object_class (m->mb)))
12130 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12131 else if (is_sr_mono_method (mono_object_class (m->mb)))
12132 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12134 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)));
12136 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12141 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12146 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12148 MonoReflectionTypeBuilder *tb;
12150 MonoReflectionMethod *m;
12153 *num_overrides = 0;
12155 g_assert (image_is_dynamic (klass->image));
12157 if (!mono_class_get_ref_info (klass))
12160 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12162 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12166 for (i = 0; i < tb->num_methods; ++i) {
12167 MonoReflectionMethodBuilder *mb =
12168 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12169 if (mb->override_methods)
12170 onum += mono_array_length (mb->override_methods);
12175 *overrides = g_new0 (MonoMethod*, onum * 2);
12178 for (i = 0; i < tb->num_methods; ++i) {
12179 MonoReflectionMethodBuilder *mb =
12180 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12181 if (mb->override_methods) {
12182 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12183 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12185 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12186 (*overrides) [onum * 2 + 1] = mb->mhandle;
12188 g_assert (mb->mhandle);
12196 *num_overrides = onum;
12200 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12202 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12203 MonoReflectionFieldBuilder *fb;
12204 MonoClassField *field;
12205 MonoImage *image = klass->image;
12206 const char *p, *p2;
12208 guint32 len, idx, real_size = 0;
12210 klass->field.count = tb->num_fields;
12211 klass->field.first = 0;
12213 mono_error_init (error);
12215 if (tb->class_size) {
12216 if ((tb->packing_size & 0xffffff00) != 0) {
12217 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12218 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12221 klass->packing_size = tb->packing_size;
12222 real_size = klass->instance_size + tb->class_size;
12225 if (!klass->field.count) {
12226 klass->instance_size = MAX (klass->instance_size, real_size);
12230 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12231 mono_class_alloc_ext (klass);
12232 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12234 This is, guess what, a hack.
12235 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12236 On the static path no field class is resolved, only types are built. This is the right thing to do
12238 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12240 klass->size_inited = 1;
12242 for (i = 0; i < klass->field.count; ++i) {
12243 MonoArray *rva_data;
12244 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12245 field = &klass->fields [i];
12246 field->name = mono_string_to_utf8_image (image, fb->name, error);
12247 if (!mono_error_ok (error))
12250 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12251 field->type->attrs = fb->attrs;
12253 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12256 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12257 char *base = mono_array_addr (rva_data, char, 0);
12258 size_t size = mono_array_length (rva_data);
12259 char *data = (char *)mono_image_alloc (klass->image, size);
12260 memcpy (data, base, size);
12261 klass->ext->field_def_values [i].data = data;
12263 if (fb->offset != -1)
12264 field->offset = fb->offset;
12265 field->parent = klass;
12266 fb->handle = field;
12267 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12269 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12270 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12272 if (fb->def_value) {
12273 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12274 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12275 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12276 /* Copy the data from the blob since it might get realloc-ed */
12277 p = assembly->blob.data + idx;
12278 len = mono_metadata_decode_blob_size (p, &p2);
12280 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12281 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12285 klass->instance_size = MAX (klass->instance_size, real_size);
12286 mono_class_layout_fields (klass);
12290 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12292 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12293 MonoReflectionPropertyBuilder *pb;
12294 MonoImage *image = klass->image;
12295 MonoProperty *properties;
12298 mono_error_init (error);
12301 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12303 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12304 klass->ext->property.first = 0;
12306 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12307 klass->ext->properties = properties;
12308 for (i = 0; i < klass->ext->property.count; ++i) {
12309 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12310 properties [i].parent = klass;
12311 properties [i].attrs = pb->attrs;
12312 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12313 if (!mono_error_ok (error))
12315 if (pb->get_method)
12316 properties [i].get = pb->get_method->mhandle;
12317 if (pb->set_method)
12318 properties [i].set = pb->set_method->mhandle;
12320 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12321 if (pb->def_value) {
12323 const char *p, *p2;
12324 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12325 if (!klass->ext->prop_def_values)
12326 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12327 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12328 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12329 /* Copy the data from the blob since it might get realloc-ed */
12330 p = assembly->blob.data + idx;
12331 len = mono_metadata_decode_blob_size (p, &p2);
12333 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12334 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12339 MonoReflectionEvent *
12340 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12343 MonoEvent *event = g_new0 (MonoEvent, 1);
12346 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12348 event->parent = klass;
12349 event->attrs = eb->attrs;
12350 event->name = mono_string_to_utf8 (eb->name);
12351 if (eb->add_method)
12352 event->add = eb->add_method->mhandle;
12353 if (eb->remove_method)
12354 event->remove = eb->remove_method->mhandle;
12355 if (eb->raise_method)
12356 event->raise = eb->raise_method->mhandle;
12358 #ifndef MONO_SMALL_CONFIG
12359 if (eb->other_methods) {
12361 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12362 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12363 MonoReflectionMethodBuilder *mb =
12364 mono_array_get (eb->other_methods,
12365 MonoReflectionMethodBuilder*, j);
12366 event->other [j] = mb->mhandle;
12371 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12372 mono_error_raise_exception (&error); /* FIXME don't raise here */
12377 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12379 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12380 MonoReflectionEventBuilder *eb;
12381 MonoImage *image = klass->image;
12385 mono_error_init (error);
12388 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12390 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12391 klass->ext->event.first = 0;
12393 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12394 klass->ext->events = events;
12395 for (i = 0; i < klass->ext->event.count; ++i) {
12396 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12397 events [i].parent = klass;
12398 events [i].attrs = eb->attrs;
12399 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12400 if (!mono_error_ok (error))
12402 if (eb->add_method)
12403 events [i].add = eb->add_method->mhandle;
12404 if (eb->remove_method)
12405 events [i].remove = eb->remove_method->mhandle;
12406 if (eb->raise_method)
12407 events [i].raise = eb->raise_method->mhandle;
12409 #ifndef MONO_SMALL_CONFIG
12410 if (eb->other_methods) {
12412 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12413 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12414 MonoReflectionMethodBuilder *mb =
12415 mono_array_get (eb->other_methods,
12416 MonoReflectionMethodBuilder*, j);
12417 events [i].other [j] = mb->mhandle;
12421 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12426 remove_instantiations_of_and_ensure_contents (gpointer key,
12428 gpointer user_data)
12430 MonoType *type = (MonoType*)key;
12431 MonoClass *klass = (MonoClass*)user_data;
12433 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12434 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12441 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12443 mono_error_init (error);
12449 for (i = 0; i < mono_array_length (arr); ++i) {
12450 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12451 if (!mono_error_ok (error))
12456 MonoReflectionType*
12457 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12461 MonoDomain* domain;
12462 MonoReflectionType* res;
12465 domain = mono_object_domain (tb);
12466 klass = mono_class_from_mono_type (tb->type.type);
12469 * Check for user defined Type subclasses.
12471 RESOLVE_TYPE (tb->parent, &error);
12472 mono_error_raise_exception (&error); /* FIXME don't raise here */
12473 check_array_for_usertypes (tb->interfaces, &error);
12474 mono_error_raise_exception (&error); /*FIXME don't raise here */
12476 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12477 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12479 RESOLVE_TYPE (fb->type, &error);
12480 mono_error_raise_exception (&error); /* FIXME don't raise here */
12481 check_array_for_usertypes (fb->modreq, &error);
12482 mono_error_raise_exception (&error); /*FIXME don't raise here */
12483 check_array_for_usertypes (fb->modopt, &error);
12484 mono_error_raise_exception (&error); /*FIXME don't raise here */
12485 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12486 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12487 mono_error_raise_exception (&error); /* FIXME don't raise here */
12493 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12494 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12496 RESOLVE_TYPE (mb->rtype, &error);
12497 mono_error_raise_exception (&error); /* FIXME don't raise here */
12498 check_array_for_usertypes (mb->return_modreq, &error);
12499 mono_error_raise_exception (&error); /*FIXME don't raise here */
12500 check_array_for_usertypes (mb->return_modopt, &error);
12501 mono_error_raise_exception (&error); /*FIXME don't raise here */
12502 check_array_for_usertypes (mb->parameters, &error);
12503 mono_error_raise_exception (&error); /*FIXME don't raise here */
12504 if (mb->param_modreq)
12505 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12506 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12507 mono_error_raise_exception (&error); /*FIXME don't raise here */
12509 if (mb->param_modopt)
12510 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12511 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12512 mono_error_raise_exception (&error); /*FIXME don't raise here */
12518 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12519 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12521 check_array_for_usertypes (mb->parameters, &error);
12522 mono_error_raise_exception (&error); /*FIXME don't raise here */
12523 if (mb->param_modreq)
12524 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12525 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12526 mono_error_raise_exception (&error); /*FIXME don't raise here */
12528 if (mb->param_modopt)
12529 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12530 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12531 mono_error_raise_exception (&error); /*FIXME don't raise here */
12537 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12540 * we need to lock the domain because the lock will be taken inside
12541 * So, we need to keep the locking order correct.
12543 mono_loader_lock ();
12544 mono_domain_lock (domain);
12545 if (klass->wastypebuilder) {
12546 mono_domain_unlock (domain);
12547 mono_loader_unlock ();
12549 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12550 mono_error_raise_exception (&error); /* FIXME don't raise here */
12555 * Fields to set in klass:
12556 * the various flags: delegate/unicode/contextbound etc.
12558 klass->flags = tb->attrs;
12559 klass->has_cctor = 1;
12560 klass->has_finalize = 1;
12561 klass->has_finalize_inited = 1;
12563 mono_class_setup_parent (klass, klass->parent);
12564 /* fool mono_class_setup_supertypes */
12565 klass->supertypes = NULL;
12566 mono_class_setup_supertypes (klass);
12567 mono_class_setup_mono_type (klass);
12570 if (!((MonoDynamicImage*)klass->image)->run) {
12571 if (klass->generic_container) {
12572 /* FIXME: The code below can't handle generic classes */
12573 klass->wastypebuilder = TRUE;
12574 mono_loader_unlock ();
12575 mono_domain_unlock (domain);
12577 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12578 mono_error_raise_exception (&error); /* FIXME don't raise here */
12585 /* enums are done right away */
12586 if (!klass->enumtype)
12587 if (!ensure_runtime_vtable (klass, &error))
12590 if (tb->subtypes) {
12591 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12592 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12593 mono_class_alloc_ext (klass);
12594 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
12598 klass->nested_classes_inited = TRUE;
12600 /* fields and object layout */
12601 if (klass->parent) {
12602 if (!klass->parent->size_inited)
12603 mono_class_init (klass->parent);
12604 klass->instance_size = klass->parent->instance_size;
12605 klass->sizes.class_size = 0;
12606 klass->min_align = klass->parent->min_align;
12607 /* if the type has no fields we won't call the field_setup
12608 * routine which sets up klass->has_references.
12610 klass->has_references |= klass->parent->has_references;
12612 klass->instance_size = sizeof (MonoObject);
12613 klass->min_align = 1;
12616 /* FIXME: handle packing_size and instance_size */
12617 typebuilder_setup_fields (klass, &error);
12618 if (!mono_error_ok (&error))
12620 typebuilder_setup_properties (klass, &error);
12621 if (!mono_error_ok (&error))
12624 typebuilder_setup_events (klass, &error);
12625 if (!mono_error_ok (&error))
12628 klass->wastypebuilder = TRUE;
12631 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12632 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12633 * we want to return normal System.MonoType objects, so clear these out from the cache.
12635 * Together with this we must ensure the contents of all instances to match the created type.
12637 if (domain->type_hash && klass->generic_container)
12638 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12640 mono_domain_unlock (domain);
12641 mono_loader_unlock ();
12643 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12644 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12645 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12648 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12649 mono_error_raise_exception (&error); /* FIXME don't raise here */
12651 g_assert (res != (MonoReflectionType*)tb);
12656 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12657 klass->wastypebuilder = TRUE;
12658 mono_domain_unlock (domain);
12659 mono_loader_unlock ();
12660 mono_error_raise_exception (&error);
12665 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12667 MonoGenericParamFull *param;
12672 image = &gparam->tbuilder->module->dynamic_image->image;
12674 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12676 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12677 g_assert (mono_error_ok (&error));
12678 param->param.num = gparam->index;
12680 if (gparam->mbuilder) {
12681 if (!gparam->mbuilder->generic_container) {
12682 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12683 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12684 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12685 gparam->mbuilder->generic_container->is_method = TRUE;
12687 * Cannot set owner.method, since the MonoMethod is not created yet.
12688 * Set the image field instead, so type_in_image () works.
12690 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12691 gparam->mbuilder->generic_container->owner.image = klass->image;
12693 param->param.owner = gparam->mbuilder->generic_container;
12694 } else if (gparam->tbuilder) {
12695 if (!gparam->tbuilder->generic_container) {
12696 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12697 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12698 gparam->tbuilder->generic_container->owner.klass = klass;
12700 param->param.owner = gparam->tbuilder->generic_container;
12703 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12705 gparam->type.type = &pklass->byval_arg;
12707 mono_class_set_ref_info (pklass, gparam);
12708 mono_image_append_class_to_reflection_info_set (pklass);
12712 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12715 MonoReflectionModuleBuilder *module = sig->module;
12716 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12717 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12722 check_array_for_usertypes (sig->arguments, &error);
12723 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12725 sigbuffer_init (&buf, 32);
12727 sigbuffer_add_value (&buf, 0x07);
12728 sigbuffer_add_value (&buf, na);
12729 if (assembly != NULL){
12730 for (i = 0; i < na; ++i) {
12731 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12732 encode_reflection_type (assembly, type, &buf);
12736 buflen = buf.p - buf.buf;
12737 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12738 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12739 sigbuffer_free (&buf);
12745 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12748 MonoDynamicImage *assembly = sig->module->dynamic_image;
12749 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12754 check_array_for_usertypes (sig->arguments, &error);
12755 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12757 sigbuffer_init (&buf, 32);
12759 sigbuffer_add_value (&buf, 0x06);
12760 for (i = 0; i < na; ++i) {
12761 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12762 encode_reflection_type (assembly, type, &buf);
12765 buflen = buf.p - buf.buf;
12766 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12767 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12768 sigbuffer_free (&buf);
12774 MonoMethod *handle;
12775 MonoDomain *domain;
12776 } DynamicMethodReleaseData;
12779 * The runtime automatically clean up those after finalization.
12781 static MonoReferenceQueue *dynamic_method_queue;
12784 free_dynamic_method (void *dynamic_method)
12786 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12787 MonoDomain *domain = data->domain;
12788 MonoMethod *method = data->handle;
12791 mono_domain_lock (domain);
12792 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12793 g_hash_table_remove (domain->method_to_dyn_method, method);
12794 mono_domain_unlock (domain);
12795 g_assert (dis_link);
12796 mono_gchandle_free (dis_link);
12798 mono_runtime_free_method (domain, method);
12803 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12805 MonoReferenceQueue *queue;
12806 MonoMethod *handle;
12807 DynamicMethodReleaseData *release_data;
12808 ReflectionMethodBuilder rmb;
12809 MonoMethodSignature *sig;
12811 MonoDomain *domain;
12815 if (mono_runtime_is_shutting_down ())
12816 mono_raise_exception (mono_get_exception_invalid_operation (""));
12818 if (!(queue = dynamic_method_queue)) {
12819 mono_loader_lock ();
12820 if (!(queue = dynamic_method_queue))
12821 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12822 mono_loader_unlock ();
12825 sig = dynamic_method_to_signature (mb);
12827 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12830 * Resolve references.
12833 * Every second entry in the refs array is reserved for storing handle_class,
12834 * which is needed by the ldtoken implementation in the JIT.
12836 rmb.nrefs = mb->nrefs;
12837 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12838 for (i = 0; i < mb->nrefs; i += 2) {
12839 MonoClass *handle_class;
12841 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12843 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12844 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12846 * The referenced DynamicMethod should already be created by the managed
12847 * code, except in the case of circular references. In that case, we store
12848 * method in the refs array, and fix it up later when the referenced
12849 * DynamicMethod is created.
12851 if (method->mhandle) {
12852 ref = method->mhandle;
12854 /* FIXME: GC object stored in unmanaged memory */
12857 /* FIXME: GC object stored in unmanaged memory */
12858 method->referenced_by = g_slist_append (method->referenced_by, mb);
12860 handle_class = mono_defaults.methodhandle_class;
12862 MonoException *ex = NULL;
12863 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12865 ex = mono_get_exception_type_load (NULL, NULL);
12866 else if (mono_security_core_clr_enabled ())
12867 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12871 mono_raise_exception (ex);
12876 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12877 rmb.refs [i + 1] = handle_class;
12880 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12882 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12883 release_data = g_new (DynamicMethodReleaseData, 1);
12884 release_data->handle = handle;
12885 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12886 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12887 g_free (release_data);
12889 /* Fix up refs entries pointing at us */
12890 for (l = mb->referenced_by; l; l = l->next) {
12891 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12892 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12895 g_assert (method->mhandle);
12897 data = (gpointer*)wrapper->method_data;
12898 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12899 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12900 data [i + 1] = mb->mhandle;
12903 g_slist_free (mb->referenced_by);
12907 /* ilgen is no longer needed */
12910 domain = mono_domain_get ();
12911 mono_domain_lock (domain);
12912 if (!domain->method_to_dyn_method)
12913 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12914 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12915 mono_domain_unlock (domain);
12918 #endif /* DISABLE_REFLECTION_EMIT */
12922 * mono_reflection_is_valid_dynamic_token:
12924 * Returns TRUE if token is valid.
12928 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12930 return lookup_dyn_token (image, token) != NULL;
12933 MonoMethodSignature *
12934 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12936 MonoMethodSignature *sig;
12937 g_assert (image_is_dynamic (image));
12939 mono_error_init (error);
12941 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12945 return mono_method_signature_checked (method, error);
12948 #ifndef DISABLE_REFLECTION_EMIT
12951 * mono_reflection_lookup_dynamic_token:
12953 * Finish the Builder object pointed to by TOKEN and return the corresponding
12954 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12955 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12958 * LOCKING: Take the loader lock
12961 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12963 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12967 obj = lookup_dyn_token (assembly, token);
12970 g_error ("Could not find required dynamic token 0x%08x", token);
12976 handle_class = &klass;
12977 return resolve_object (image, obj, handle_class, context);
12981 * ensure_complete_type:
12983 * Ensure that KLASS is completed if it is a dynamic type, or references
12987 ensure_complete_type (MonoClass *klass)
12991 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12992 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12994 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12995 mono_error_raise_exception (&error); /* FIXME don't raise here */
12997 // Asserting here could break a lot of code
12998 //g_assert (klass->wastypebuilder);
13001 if (klass->generic_class) {
13002 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13005 for (i = 0; i < inst->type_argc; ++i) {
13006 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13012 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13015 gpointer result = NULL;
13017 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13018 result = mono_string_intern_checked ((MonoString*)obj, &error);
13019 mono_error_raise_exception (&error); /* FIXME don't raise here */
13020 *handle_class = mono_defaults.string_class;
13022 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13023 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13024 MonoClass *mc = mono_class_from_mono_type (type);
13025 if (!mono_class_init (mc))
13026 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13029 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13030 result = mono_class_from_mono_type (inflated);
13031 mono_metadata_free_type (inflated);
13033 result = mono_class_from_mono_type (type);
13035 *handle_class = mono_defaults.typehandle_class;
13037 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13038 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13039 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13040 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13041 result = ((MonoReflectionMethod*)obj)->method;
13044 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13045 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13047 *handle_class = mono_defaults.methodhandle_class;
13049 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13050 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13051 result = mb->mhandle;
13053 /* Type is not yet created */
13054 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13056 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13057 mono_error_raise_exception (&error); /* FIXME don't raise here */
13060 * Hopefully this has been filled in by calling CreateType() on the
13064 * TODO: This won't work if the application finishes another
13065 * TypeBuilder instance instead of this one.
13067 result = mb->mhandle;
13071 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13072 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13074 *handle_class = mono_defaults.methodhandle_class;
13075 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13076 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13078 result = cb->mhandle;
13080 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13082 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13083 mono_error_raise_exception (&error); /* FIXME don't raise here */
13084 result = cb->mhandle;
13088 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13089 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13091 *handle_class = mono_defaults.methodhandle_class;
13092 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13093 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13095 ensure_complete_type (field->parent);
13097 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
13098 MonoClass *klass = mono_class_from_mono_type (inflated);
13099 MonoClassField *inflated_field;
13100 gpointer iter = NULL;
13101 mono_metadata_free_type (inflated);
13102 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13103 if (!strcmp (field->name, inflated_field->name))
13106 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13107 result = inflated_field;
13111 *handle_class = mono_defaults.fieldhandle_class;
13113 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13114 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13115 result = fb->handle;
13118 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13120 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13121 mono_error_raise_exception (&error); /* FIXME don't raise here */
13122 result = fb->handle;
13125 if (fb->handle && fb->handle->parent->generic_container) {
13126 MonoClass *klass = fb->handle->parent;
13127 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
13128 MonoClass *inflated = mono_class_from_mono_type (type);
13130 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13132 mono_metadata_free_type (type);
13134 *handle_class = mono_defaults.fieldhandle_class;
13135 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13136 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13137 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
13140 klass = type->data.klass;
13141 if (klass->wastypebuilder) {
13142 /* Already created */
13146 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13147 mono_error_raise_exception (&error); /* FIXME don't raise here */
13148 result = type->data.klass;
13151 *handle_class = mono_defaults.typehandle_class;
13152 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13153 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13154 MonoMethodSignature *sig;
13157 if (helper->arguments)
13158 nargs = mono_array_length (helper->arguments);
13162 sig = mono_metadata_signature_alloc (image, nargs);
13163 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13164 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13166 if (helper->unmanaged_call_conv) { /* unmanaged */
13167 sig->call_convention = helper->unmanaged_call_conv - 1;
13168 sig->pinvoke = TRUE;
13169 } else if (helper->call_conv & 0x02) {
13170 sig->call_convention = MONO_CALL_VARARG;
13172 sig->call_convention = MONO_CALL_DEFAULT;
13175 sig->param_count = nargs;
13176 /* TODO: Copy type ? */
13177 sig->ret = helper->return_type->type;
13178 for (i = 0; i < nargs; ++i)
13179 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13182 *handle_class = NULL;
13183 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13184 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13185 /* Already created by the managed code */
13186 g_assert (method->mhandle);
13187 result = method->mhandle;
13188 *handle_class = mono_defaults.methodhandle_class;
13189 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13190 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13191 type = mono_class_inflate_generic_type (type, context);
13192 result = mono_class_from_mono_type (type);
13193 *handle_class = mono_defaults.typehandle_class;
13195 mono_metadata_free_type (type);
13196 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13197 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13198 type = mono_class_inflate_generic_type (type, context);
13199 result = mono_class_from_mono_type (type);
13200 *handle_class = mono_defaults.typehandle_class;
13202 mono_metadata_free_type (type);
13203 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13204 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13205 MonoClass *inflated;
13207 MonoClassField *field;
13209 if (is_sre_field_builder (mono_object_class (f->fb)))
13210 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13211 else if (is_sr_mono_field (mono_object_class (f->fb)))
13212 field = ((MonoReflectionField*)f->fb)->field;
13214 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)));
13216 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13217 inflated = mono_class_from_mono_type (type);
13219 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13220 ensure_complete_type (field->parent);
13222 mono_metadata_free_type (type);
13223 *handle_class = mono_defaults.fieldhandle_class;
13224 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13225 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13226 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13227 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13228 MonoMethod *method;
13230 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13231 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13232 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13233 method = ((MonoReflectionMethod *)c->cb)->method;
13235 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)));
13237 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13238 *handle_class = mono_defaults.methodhandle_class;
13239 mono_metadata_free_type (type);
13240 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13241 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13242 if (m->method_args) {
13243 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13244 mono_error_raise_exception (&error); /* FIXME don't raise here */
13246 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13247 mono_error_assert_ok (&error);
13250 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13251 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13252 MonoMethod *method;
13254 if (is_sre_method_builder (mono_object_class (m->mb)))
13255 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13256 else if (is_sr_mono_method (mono_object_class (m->mb)))
13257 method = ((MonoReflectionMethod *)m->mb)->method;
13259 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)));
13261 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13262 mono_metadata_free_type (type);
13264 *handle_class = mono_defaults.methodhandle_class;
13265 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13266 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13269 MonoMethod *method;
13273 mtype = mono_reflection_type_get_handle (m->parent);
13274 klass = mono_class_from_mono_type (mtype);
13276 /* Find the method */
13278 name = mono_string_to_utf8 (m->name);
13280 while ((method = mono_class_get_methods (klass, &iter))) {
13281 if (!strcmp (method->name, name))
13288 // FIXME: Check parameters/return value etc. match
13291 *handle_class = mono_defaults.methodhandle_class;
13292 } else if (is_sre_array (mono_object_get_class(obj)) ||
13293 is_sre_byref (mono_object_get_class(obj)) ||
13294 is_sre_pointer (mono_object_get_class(obj))) {
13295 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13296 MonoType *type = mono_reflection_type_get_handle (ref_type);
13299 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13300 result = mono_class_from_mono_type (inflated);
13301 mono_metadata_free_type (inflated);
13303 result = mono_class_from_mono_type (type);
13305 *handle_class = mono_defaults.typehandle_class;
13307 g_print ("%s\n", obj->vtable->klass->name);
13308 g_assert_not_reached ();
13313 #else /* DISABLE_REFLECTION_EMIT */
13316 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13318 g_assert_not_reached ();
13323 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13325 g_assert_not_reached ();
13329 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13331 g_assert_not_reached ();
13335 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13337 g_assert_not_reached ();
13341 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13343 g_assert_not_reached ();
13347 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13349 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13353 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13355 g_assert_not_reached ();
13359 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13361 g_assert_not_reached ();
13364 MonoReflectionModule *
13365 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13367 g_assert_not_reached ();
13372 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13374 g_assert_not_reached ();
13379 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13381 g_assert_not_reached ();
13386 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13387 gboolean create_open_instance, gboolean register_token, MonoError *error)
13389 g_assert_not_reached ();
13394 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13399 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13401 g_assert_not_reached ();
13405 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13408 *num_overrides = 0;
13411 MonoReflectionEvent *
13412 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13414 g_assert_not_reached ();
13418 MonoReflectionType*
13419 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13421 g_assert_not_reached ();
13426 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13428 g_assert_not_reached ();
13432 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13434 g_assert_not_reached ();
13439 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13441 g_assert_not_reached ();
13446 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13451 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13457 mono_reflection_type_get_handle (MonoReflectionType* ref)
13465 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13467 g_assert_not_reached ();
13470 #endif /* DISABLE_REFLECTION_EMIT */
13472 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13473 const static guint32 declsec_flags_map[] = {
13474 0x00000000, /* empty */
13475 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13476 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13477 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13478 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13479 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13480 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13481 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13482 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13483 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13484 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13485 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13486 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13487 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13488 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13489 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13490 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13491 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13492 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13496 * Returns flags that includes all available security action associated to the handle.
13497 * @token: metadata token (either for a class or a method)
13498 * @image: image where resides the metadata.
13501 mono_declsec_get_flags (MonoImage *image, guint32 token)
13503 int index = mono_metadata_declsec_from_index (image, token);
13504 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13505 guint32 result = 0;
13509 /* HasSecurity can be present for other, not specially encoded, attributes,
13510 e.g. SuppressUnmanagedCodeSecurityAttribute */
13514 for (i = index; i < t->rows; i++) {
13515 guint32 cols [MONO_DECL_SECURITY_SIZE];
13517 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13518 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13521 action = cols [MONO_DECL_SECURITY_ACTION];
13522 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13523 result |= declsec_flags_map [action];
13525 g_assert_not_reached ();
13532 * Get the security actions (in the form of flags) associated with the specified method.
13534 * @method: The method for which we want the declarative security flags.
13535 * Return the declarative security flags for the method (only).
13537 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13538 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13541 mono_declsec_flags_from_method (MonoMethod *method)
13543 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13544 /* FIXME: No cache (for the moment) */
13545 guint32 idx = mono_method_get_index (method);
13546 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13547 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13548 return mono_declsec_get_flags (method->klass->image, idx);
13554 * Get the security actions (in the form of flags) associated with the specified class.
13556 * @klass: The class for which we want the declarative security flags.
13557 * Return the declarative security flags for the class.
13559 * Note: We cache the flags inside the MonoClass structure as this will get
13560 * called very often (at least for each method).
13563 mono_declsec_flags_from_class (MonoClass *klass)
13565 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13566 if (!klass->ext || !klass->ext->declsec_flags) {
13569 idx = mono_metadata_token_index (klass->type_token);
13570 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13571 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13572 mono_loader_lock ();
13573 mono_class_alloc_ext (klass);
13574 mono_loader_unlock ();
13575 /* we cache the flags on classes */
13576 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13578 return klass->ext->declsec_flags;
13584 * Get the security actions (in the form of flags) associated with the specified assembly.
13586 * @assembly: The assembly for which we want the declarative security flags.
13587 * Return the declarative security flags for the assembly.
13590 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13592 guint32 idx = 1; /* there is only one assembly */
13593 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13594 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13595 return mono_declsec_get_flags (assembly->image, idx);
13600 * Fill actions for the specific index (which may either be an encoded class token or
13601 * an encoded method token) from the metadata image.
13602 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13605 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13606 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13608 MonoBoolean result = FALSE;
13610 guint32 cols [MONO_DECL_SECURITY_SIZE];
13611 int index = mono_metadata_declsec_from_index (image, token);
13614 t = &image->tables [MONO_TABLE_DECLSECURITY];
13615 for (i = index; i < t->rows; i++) {
13616 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13618 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13621 /* if present only replace (class) permissions with method permissions */
13622 /* if empty accept either class or method permissions */
13623 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13624 if (!actions->demand.blob) {
13625 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13626 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13627 actions->demand.blob = (char*) (blob + 2);
13628 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13631 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13632 if (!actions->noncasdemand.blob) {
13633 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13634 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13635 actions->noncasdemand.blob = (char*) (blob + 2);
13636 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13639 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13640 if (!actions->demandchoice.blob) {
13641 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13642 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13643 actions->demandchoice.blob = (char*) (blob + 2);
13644 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13654 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13655 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13657 guint32 idx = mono_metadata_token_index (klass->type_token);
13658 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13659 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13660 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13664 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13665 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13667 guint32 idx = mono_method_get_index (method);
13668 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13669 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13670 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13674 * Collect all actions (that requires to generate code in mini) assigned for
13675 * the specified method.
13676 * Note: Don't use the content of actions if the function return FALSE.
13679 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13681 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13682 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13683 MonoBoolean result = FALSE;
13686 /* quick exit if no declarative security is present in the metadata */
13687 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13690 /* we want the original as the wrapper is "free" of the security informations */
13691 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13692 method = mono_marshal_method_from_wrapper (method);
13697 /* First we look for method-level attributes */
13698 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13699 mono_class_init (method->klass);
13700 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13702 result = mono_declsec_get_method_demands_params (method, demands,
13703 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13706 /* Here we use (or create) the class declarative cache to look for demands */
13707 flags = mono_declsec_flags_from_class (method->klass);
13708 if (flags & mask) {
13710 mono_class_init (method->klass);
13711 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13713 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13714 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13717 /* The boolean return value is used as a shortcut in case nothing needs to
13718 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13724 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13726 * Note: Don't use the content of actions if the function return FALSE.
13729 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13731 MonoBoolean result = FALSE;
13734 /* quick exit if no declarative security is present in the metadata */
13735 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13738 /* we want the original as the wrapper is "free" of the security informations */
13739 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13740 method = mono_marshal_method_from_wrapper (method);
13745 /* results are independant - zeroize both */
13746 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13747 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13749 /* First we look for method-level attributes */
13750 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13751 mono_class_init (method->klass);
13753 result = mono_declsec_get_method_demands_params (method, cmethod,
13754 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13757 /* Here we use (or create) the class declarative cache to look for demands */
13758 flags = mono_declsec_flags_from_class (method->klass);
13759 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13760 mono_class_init (method->klass);
13762 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13763 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13770 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13772 * @klass The inherited class - this is the class that provides the security check (attributes)
13774 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13776 * Note: Don't use the content of actions if the function return FALSE.
13779 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13781 MonoBoolean result = FALSE;
13784 /* quick exit if no declarative security is present in the metadata */
13785 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13788 /* Here we use (or create) the class declarative cache to look for demands */
13789 flags = mono_declsec_flags_from_class (klass);
13790 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13791 mono_class_init (klass);
13792 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13794 result |= mono_declsec_get_class_demands_params (klass, demands,
13795 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13802 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13804 * Note: Don't use the content of actions if the function return FALSE.
13807 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13809 /* quick exit if no declarative security is present in the metadata */
13810 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13813 /* we want the original as the wrapper is "free" of the security informations */
13814 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13815 method = mono_marshal_method_from_wrapper (method);
13820 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13821 mono_class_init (method->klass);
13822 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13824 return mono_declsec_get_method_demands_params (method, demands,
13825 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13832 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13834 guint32 cols [MONO_DECL_SECURITY_SIZE];
13838 int index = mono_metadata_declsec_from_index (image, token);
13842 t = &image->tables [MONO_TABLE_DECLSECURITY];
13843 for (i = index; i < t->rows; i++) {
13844 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13846 /* shortcut - index are ordered */
13847 if (token != cols [MONO_DECL_SECURITY_PARENT])
13850 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13851 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13852 entry->blob = (char*) (metadata + 2);
13853 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13862 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13864 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13865 guint32 idx = mono_method_get_index (method);
13866 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13867 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13868 return get_declsec_action (method->klass->image, idx, action, entry);
13874 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13877 guint32 flags = mono_declsec_flags_from_class (klass);
13878 if (declsec_flags_map [action] & flags) {
13879 guint32 idx = mono_metadata_token_index (klass->type_token);
13880 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13881 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13882 return get_declsec_action (klass->image, idx, action, entry);
13888 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13890 guint32 idx = 1; /* there is only one assembly */
13891 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13892 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13894 return get_declsec_action (assembly->image, idx, action, entry);
13898 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13901 MonoObject *res, *exc;
13903 static MonoMethod *method = NULL;
13905 if (method == NULL) {
13906 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13911 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13912 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13914 g_assert (mono_class_get_ref_info (klass));
13915 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13917 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13918 mono_error_raise_exception (&error); /* FIXME don't raise here */
13920 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13922 if (exc || !mono_error_ok (&error)) {
13923 mono_error_cleanup (&error);
13926 return *(MonoBoolean*)mono_object_unbox (res);
13930 * mono_reflection_type_get_type:
13931 * @reftype: the System.Type object
13933 * Returns the MonoType* associated with the C# System.Type object @reftype.
13936 mono_reflection_type_get_type (MonoReflectionType *reftype)
13938 g_assert (reftype);
13940 return mono_reflection_type_get_handle (reftype);
13944 * mono_reflection_assembly_get_assembly:
13945 * @refassembly: the System.Reflection.Assembly object
13947 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13950 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13952 g_assert (refassembly);
13954 return refassembly->assembly;