2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) 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)
7364 static MonoClass *System_Reflection_ParameterInfo;
7365 static MonoClass *System_Reflection_ParameterInfo_array;
7367 MonoArray *res = NULL;
7368 MonoReflectionMethod *member = NULL;
7369 MonoReflectionParameter *param = NULL;
7370 char **names = NULL, **blobs = NULL;
7371 guint32 *types = NULL;
7372 MonoType *type = NULL;
7373 MonoObject *dbnull = NULL;
7374 MonoObject *missing = NULL;
7375 MonoMarshalSpec **mspecs = NULL;
7376 MonoMethodSignature *sig = NULL;
7377 MonoVTable *pinfo_vtable;
7378 MonoReflectionType *rt;
7381 mono_error_init (&error);
7383 if (!System_Reflection_ParameterInfo_array) {
7386 klass = mono_class_get_mono_parameter_info_class ();
7388 mono_memory_barrier ();
7389 System_Reflection_ParameterInfo = klass;
7392 klass = mono_array_class_get (klass, 1);
7393 mono_memory_barrier ();
7394 System_Reflection_ParameterInfo_array = klass;
7397 sig = mono_method_signature_checked (method, &error);
7398 if (!mono_error_ok (&error))
7401 if (!sig->param_count) {
7402 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7409 /* Note: the cache is based on the address of the signature into the method
7410 * since we already cache MethodInfos with the method as keys.
7412 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7414 member = mono_method_get_object_checked (domain, method, refclass, &error);
7417 names = g_new (char *, sig->param_count);
7418 mono_method_get_param_names (method, (const char **) names);
7420 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7421 mono_method_get_marshal_info (method, mspecs);
7423 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7427 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7428 for (i = 0; i < sig->param_count; ++i) {
7429 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7433 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7437 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7439 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7441 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7443 param->PositionImpl = i;
7444 param->AttrsImpl = sig->params [i]->attrs;
7446 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7447 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7448 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7450 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7454 blobs = g_new0 (char *, sig->param_count);
7455 types = g_new0 (guint32, sig->param_count);
7456 get_default_param_value_blobs (method, blobs, types);
7459 /* Build MonoType for the type from the Constant Table */
7461 type = g_new0 (MonoType, 1);
7462 type->type = (MonoTypeEnum)types [i];
7463 type->data.klass = NULL;
7464 if (types [i] == MONO_TYPE_CLASS)
7465 type->data.klass = mono_defaults.object_class;
7466 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7467 /* For enums, types [i] contains the base type */
7469 type->type = MONO_TYPE_VALUETYPE;
7470 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7472 type->data.klass = mono_class_from_mono_type (type);
7474 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7476 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7477 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7478 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7479 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7481 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7486 if (mspecs [i + 1]) {
7487 MonoReflectionMarshalAsAttribute* mobj;
7488 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7491 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7494 mono_array_setref (res, i, param);
7504 for (i = sig->param_count; i >= 0; i--) {
7506 mono_metadata_free_marshal_spec (mspecs [i]);
7511 mono_error_raise_exception (&error); /* FIXME don't raise here */
7513 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7517 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7519 return mono_param_get_objects_internal (domain, method, NULL);
7523 * mono_method_body_get_object:
7524 * @domain: an app domain
7527 * Return an System.Reflection.MethodBody object representing the method @method.
7529 MonoReflectionMethodBody*
7530 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7533 MonoReflectionMethodBody *ret;
7534 MonoMethodHeader *header;
7536 MonoReflectionType *rt;
7537 guint32 method_rva, local_var_sig_token;
7539 unsigned char format, flags;
7542 /* for compatibility with .net */
7543 if (method_is_dynamic (method))
7544 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7546 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7548 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7549 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7550 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7551 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7552 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7555 image = method->klass->image;
7556 header = mono_method_get_header_checked (method, &error);
7557 mono_error_raise_exception (&error); /* FIXME don't raise here */
7559 if (!image_is_dynamic (image)) {
7560 /* Obtain local vars signature token */
7561 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7562 ptr = mono_image_rva_map (image, method_rva);
7563 flags = *(const unsigned char *) ptr;
7564 format = flags & METHOD_HEADER_FORMAT_MASK;
7566 case METHOD_HEADER_TINY_FORMAT:
7567 local_var_sig_token = 0;
7569 case METHOD_HEADER_FAT_FORMAT:
7573 local_var_sig_token = read32 (ptr);
7576 g_assert_not_reached ();
7579 local_var_sig_token = 0; //FIXME
7581 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7582 mono_error_raise_exception (&error); /* FIXME don't raise here */
7584 ret->init_locals = header->init_locals;
7585 ret->max_stack = header->max_stack;
7586 ret->local_var_sig_token = local_var_sig_token;
7587 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7588 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7591 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7592 for (i = 0; i < header->num_locals; ++i) {
7593 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7594 mono_error_raise_exception (&error); /* FIXME don't raise here */
7596 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7597 mono_error_raise_exception (&error); /* FIXME don't raise here */
7599 MONO_OBJECT_SETREF (info, local_type, rt);
7601 info->is_pinned = header->locals [i]->pinned;
7602 info->local_index = i;
7603 mono_array_setref (ret->locals, i, info);
7607 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7608 for (i = 0; i < header->num_clauses; ++i) {
7609 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7610 mono_error_raise_exception (&error); /* FIXME don't raise here */
7611 MonoExceptionClause *clause = &header->clauses [i];
7613 info->flags = clause->flags;
7614 info->try_offset = clause->try_offset;
7615 info->try_length = clause->try_len;
7616 info->handler_offset = clause->handler_offset;
7617 info->handler_length = clause->handler_len;
7618 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7619 info->filter_offset = clause->data.filter_offset;
7620 else if (clause->data.catch_class) {
7621 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7622 mono_error_raise_exception (&error); /* FIXME don't raise here */
7624 MONO_OBJECT_SETREF (info, catch_type, rt);
7627 mono_array_setref (ret->clauses, i, info);
7630 mono_metadata_free_mh (header);
7631 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7636 * mono_get_dbnull_object:
7637 * @domain: Domain where the object lives
7639 * Returns the System.DBNull.Value singleton object
7641 * Used as the value for ParameterInfo.DefaultValue
7644 mono_get_dbnull_object (MonoDomain *domain)
7647 static MonoClassField *dbnull_value_field = NULL;
7649 if (!dbnull_value_field) {
7650 MonoClass *dbnull_klass;
7651 dbnull_klass = mono_class_get_dbnull_class ();
7652 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7653 g_assert (dbnull_value_field);
7655 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7661 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7663 guint32 param_index, i, lastp, crow = 0;
7664 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7667 MonoClass *klass = method->klass;
7668 MonoImage *image = klass->image;
7669 MonoMethodSignature *methodsig = mono_method_signature (method);
7671 MonoTableInfo *constt;
7672 MonoTableInfo *methodt;
7673 MonoTableInfo *paramt;
7675 if (!methodsig->param_count)
7678 mono_class_init (klass);
7680 if (image_is_dynamic (klass->image)) {
7681 MonoReflectionMethodAux *aux;
7682 if (method->is_inflated)
7683 method = ((MonoMethodInflated*)method)->declaring;
7684 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7685 if (aux && aux->param_defaults) {
7686 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7687 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7692 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7693 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7694 constt = &image->tables [MONO_TABLE_CONSTANT];
7696 idx = mono_method_get_index (method) - 1;
7697 g_assert (idx != -1);
7699 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7700 if (idx + 1 < methodt->rows)
7701 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7703 lastp = paramt->rows + 1;
7705 for (i = param_index; i < lastp; ++i) {
7708 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7709 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7711 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7714 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7719 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7720 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7721 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7728 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7734 MonoType *basetype = type;
7739 klass = mono_class_from_mono_type (type);
7740 if (klass->valuetype) {
7741 object = mono_object_new_checked (domain, klass, &error);
7742 mono_error_raise_exception (&error); /* FIXME don't raise here */
7743 retval = ((gchar *) object + sizeof (MonoObject));
7744 if (klass->enumtype)
7745 basetype = mono_class_enum_basetype (klass);
7750 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7757 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7760 gboolean quoted = FALSE;
7762 memset (assembly, 0, sizeof (MonoAssemblyName));
7763 assembly->culture = "";
7764 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7771 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7782 /* Remove trailing whitespace */
7784 while (*s && g_ascii_isspace (*s))
7787 while (g_ascii_isspace (*p))
7790 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7792 assembly->major = strtoul (p, &s, 10);
7793 if (s == p || *s != '.')
7796 assembly->minor = strtoul (p, &s, 10);
7797 if (s == p || *s != '.')
7800 assembly->build = strtoul (p, &s, 10);
7801 if (s == p || *s != '.')
7804 assembly->revision = strtoul (p, &s, 10);
7808 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7810 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7811 assembly->culture = "";
7814 assembly->culture = p;
7815 while (*p && *p != ',') {
7819 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7821 if (strncmp (p, "null", 4) == 0) {
7826 while (*p && *p != ',') {
7829 len = (p - start + 1);
7830 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7831 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7832 g_strlcpy ((char*)assembly->public_key_token, start, len);
7835 while (*p && *p != ',')
7839 while (g_ascii_isspace (*p) || *p == ',') {
7853 * mono_reflection_parse_type:
7856 * Parse a type name as accepted by the GetType () method and output the info
7857 * extracted in the info structure.
7858 * the name param will be mangled, so, make a copy before passing it to this function.
7859 * The fields in info will be valid until the memory pointed to by name is valid.
7861 * See also mono_type_get_name () below.
7863 * Returns: 0 on parse error.
7866 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7867 MonoTypeNameParse *info)
7869 char *start, *p, *w, *last_point, *startn;
7870 int in_modifiers = 0;
7871 int isbyref = 0, rank = 0, isptr = 0;
7873 start = p = w = name;
7875 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7876 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7877 info->name = info->name_space = NULL;
7878 info->nested = NULL;
7879 info->modifiers = NULL;
7880 info->type_arguments = NULL;
7882 /* last_point separates the namespace from the name */
7885 while (*p == ' ') p++, start++, w++, name++;
7890 *p = 0; /* NULL terminate the name */
7892 info->nested = g_list_append (info->nested, startn);
7893 /* we have parsed the nesting namespace + name */
7897 info->name_space = start;
7899 info->name = last_point + 1;
7901 info->name_space = (char *)"";
7929 info->name_space = start;
7931 info->name = last_point + 1;
7933 info->name_space = (char *)"";
7940 if (isbyref) /* only one level allowed by the spec */
7944 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7948 if (isbyref) /* pointer to ref not okay */
7950 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7955 if (isbyref) /* array of ref and generic ref are not okay */
7957 //Decide if it's an array of a generic argument list
7962 if (*p == ',' || *p == '*' || *p == ']') { //array
7970 else if (*p == '*') /* '*' means unknown lower bound */
7971 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7978 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7980 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7983 info->type_arguments = g_ptr_array_new ();
7985 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7986 gboolean fqname = FALSE;
7988 g_ptr_array_add (info->type_arguments, subinfo);
7990 while (*p == ' ') p++;
7996 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7999 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8000 if (fqname && (*p != ']')) {
8008 while (*p && (*p != ']'))
8016 if (g_ascii_isspace (*aname)) {
8023 !assembly_name_to_aname (&subinfo->assembly, aname))
8025 } else if (fqname && (*p == ']')) {
8047 if (g_ascii_isspace (*p)) {
8054 return 0; /* missing assembly name */
8055 if (!assembly_name_to_aname (&info->assembly, p))
8061 if (info->assembly.name)
8064 // *w = 0; /* terminate class name */
8066 if (!info->name || !*info->name)
8070 /* add other consistency checks */
8076 * mono_identifier_unescape_type_name_chars:
8077 * @identifier: the display name of a mono type
8080 * The name in internal form, that is without escaping backslashes.
8082 * The string is modified in place!
8085 mono_identifier_unescape_type_name_chars(char* identifier)
8090 for (w = r = identifier; *r != 0; r++)
8108 mono_identifier_unescape_info (MonoTypeNameParse* info);
8111 unescape_each_type_argument(void* data, void* user_data)
8113 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8114 mono_identifier_unescape_info (info);
8118 unescape_each_nested_name (void* data, void* user_data)
8120 char* nested_name = (char*) data;
8121 mono_identifier_unescape_type_name_chars(nested_name);
8125 * mono_identifier_unescape_info:
8127 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8131 * Destructively updates the info by unescaping the identifiers that
8132 * comprise the type namespace, name, nested types (if any) and
8133 * generic type arguments (if any).
8135 * The resulting info has the names in internal form.
8139 mono_identifier_unescape_info (MonoTypeNameParse *info)
8143 mono_identifier_unescape_type_name_chars(info->name_space);
8144 mono_identifier_unescape_type_name_chars(info->name);
8145 // but don't escape info->assembly
8146 if (info->type_arguments)
8147 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8149 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8153 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8155 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8157 mono_identifier_unescape_info (info);
8163 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8165 gboolean type_resolve = FALSE;
8167 MonoImage *rootimage = image;
8169 mono_error_init (error);
8171 if (info->assembly.name) {
8172 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8173 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8175 * This could happen in the AOT compiler case when the search hook is not
8178 assembly = image->assembly;
8180 /* then we must load the assembly ourselve - see #60439 */
8181 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8185 image = assembly->image;
8186 } else if (!image) {
8187 image = mono_defaults.corlib;
8190 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8191 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8192 mono_error_cleanup (error);
8193 image = mono_defaults.corlib;
8194 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8201 * mono_reflection_get_type_internal:
8203 * Returns: may return NULL on success, sets error on failure.
8206 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8211 gboolean bounded = FALSE;
8213 mono_error_init (error);
8215 image = mono_defaults.corlib;
8218 rootimage = mono_defaults.corlib;
8221 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8223 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8228 for (mod = info->nested; mod; mod = mod->next) {
8229 gpointer iter = NULL;
8233 mono_class_init (parent);
8235 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8237 char *nested_name, *nested_nspace;
8238 gboolean match = TRUE;
8240 lastp = strrchr ((const char *)mod->data, '.');
8242 /* Nested classes can have namespaces */
8245 nested_name = g_strdup (lastp + 1);
8246 nspace_len = lastp - (char*)mod->data;
8247 nested_nspace = (char *)g_malloc (nspace_len + 1);
8248 memcpy (nested_nspace, mod->data, nspace_len);
8249 nested_nspace [nspace_len] = '\0';
8252 nested_name = (char *)mod->data;
8253 nested_nspace = NULL;
8256 if (nested_nspace) {
8258 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8261 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8267 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8270 if (strcmp (klass->name, nested_name) != 0)
8275 g_free (nested_name);
8276 g_free (nested_nspace);
8288 if (info->type_arguments) {
8289 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8290 MonoReflectionType *the_type;
8294 for (i = 0; i < info->type_arguments->len; i++) {
8295 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8297 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8298 if (!type_args [i]) {
8304 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8308 instance = mono_reflection_bind_generic_parameters (
8309 the_type, info->type_arguments->len, type_args);
8315 klass = mono_class_from_mono_type (instance);
8318 for (mod = info->modifiers; mod; mod = mod->next) {
8319 modval = GPOINTER_TO_UINT (mod->data);
8320 if (!modval) { /* byref: must be last modifier */
8321 return &klass->this_arg;
8322 } else if (modval == -1) {
8323 klass = mono_ptr_class_get (&klass->byval_arg);
8324 } else if (modval == -2) {
8326 } else { /* array rank */
8327 klass = mono_bounded_array_class_get (klass, modval, bounded);
8331 return &klass->byval_arg;
8335 * mono_reflection_get_type:
8336 * @image: a metadata context
8337 * @info: type description structure
8338 * @ignorecase: flag for case-insensitive string compares
8339 * @type_resolve: whenever type resolve was already tried
8341 * Build a MonoType from the type description in @info.
8346 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8348 MonoType *result = mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve, &error);
8349 mono_error_raise_exception (&error); /* FIXME don't raise here */
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, MonoError *error)
8398 MonoReflectionAssembly *assembly;
8402 mono_error_init (error);
8404 if (image && image_is_dynamic (image))
8405 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8407 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8409 return_val_if_nok (error, NULL);
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 if (!is_ok (error)) {
8434 g_string_free (fullName, TRUE);
8439 if (assembly_is_dynamic (assembly->assembly))
8440 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8441 info, ignorecase, error);
8443 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8444 info, ignorecase, error);
8446 g_string_free (fullName, TRUE);
8447 return_val_if_nok (error, NULL);
8452 mono_reflection_free_type_info (MonoTypeNameParse *info)
8454 g_list_free (info->modifiers);
8455 g_list_free (info->nested);
8457 if (info->type_arguments) {
8460 for (i = 0; i < info->type_arguments->len; i++) {
8461 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8463 mono_reflection_free_type_info (subinfo);
8464 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8468 g_ptr_array_free (info->type_arguments, TRUE);
8473 * mono_reflection_type_from_name:
8475 * @image: a metadata context (can be NULL).
8477 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8478 * it defaults to get the type from @image or, if @image is NULL or loading
8479 * from it fails, uses corlib.
8483 mono_reflection_type_from_name (char *name, MonoImage *image)
8486 MonoType *type = NULL;
8487 MonoTypeNameParse info;
8490 /* Make a copy since parse_type modifies its argument */
8491 tmp = g_strdup (name);
8493 /*g_print ("requested type %s\n", str);*/
8494 if (mono_reflection_parse_type (tmp, &info)) {
8495 type = _mono_reflection_get_type_from_info (&info, image, FALSE, &error);
8496 if (!is_ok (&error)) {
8498 mono_reflection_free_type_info (&info);
8499 mono_error_raise_exception (&error); /* FIXME don't raise here */
8504 mono_reflection_free_type_info (&info);
8509 * mono_reflection_get_token:
8511 * Return the metadata token of OBJ which should be an object
8512 * representing a metadata element.
8515 mono_reflection_get_token (MonoObject *obj)
8520 klass = obj->vtable->klass;
8522 if (strcmp (klass->name, "MethodBuilder") == 0) {
8523 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8525 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8526 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8527 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8529 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8530 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8531 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8533 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8534 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8536 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8537 } else if (strcmp (klass->name, "MonoType") == 0) {
8538 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8539 MonoClass *mc = mono_class_from_mono_type (type);
8540 if (!mono_class_init (mc))
8541 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8543 token = mc->type_token;
8544 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8545 strcmp (klass->name, "MonoMethod") == 0 ||
8546 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8547 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8548 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8549 if (m->method->is_inflated) {
8550 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8551 return inflated->declaring->token;
8553 token = m->method->token;
8555 } else if (strcmp (klass->name, "MonoField") == 0) {
8556 MonoReflectionField *f = (MonoReflectionField*)obj;
8558 if (is_field_on_inst (f->field)) {
8559 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8561 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8562 int field_index = f->field - dgclass->fields;
8565 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8566 obj = dgclass->field_objects [field_index];
8567 return mono_reflection_get_token (obj);
8570 token = mono_class_get_field_token (f->field);
8571 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8572 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8574 token = mono_class_get_property_token (p->property);
8575 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8576 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8578 token = mono_class_get_event_token (p->event);
8579 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8580 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8581 MonoClass *member_class = mono_object_class (p->MemberImpl);
8582 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8584 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8585 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8586 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8589 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8590 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8592 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8593 MonoException *ex = mono_get_exception_not_implemented (msg);
8595 mono_raise_exception (ex);
8602 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8606 int slen = mono_metadata_decode_value (p, &p);
8608 mono_error_init (error);
8610 n = (char *)g_memdup (p, slen + 1);
8612 t = mono_reflection_type_from_name (n, image);
8614 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8615 /* We don't free n, it's consumed by mono_error */
8616 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8622 return mono_class_from_mono_type (t);
8626 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8628 int slen, type = t->type;
8629 MonoClass *tklass = t->data.klass;
8631 mono_error_init (error);
8637 case MONO_TYPE_BOOLEAN: {
8638 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8643 case MONO_TYPE_CHAR:
8645 case MONO_TYPE_I2: {
8646 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8651 #if SIZEOF_VOID_P == 4
8657 case MONO_TYPE_I4: {
8658 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8663 #if SIZEOF_VOID_P == 8
8664 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8668 case MONO_TYPE_I8: {
8669 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8674 case MONO_TYPE_R8: {
8675 double *val = (double *)g_malloc (sizeof (double));
8680 case MONO_TYPE_VALUETYPE:
8681 if (t->data.klass->enumtype) {
8682 type = mono_class_enum_basetype (t->data.klass)->type;
8685 MonoClass *k = t->data.klass;
8687 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8688 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8694 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8697 case MONO_TYPE_STRING:
8698 if (*p == (char)0xFF) {
8702 slen = mono_metadata_decode_value (p, &p);
8704 return mono_string_new_len (mono_domain_get (), p, slen);
8705 case MONO_TYPE_CLASS: {
8706 MonoReflectionType *rt;
8709 if (*p == (char)0xFF) {
8714 slen = mono_metadata_decode_value (p, &p);
8715 n = (char *)g_memdup (p, slen + 1);
8717 t = mono_reflection_type_from_name (n, image);
8719 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8720 /* We don't free n, it's consumed by mono_error */
8721 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8727 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8728 if (!mono_error_ok (error))
8733 case MONO_TYPE_OBJECT: {
8736 MonoClass *subc = NULL;
8741 } else if (subt == 0x0E) {
8742 type = MONO_TYPE_STRING;
8744 } else if (subt == 0x1D) {
8745 MonoType simple_type = {{0}};
8749 type = MONO_TYPE_SZARRAY;
8750 if (etype == 0x50) {
8751 tklass = mono_defaults.systemtype_class;
8752 } else if (etype == 0x55) {
8753 tklass = load_cattr_enum_type (image, p, &p, error);
8754 if (!mono_error_ok (error))
8758 /* See Partition II, Appendix B3 */
8759 etype = MONO_TYPE_OBJECT;
8760 simple_type.type = (MonoTypeEnum)etype;
8761 tklass = mono_class_from_mono_type (&simple_type);
8764 } else if (subt == 0x55) {
8767 slen = mono_metadata_decode_value (p, &p);
8768 n = (char *)g_memdup (p, slen + 1);
8770 t = mono_reflection_type_from_name (n, image);
8772 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8773 /* We don't free n, it's consumed by mono_error */
8774 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8779 subc = mono_class_from_mono_type (t);
8780 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8781 MonoType simple_type = {{0}};
8782 simple_type.type = (MonoTypeEnum)subt;
8783 subc = mono_class_from_mono_type (&simple_type);
8785 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8787 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8789 if (mono_error_ok (error)) {
8790 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8791 g_assert (!subc->has_references);
8792 if (mono_error_ok (error))
8793 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8799 case MONO_TYPE_SZARRAY: {
8801 guint32 i, alen, basetype;
8804 if (alen == 0xffffffff) {
8808 arr = mono_array_new (mono_domain_get(), tklass, alen);
8809 basetype = tklass->byval_arg.type;
8810 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8811 basetype = mono_class_enum_basetype (tklass)->type;
8816 case MONO_TYPE_BOOLEAN:
8817 for (i = 0; i < alen; i++) {
8818 MonoBoolean val = *p++;
8819 mono_array_set (arr, MonoBoolean, i, val);
8822 case MONO_TYPE_CHAR:
8825 for (i = 0; i < alen; i++) {
8826 guint16 val = read16 (p);
8827 mono_array_set (arr, guint16, i, val);
8834 for (i = 0; i < alen; i++) {
8835 guint32 val = read32 (p);
8836 mono_array_set (arr, guint32, i, val);
8841 for (i = 0; i < alen; i++) {
8844 mono_array_set (arr, double, i, val);
8850 for (i = 0; i < alen; i++) {
8851 guint64 val = read64 (p);
8852 mono_array_set (arr, guint64, i, val);
8856 case MONO_TYPE_CLASS:
8857 case MONO_TYPE_OBJECT:
8858 case MONO_TYPE_STRING:
8859 case MONO_TYPE_SZARRAY:
8860 for (i = 0; i < alen; i++) {
8861 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8862 if (!mono_error_ok (error))
8864 mono_array_setref (arr, i, item);
8868 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8874 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8880 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8882 static MonoMethod *ctor;
8884 void *params [2], *unboxed;
8886 mono_error_init (error);
8889 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8891 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8892 return_val_if_nok (error, NULL);
8895 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8896 return_val_if_nok (error, NULL);
8897 unboxed = mono_object_unbox (retval);
8899 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8900 return_val_if_nok (error, NULL);
8906 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8908 static MonoMethod *ctor;
8910 void *unboxed, *params [2];
8912 mono_error_init (error);
8915 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8918 params [1] = typedarg;
8919 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8920 return_val_if_nok (error, NULL);
8922 unboxed = mono_object_unbox (retval);
8924 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8925 return_val_if_nok (error, NULL);
8931 type_is_reference (MonoType *type)
8933 switch (type->type) {
8934 case MONO_TYPE_BOOLEAN:
8935 case MONO_TYPE_CHAR:
8948 case MONO_TYPE_VALUETYPE:
8956 free_param_data (MonoMethodSignature *sig, void **params) {
8958 for (i = 0; i < sig->param_count; ++i) {
8959 if (!type_is_reference (sig->params [i]))
8960 g_free (params [i]);
8965 * Find the field index in the metadata FieldDef table.
8968 find_field_index (MonoClass *klass, MonoClassField *field) {
8971 for (i = 0; i < klass->field.count; ++i) {
8972 if (field == &klass->fields [i])
8973 return klass->field.first + 1 + i;
8979 * Find the property index in the metadata Property table.
8982 find_property_index (MonoClass *klass, MonoProperty *property) {
8985 for (i = 0; i < klass->ext->property.count; ++i) {
8986 if (property == &klass->ext->properties [i])
8987 return klass->ext->property.first + 1 + i;
8993 * Find the event index in the metadata Event table.
8996 find_event_index (MonoClass *klass, MonoEvent *event) {
8999 for (i = 0; i < klass->ext->event.count; ++i) {
9000 if (event == &klass->ext->events [i])
9001 return klass->ext->event.first + 1 + i;
9007 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9009 const char *p = (const char*)data;
9011 guint32 i, j, num_named;
9013 void *params_buf [32];
9014 void **params = NULL;
9015 MonoMethodSignature *sig;
9016 MonoObject *exc = NULL;
9018 mono_error_init (error);
9020 mono_class_init (method->klass);
9022 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9023 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9028 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9029 if (!mono_error_ok (error)) return NULL;
9031 mono_runtime_invoke_checked (method, attr, NULL, error);
9032 if (!mono_error_ok (error))
9038 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9041 /*g_print ("got attr %s\n", method->klass->name);*/
9043 sig = mono_method_signature (method);
9044 if (sig->param_count < 32) {
9045 params = params_buf;
9046 memset (params, 0, sizeof (void*) * sig->param_count);
9048 /* Allocate using GC so it gets GC tracking */
9049 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9054 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9055 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9056 if (!mono_error_ok (error))
9061 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9062 if (!mono_error_ok (error)) goto fail;
9064 mono_runtime_try_invoke (method, attr, params, &exc, error);
9065 if (!mono_error_ok (error))
9070 num_named = read16 (named);
9072 for (j = 0; j < num_named; j++) {
9074 char *name, named_type, data_type;
9075 named_type = *named++;
9076 data_type = *named++; /* type of data */
9077 if (data_type == MONO_TYPE_SZARRAY)
9078 data_type = *named++;
9079 if (data_type == MONO_TYPE_ENUM) {
9082 type_len = mono_metadata_decode_blob_size (named, &named);
9083 type_name = (char *)g_malloc (type_len + 1);
9084 memcpy (type_name, named, type_len);
9085 type_name [type_len] = 0;
9087 /* FIXME: lookup the type and check type consistency */
9090 name_len = mono_metadata_decode_blob_size (named, &named);
9091 name = (char *)g_malloc (name_len + 1);
9092 memcpy (name, named, name_len);
9093 name [name_len] = 0;
9095 if (named_type == 0x53) {
9096 MonoClassField *field;
9099 /* how this fail is a blackbox */
9100 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9102 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9107 val = load_cattr_value (image, field->type, named, &named, error);
9108 if (!mono_error_ok (error)) {
9110 if (!type_is_reference (field->type))
9115 mono_field_set_value (attr, field, val);
9116 if (!type_is_reference (field->type))
9118 } else if (named_type == 0x54) {
9121 MonoType *prop_type;
9123 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9126 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9132 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9137 /* can we have more that 1 arg in a custom attr named property? */
9138 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9139 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9141 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9142 if (!mono_error_ok (error)) {
9144 if (!type_is_reference (prop_type))
9145 g_free (pparams [0]);
9150 mono_property_set_value (prop, attr, pparams, NULL);
9151 if (!type_is_reference (prop_type))
9152 g_free (pparams [0]);
9157 free_param_data (method->signature, params);
9158 if (params != params_buf)
9159 mono_gc_free_fixed (params);
9164 free_param_data (method->signature, params);
9165 if (params != params_buf)
9166 mono_gc_free_fixed (params);
9168 mono_raise_exception ((MonoException*)exc);
9173 * mono_reflection_create_custom_attr_data_args:
9175 * Create an array of typed and named arguments from the cattr blob given by DATA.
9176 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9177 * NAMED_ARG_INFO will contain information about the named arguments.
9180 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)
9182 MonoArray *typedargs, *namedargs;
9183 MonoClass *attrklass;
9185 const char *p = (const char*)data;
9187 guint32 i, j, num_named;
9188 CattrNamedArg *arginfo = NULL;
9192 *named_arg_info = NULL;
9194 mono_error_init (error);
9196 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9197 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9201 mono_class_init (method->klass);
9203 domain = mono_domain_get ();
9205 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9208 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9212 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9216 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9217 if (!mono_error_ok (error)) {
9218 if (!type_is_reference (mono_method_signature (method)->params [i]))
9223 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9224 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9225 mono_array_setref (typedargs, i, obj);
9227 if (!type_is_reference (mono_method_signature (method)->params [i]))
9232 num_named = read16 (named);
9233 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9235 attrklass = method->klass;
9237 arginfo = g_new0 (CattrNamedArg, num_named);
9238 *named_arg_info = arginfo;
9240 for (j = 0; j < num_named; j++) {
9242 char *name, named_type, data_type;
9243 named_type = *named++;
9244 data_type = *named++; /* type of data */
9245 if (data_type == MONO_TYPE_SZARRAY)
9246 data_type = *named++;
9247 if (data_type == MONO_TYPE_ENUM) {
9250 type_len = mono_metadata_decode_blob_size (named, &named);
9251 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9254 type_name = (char *)g_malloc (type_len + 1);
9255 memcpy (type_name, named, type_len);
9256 type_name [type_len] = 0;
9258 /* FIXME: lookup the type and check type consistency */
9261 name_len = mono_metadata_decode_blob_size (named, &named);
9262 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9264 name = (char *)g_malloc (name_len + 1);
9265 memcpy (name, named, name_len);
9266 name [name_len] = 0;
9268 if (named_type == 0x53) {
9270 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9278 arginfo [j].type = field->type;
9279 arginfo [j].field = field;
9281 val = load_cattr_value (image, field->type, named, &named, error);
9282 if (!mono_error_ok (error)) {
9283 if (!type_is_reference (field->type))
9289 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9290 mono_array_setref (namedargs, j, obj);
9291 if (!type_is_reference (field->type))
9293 } else if (named_type == 0x54) {
9295 MonoType *prop_type;
9296 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9299 if (!prop || !prop->set) {
9304 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9305 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9307 arginfo [j].type = prop_type;
9308 arginfo [j].prop = prop;
9310 val = load_cattr_value (image, prop_type, named, &named, error);
9311 if (!mono_error_ok (error)) {
9312 if (!type_is_reference (prop_type))
9318 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9319 mono_array_setref (namedargs, j, obj);
9320 if (!type_is_reference (prop_type))
9326 *typed_args = typedargs;
9327 *named_args = namedargs;
9330 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9332 *named_arg_info = NULL;
9336 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9339 MonoArray *typedargs, *namedargs;
9342 CattrNamedArg *arginfo = NULL;
9346 mono_error_init (&error);
9354 image = assembly->assembly->image;
9355 method = ref_method->method;
9356 domain = mono_object_domain (ref_method);
9358 if (!mono_class_init (method->klass))
9359 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9361 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9362 if (!mono_error_ok (&error))
9365 if (mono_loader_get_last_error ()) {
9366 mono_error_set_from_loader_error (&error);
9370 if (!typedargs || !namedargs)
9373 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9374 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9375 MonoObject *typedarg;
9377 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9378 if (!is_ok (&error))
9380 mono_array_setref (typedargs, i, typedarg);
9383 for (i = 0; i < mono_array_length (namedargs); ++i) {
9384 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9385 MonoObject *typedarg, *namedarg, *minfo;
9387 if (arginfo [i].prop) {
9388 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9392 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9393 if (!mono_error_ok (&error))
9397 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9398 if (!is_ok (&error))
9400 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9401 if (!is_ok (&error))
9404 mono_array_setref (namedargs, i, namedarg);
9407 *ctor_args = typedargs;
9408 *named_args = namedargs;
9411 mono_error_raise_exception (&error);
9416 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9418 static MonoMethod *ctor;
9424 mono_error_init (error);
9426 g_assert (image->assembly);
9429 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9431 domain = mono_domain_get ();
9432 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9433 return_val_if_nok (error, NULL);
9434 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9435 return_val_if_nok (error, NULL);
9436 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9437 return_val_if_nok (error, NULL);
9438 params [2] = (gpointer)&cattr->data;
9439 params [3] = &cattr->data_size;
9441 mono_runtime_invoke_checked (ctor, attr, params, error);
9442 return_val_if_nok (error, NULL);
9447 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9453 mono_error_init (error);
9456 for (i = 0; i < cinfo->num_attrs; ++i) {
9457 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9461 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9463 for (i = 0; i < cinfo->num_attrs; ++i) {
9464 if (!cinfo->attrs [i].ctor) {
9465 /* The cattr type is not finished yet */
9466 /* We should include the type name but cinfo doesn't contain it */
9467 mono_error_set_type_load_name (error, NULL, NULL, "");
9470 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9471 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9472 if (!mono_error_ok (error))
9474 mono_array_setref (result, n, attr);
9482 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9485 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9486 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9492 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9498 mono_error_init (error);
9499 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9500 for (i = 0; i < cinfo->num_attrs; ++i) {
9501 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9502 return_val_if_nok (error, NULL);
9503 mono_array_setref (result, i, attr);
9509 * mono_custom_attrs_from_index:
9511 * Returns: NULL if no attributes are found or if a loading error occurs.
9514 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9517 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9518 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9522 * mono_custom_attrs_from_index_checked:
9524 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9527 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9529 guint32 mtoken, i, len;
9530 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9532 MonoCustomAttrInfo *ainfo;
9533 GList *tmp, *list = NULL;
9535 MonoCustomAttrEntry* attr;
9537 mono_error_init (error);
9539 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9541 i = mono_metadata_custom_attrs_from_index (image, idx);
9545 while (i < ca->rows) {
9546 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9548 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9551 len = g_list_length (list);
9554 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9555 ainfo->num_attrs = len;
9556 ainfo->image = image;
9557 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9558 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9559 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9560 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9561 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9562 mtoken |= MONO_TOKEN_METHOD_DEF;
9564 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9565 mtoken |= MONO_TOKEN_MEMBER_REF;
9568 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9571 attr = &ainfo->attrs [i - 1];
9572 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9574 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9580 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9581 /*FIXME raising an exception here doesn't make any sense*/
9582 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9587 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9588 attr->data_size = mono_metadata_decode_value (data, &data);
9589 attr->data = (guchar*)data;
9597 mono_custom_attrs_from_method (MonoMethod *method)
9600 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9601 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9606 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9610 mono_error_init (error);
9613 * An instantiated method has the same cattrs as the generic method definition.
9615 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9616 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9618 if (method->is_inflated)
9619 method = ((MonoMethodInflated *) method)->declaring;
9621 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9622 return lookup_custom_attr (method->klass->image, method);
9625 /* Synthetic methods */
9628 idx = mono_method_get_index (method);
9629 idx <<= MONO_CUSTOM_ATTR_BITS;
9630 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9631 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9635 mono_custom_attrs_from_class (MonoClass *klass)
9638 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9639 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9644 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9648 mono_error_init (error);
9650 if (klass->generic_class)
9651 klass = klass->generic_class->container_class;
9653 if (image_is_dynamic (klass->image))
9654 return lookup_custom_attr (klass->image, klass);
9656 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9657 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9658 idx <<= MONO_CUSTOM_ATTR_BITS;
9659 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9661 idx = mono_metadata_token_index (klass->type_token);
9662 idx <<= MONO_CUSTOM_ATTR_BITS;
9663 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9665 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9669 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9672 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9673 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9678 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9682 mono_error_init (error);
9684 if (image_is_dynamic (assembly->image))
9685 return lookup_custom_attr (assembly->image, assembly);
9686 idx = 1; /* there is only one assembly */
9687 idx <<= MONO_CUSTOM_ATTR_BITS;
9688 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9689 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9692 static MonoCustomAttrInfo*
9693 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9697 if (image_is_dynamic (image))
9698 return lookup_custom_attr (image, image);
9699 idx = 1; /* there is only one module */
9700 idx <<= MONO_CUSTOM_ATTR_BITS;
9701 idx |= MONO_CUSTOM_ATTR_MODULE;
9702 return mono_custom_attrs_from_index_checked (image, idx, error);
9706 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9709 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9710 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9715 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9719 if (image_is_dynamic (klass->image)) {
9720 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9721 return lookup_custom_attr (klass->image, property);
9723 idx = find_property_index (klass, property);
9724 idx <<= MONO_CUSTOM_ATTR_BITS;
9725 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9726 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9730 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9733 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9734 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9739 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9743 if (image_is_dynamic (klass->image)) {
9744 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9745 return lookup_custom_attr (klass->image, event);
9747 idx = find_event_index (klass, event);
9748 idx <<= MONO_CUSTOM_ATTR_BITS;
9749 idx |= MONO_CUSTOM_ATTR_EVENT;
9750 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9754 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9757 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9758 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9763 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9766 mono_error_init (error);
9768 if (image_is_dynamic (klass->image)) {
9769 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9770 return lookup_custom_attr (klass->image, field);
9772 idx = find_field_index (klass, field);
9773 idx <<= MONO_CUSTOM_ATTR_BITS;
9774 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9775 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9779 * mono_custom_attrs_from_param:
9780 * @method: handle to the method that we want to retrieve custom parameter information from
9781 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9783 * The result must be released with mono_custom_attrs_free().
9785 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9788 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9791 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9792 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9797 * mono_custom_attrs_from_param_checked:
9798 * @method: handle to the method that we want to retrieve custom parameter information from
9799 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9800 * @error: set on error
9802 * The result must be released with mono_custom_attrs_free().
9804 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9807 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9810 guint32 i, idx, method_index;
9811 guint32 param_list, param_last, param_pos, found;
9813 MonoReflectionMethodAux *aux;
9815 mono_error_init (error);
9818 * An instantiated method has the same cattrs as the generic method definition.
9820 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9821 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9823 if (method->is_inflated)
9824 method = ((MonoMethodInflated *) method)->declaring;
9826 if (image_is_dynamic (method->klass->image)) {
9827 MonoCustomAttrInfo *res, *ainfo;
9830 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9831 if (!aux || !aux->param_cattr)
9834 /* Need to copy since it will be freed later */
9835 ainfo = aux->param_cattr [param];
9838 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9839 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9840 memcpy (res, ainfo, size);
9844 image = method->klass->image;
9845 method_index = mono_method_get_index (method);
9848 ca = &image->tables [MONO_TABLE_METHOD];
9850 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9851 if (method_index == ca->rows) {
9852 ca = &image->tables [MONO_TABLE_PARAM];
9853 param_last = ca->rows + 1;
9855 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9856 ca = &image->tables [MONO_TABLE_PARAM];
9859 for (i = param_list; i < param_last; ++i) {
9860 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9861 if (param_pos == param) {
9869 idx <<= MONO_CUSTOM_ATTR_BITS;
9870 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9871 return mono_custom_attrs_from_index_checked (image, idx, error);
9875 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9879 for (i = 0; i < ainfo->num_attrs; ++i) {
9880 klass = ainfo->attrs [i].ctor->klass;
9881 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9888 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9891 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9892 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9897 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9903 mono_error_init (error);
9906 for (i = 0; i < ainfo->num_attrs; ++i) {
9907 klass = ainfo->attrs [i].ctor->klass;
9908 if (mono_class_has_parent (klass, attr_klass)) {
9913 if (attr_index == -1)
9916 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9917 if (!mono_error_ok (error))
9919 return mono_array_get (attrs, MonoObject*, attr_index);
9923 * mono_reflection_get_custom_attrs_info:
9924 * @obj: a reflection object handle
9926 * Return the custom attribute info for attributes defined for the
9927 * reflection handle @obj. The objects.
9929 * FIXME this function leaks like a sieve for SRE objects.
9932 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9935 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9936 mono_error_assert_ok (&error);
9941 * mono_reflection_get_custom_attrs_info_checked:
9942 * @obj: a reflection object handle
9943 * @error: set on error
9945 * Return the custom attribute info for attributes defined for the
9946 * reflection handle @obj. The objects.
9948 * On failure returns NULL and sets @error.
9950 * FIXME this function leaks like a sieve for SRE objects.
9953 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9956 MonoCustomAttrInfo *cinfo = NULL;
9958 mono_error_init (error);
9960 klass = obj->vtable->klass;
9961 if (klass == mono_defaults.monotype_class) {
9962 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9963 klass = mono_class_from_mono_type (type);
9964 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9965 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9966 return_val_if_nok (error, NULL);
9967 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9968 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9969 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9970 return_val_if_nok (error, NULL);
9971 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9972 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9973 cinfo = mono_custom_attrs_from_module (module->image, error);
9974 return_val_if_nok (error, NULL);
9975 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9976 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9977 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9978 return_val_if_nok (error, NULL);
9979 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9980 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9981 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9982 return_val_if_nok (error, NULL);
9983 } else if (strcmp ("MonoField", klass->name) == 0) {
9984 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9985 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9986 return_val_if_nok (error, NULL);
9987 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9988 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9989 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9990 return_val_if_nok (error, NULL);
9991 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9992 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9993 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9994 return_val_if_nok (error, NULL);
9995 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9996 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9997 MonoClass *member_class = mono_object_class (param->MemberImpl);
9998 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9999 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10000 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10001 return_val_if_nok (error, NULL);
10002 } else if (is_sr_mono_property (member_class)) {
10003 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10004 MonoMethod *method;
10005 if (!(method = prop->property->get))
10006 method = prop->property->set;
10009 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10010 return_val_if_nok (error, NULL);
10012 #ifndef DISABLE_REFLECTION_EMIT
10013 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10014 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10015 return_val_if_nok (error, NULL);
10016 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10017 return_val_if_nok (error, NULL);
10018 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10019 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10020 MonoMethod *method = NULL;
10021 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10022 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10023 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10024 method = ((MonoReflectionMethod *)c->cb)->method;
10026 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));
10028 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10029 return_val_if_nok (error, NULL);
10033 char *type_name = mono_type_get_full_name (member_class);
10034 mono_error_set_generic_error (error, "System", "NotSupportedException",
10035 "Custom attributes on a ParamInfo with member %s are not supported",
10037 g_free (type_name);
10040 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10041 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10042 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10043 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10044 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10045 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10046 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10047 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10048 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10049 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10050 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10051 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10052 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10053 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10054 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10055 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10056 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10057 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10058 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10059 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10060 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10061 return_val_if_nok (error, NULL);
10062 } else { /* handle other types here... */
10063 g_error ("get custom attrs not yet supported for %s", klass->name);
10070 * mono_reflection_get_custom_attrs_by_type:
10071 * @obj: a reflection object handle
10073 * Return an array with all the custom attributes defined of the
10074 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10075 * of that type are returned. The objects are fully build. Return NULL if a loading error
10079 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10082 MonoCustomAttrInfo *cinfo;
10084 mono_error_init (error);
10086 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10087 return_val_if_nok (error, NULL);
10089 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10092 if (!cinfo->cached)
10093 mono_custom_attrs_free (cinfo);
10095 mono_loader_assert_no_error ();
10096 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10103 * mono_reflection_get_custom_attrs:
10104 * @obj: a reflection object handle
10106 * Return an array with all the custom attributes defined of the
10107 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10111 mono_reflection_get_custom_attrs (MonoObject *obj)
10115 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10119 * mono_reflection_get_custom_attrs_data:
10120 * @obj: a reflection obj handle
10122 * Returns an array of System.Reflection.CustomAttributeData,
10123 * which include information about attributes reflected on
10124 * types loaded using the Reflection Only methods
10127 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10131 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10132 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10137 * mono_reflection_get_custom_attrs_data_checked:
10138 * @obj: a reflection obj handle
10139 * @error: set on error
10141 * Returns an array of System.Reflection.CustomAttributeData,
10142 * which include information about attributes reflected on
10143 * types loaded using the Reflection Only methods
10146 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10149 MonoCustomAttrInfo *cinfo;
10151 mono_error_init (error);
10153 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10154 return_val_if_nok (error, NULL);
10156 result = mono_custom_attrs_data_construct (cinfo, error);
10157 return_val_if_nok (error, NULL);
10158 if (!cinfo->cached)
10159 mono_custom_attrs_free (cinfo);
10161 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10163 if (mono_loader_get_last_error ())
10164 mono_error_set_from_loader_error (error);
10169 static MonoReflectionType*
10170 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10172 static MonoMethod *method_get_underlying_system_type = NULL;
10173 MonoReflectionType *rt;
10174 MonoMethod *usertype_method;
10176 mono_error_init (error);
10178 if (!method_get_underlying_system_type)
10179 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10181 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10183 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10190 is_corlib_type (MonoClass *klass)
10192 return klass->image == mono_defaults.corlib;
10195 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10196 static MonoClass *cached_class; \
10197 if (cached_class) \
10198 return cached_class == _class; \
10199 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10200 cached_class = _class; \
10207 #ifndef DISABLE_REFLECTION_EMIT
10209 is_sre_array (MonoClass *klass)
10211 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10215 is_sre_byref (MonoClass *klass)
10217 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10221 is_sre_pointer (MonoClass *klass)
10223 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10227 is_sre_generic_instance (MonoClass *klass)
10229 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10233 is_sre_type_builder (MonoClass *klass)
10235 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10239 is_sre_method_builder (MonoClass *klass)
10241 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10245 is_sre_ctor_builder (MonoClass *klass)
10247 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10251 is_sre_field_builder (MonoClass *klass)
10253 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10257 is_sre_method_on_tb_inst (MonoClass *klass)
10259 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10263 is_sre_ctor_on_tb_inst (MonoClass *klass)
10265 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10269 mono_reflection_type_get_handle (MonoReflectionType* ref)
10278 if (is_usertype (ref)) {
10279 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10280 mono_error_raise_exception (&error); /* FIXME don't raise here */
10281 if (ref == NULL || is_usertype (ref))
10287 klass = mono_object_class (ref);
10289 if (is_sre_array (klass)) {
10291 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10292 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10294 if (sre_array->rank == 0) //single dimentional array
10295 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10297 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10298 sre_array->type.type = res;
10300 } else if (is_sre_byref (klass)) {
10302 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10303 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10305 res = &mono_class_from_mono_type (base)->this_arg;
10306 sre_byref->type.type = res;
10308 } else if (is_sre_pointer (klass)) {
10310 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10311 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10313 res = &mono_ptr_class_get (base)->byval_arg;
10314 sre_pointer->type.type = res;
10316 } else if (is_sre_generic_instance (klass)) {
10317 MonoType *res, **types;
10318 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10321 count = mono_array_length (gclass->type_arguments);
10322 types = g_new0 (MonoType*, count);
10323 for (i = 0; i < count; ++i) {
10324 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10325 types [i] = mono_reflection_type_get_handle (t);
10332 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10335 gclass->type.type = res;
10339 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10346 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10348 mono_reflection_type_get_handle (type);
10352 mono_reflection_register_with_runtime (MonoReflectionType *type)
10354 MonoType *res = mono_reflection_type_get_handle (type);
10355 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10359 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10361 klass = mono_class_from_mono_type (res);
10363 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10364 mono_domain_lock (domain);
10366 if (!image_is_dynamic (klass->image)) {
10367 mono_class_setup_supertypes (klass);
10369 if (!domain->type_hash)
10370 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10371 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10372 mono_g_hash_table_insert (domain->type_hash, res, type);
10374 mono_domain_unlock (domain);
10375 mono_loader_unlock ();
10379 * LOCKING: Assumes the loader lock is held.
10381 static MonoMethodSignature*
10382 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10383 MonoMethodSignature *sig;
10386 count = parameters? mono_array_length (parameters): 0;
10388 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10389 sig->param_count = count;
10390 sig->sentinelpos = -1; /* FIXME */
10391 for (i = 0; i < count; ++i)
10392 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10397 * LOCKING: Assumes the loader lock is held.
10399 static MonoMethodSignature*
10400 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10401 MonoMethodSignature *sig;
10403 sig = parameters_to_signature (image, ctor->parameters);
10404 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10405 sig->ret = &mono_defaults.void_class->byval_arg;
10410 * LOCKING: Assumes the loader lock is held.
10412 static MonoMethodSignature*
10413 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10414 MonoMethodSignature *sig;
10416 sig = parameters_to_signature (image, method->parameters);
10417 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10418 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10419 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10423 static MonoMethodSignature*
10424 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10425 MonoMethodSignature *sig;
10427 sig = parameters_to_signature (NULL, method->parameters);
10428 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10429 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10430 sig->generic_param_count = 0;
10435 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10437 MonoClass *klass = mono_object_class (prop);
10438 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10439 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10440 *name = mono_string_to_utf8 (pb->name);
10441 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10443 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10444 *name = g_strdup (p->property->name);
10445 if (p->property->get)
10446 *type = mono_method_signature (p->property->get)->ret;
10448 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10453 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10455 MonoClass *klass = mono_object_class (field);
10456 if (strcmp (klass->name, "FieldBuilder") == 0) {
10457 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10458 *name = mono_string_to_utf8 (fb->name);
10459 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10461 MonoReflectionField *f = (MonoReflectionField *)field;
10462 *name = g_strdup (mono_field_get_name (f->field));
10463 *type = f->field->type;
10467 #else /* DISABLE_REFLECTION_EMIT */
10470 mono_reflection_register_with_runtime (MonoReflectionType *type)
10472 /* This is empty */
10476 is_sre_type_builder (MonoClass *klass)
10482 is_sre_generic_instance (MonoClass *klass)
10488 init_type_builder_generics (MonoObject *type)
10492 #endif /* !DISABLE_REFLECTION_EMIT */
10496 is_sr_mono_field (MonoClass *klass)
10498 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10502 is_sr_mono_property (MonoClass *klass)
10504 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10508 is_sr_mono_method (MonoClass *klass)
10510 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10514 is_sr_mono_cmethod (MonoClass *klass)
10516 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10520 is_sr_mono_generic_method (MonoClass *klass)
10522 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10526 is_sr_mono_generic_cmethod (MonoClass *klass)
10528 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10532 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10534 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10538 is_usertype (MonoReflectionType *ref)
10540 MonoClass *klass = mono_object_class (ref);
10541 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10544 static MonoReflectionType*
10545 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10547 mono_error_init (error);
10548 if (!type || type->type)
10551 if (is_usertype (type)) {
10552 type = mono_reflection_type_get_underlying_system_type (type, error);
10553 return_val_if_nok (error, NULL);
10554 if (is_usertype (type)) {
10555 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10563 * Encode a value in a custom attribute stream of bytes.
10564 * The value to encode is either supplied as an object in argument val
10565 * (valuetypes are boxed), or as a pointer to the data in the
10567 * @type represents the type of the value
10568 * @buffer is the start of the buffer
10569 * @p the current position in the buffer
10570 * @buflen contains the size of the buffer and is used to return the new buffer size
10571 * if this needs to be realloced.
10572 * @retbuffer and @retp return the start and the position of the buffer
10575 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10577 MonoTypeEnum simple_type;
10579 if ((p-buffer) + 10 >= *buflen) {
10582 newbuf = (char *)g_realloc (buffer, *buflen);
10583 p = newbuf + (p-buffer);
10587 argval = ((char*)arg + sizeof (MonoObject));
10588 simple_type = type->type;
10590 switch (simple_type) {
10591 case MONO_TYPE_BOOLEAN:
10596 case MONO_TYPE_CHAR:
10599 swap_with_size (p, argval, 2, 1);
10605 swap_with_size (p, argval, 4, 1);
10609 swap_with_size (p, argval, 8, 1);
10614 swap_with_size (p, argval, 8, 1);
10617 case MONO_TYPE_VALUETYPE:
10618 if (type->data.klass->enumtype) {
10619 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10622 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10625 case MONO_TYPE_STRING: {
10632 str = mono_string_to_utf8 ((MonoString*)arg);
10633 slen = strlen (str);
10634 if ((p-buffer) + 10 + slen >= *buflen) {
10638 newbuf = (char *)g_realloc (buffer, *buflen);
10639 p = newbuf + (p-buffer);
10642 mono_metadata_encode_value (slen, p, &p);
10643 memcpy (p, str, slen);
10648 case MONO_TYPE_CLASS: {
10656 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10657 slen = strlen (str);
10658 if ((p-buffer) + 10 + slen >= *buflen) {
10662 newbuf = (char *)g_realloc (buffer, *buflen);
10663 p = newbuf + (p-buffer);
10666 mono_metadata_encode_value (slen, p, &p);
10667 memcpy (p, str, slen);
10672 case MONO_TYPE_SZARRAY: {
10674 MonoClass *eclass, *arg_eclass;
10677 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10680 len = mono_array_length ((MonoArray*)arg);
10682 *p++ = (len >> 8) & 0xff;
10683 *p++ = (len >> 16) & 0xff;
10684 *p++ = (len >> 24) & 0xff;
10686 *retbuffer = buffer;
10687 eclass = type->data.klass;
10688 arg_eclass = mono_object_class (arg)->element_class;
10691 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10692 eclass = mono_defaults.object_class;
10694 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10695 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10696 int elsize = mono_class_array_element_size (arg_eclass);
10697 for (i = 0; i < len; ++i) {
10698 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10701 } else if (eclass->valuetype && arg_eclass->valuetype) {
10702 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10703 int elsize = mono_class_array_element_size (eclass);
10704 for (i = 0; i < len; ++i) {
10705 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10709 for (i = 0; i < len; ++i) {
10710 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10715 case MONO_TYPE_OBJECT: {
10721 * The parameter type is 'object' but the type of the actual
10722 * argument is not. So we have to add type information to the blob
10723 * too. This is completely undocumented in the spec.
10727 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10732 klass = mono_object_class (arg);
10734 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10737 } else if (klass->enumtype) {
10739 } else if (klass == mono_defaults.string_class) {
10740 simple_type = MONO_TYPE_STRING;
10743 } else if (klass->rank == 1) {
10745 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10746 /* See Partition II, Appendix B3 */
10749 *p++ = klass->element_class->byval_arg.type;
10750 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10752 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10753 *p++ = simple_type = klass->byval_arg.type;
10756 g_error ("unhandled type in custom attr");
10758 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10759 slen = strlen (str);
10760 if ((p-buffer) + 10 + slen >= *buflen) {
10764 newbuf = (char *)g_realloc (buffer, *buflen);
10765 p = newbuf + (p-buffer);
10768 mono_metadata_encode_value (slen, p, &p);
10769 memcpy (p, str, slen);
10772 simple_type = mono_class_enum_basetype (klass)->type;
10776 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10779 *retbuffer = buffer;
10783 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10785 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10786 char *str = type_get_qualified_name (type, NULL);
10787 int slen = strlen (str);
10791 * This seems to be optional...
10794 mono_metadata_encode_value (slen, p, &p);
10795 memcpy (p, str, slen);
10798 } else if (type->type == MONO_TYPE_OBJECT) {
10800 } else if (type->type == MONO_TYPE_CLASS) {
10801 /* it should be a type: encode_cattr_value () has the check */
10804 mono_metadata_encode_value (type->type, p, &p);
10805 if (type->type == MONO_TYPE_SZARRAY)
10806 /* See the examples in Partition VI, Annex B */
10807 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10813 #ifndef DISABLE_REFLECTION_EMIT
10815 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10818 /* Preallocate a large enough buffer */
10819 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10820 char *str = type_get_qualified_name (type, NULL);
10821 len = strlen (str);
10823 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10824 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10825 len = strlen (str);
10830 len += strlen (name);
10832 if ((p-buffer) + 20 + len >= *buflen) {
10836 newbuf = (char *)g_realloc (buffer, *buflen);
10837 p = newbuf + (p-buffer);
10841 encode_field_or_prop_type (type, p, &p);
10843 len = strlen (name);
10844 mono_metadata_encode_value (len, p, &p);
10845 memcpy (p, name, len);
10847 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10849 *retbuffer = buffer;
10853 * mono_reflection_get_custom_attrs_blob:
10854 * @ctor: custom attribute constructor
10855 * @ctorArgs: arguments o the constructor
10861 * Creates the blob of data that needs to be saved in the metadata and that represents
10862 * the custom attributed described by @ctor, @ctorArgs etc.
10863 * Returns: a Byte array representing the blob of data.
10866 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10869 MonoMethodSignature *sig;
10874 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10875 /* sig is freed later so allocate it in the heap */
10876 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10878 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10881 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10883 p = buffer = (char *)g_malloc (buflen);
10884 /* write the prolog */
10887 for (i = 0; i < sig->param_count; ++i) {
10888 arg = mono_array_get (ctorArgs, MonoObject*, i);
10889 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10893 i += mono_array_length (properties);
10895 i += mono_array_length (fields);
10897 *p++ = (i >> 8) & 0xff;
10900 for (i = 0; i < mono_array_length (properties); ++i) {
10904 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10905 get_prop_name_and_type (prop, &pname, &ptype);
10906 *p++ = 0x54; /* PROPERTY signature */
10907 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10914 for (i = 0; i < mono_array_length (fields); ++i) {
10918 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10919 get_field_name_and_type (field, &fname, &ftype);
10920 *p++ = 0x53; /* FIELD signature */
10921 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10926 g_assert (p - buffer <= buflen);
10927 buflen = p - buffer;
10928 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10929 p = mono_array_addr (result, char, 0);
10930 memcpy (p, buffer, buflen);
10932 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10938 * mono_reflection_setup_internal_class:
10939 * @tb: a TypeBuilder object
10941 * Creates a MonoClass that represents the TypeBuilder.
10942 * This is a trick that lets us simplify a lot of reflection code
10943 * (and will allow us to support Build and Run assemblies easier).
10946 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10949 MonoClass *klass, *parent;
10951 RESOLVE_TYPE (tb->parent, &error);
10952 mono_error_raise_exception (&error); /* FIXME don't raise here */
10954 mono_loader_lock ();
10957 /* check so we can compile corlib correctly */
10958 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10959 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10960 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10962 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10968 /* the type has already being created: it means we just have to change the parent */
10969 if (tb->type.type) {
10970 klass = mono_class_from_mono_type (tb->type.type);
10971 klass->parent = NULL;
10972 /* fool mono_class_setup_parent */
10973 klass->supertypes = NULL;
10974 mono_class_setup_parent (klass, parent);
10975 mono_class_setup_mono_type (klass);
10976 mono_loader_unlock ();
10980 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10982 klass->image = &tb->module->dynamic_image->image;
10984 klass->inited = 1; /* we lie to the runtime */
10985 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10986 if (!mono_error_ok (&error))
10988 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10989 if (!mono_error_ok (&error))
10991 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10992 klass->flags = tb->attrs;
10994 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10996 klass->element_class = klass;
10998 if (mono_class_get_ref_info (klass) == NULL) {
11000 mono_class_set_ref_info (klass, tb);
11002 /* Put into cache so mono_class_get_checked () will find it.
11003 Skip nested types as those should not be available on the global scope. */
11004 if (!tb->nesting_type)
11005 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11008 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11009 by performing a mono_class_get which does the full resolution.
11011 Working around this semantics would require us to write a lot of code for no clear advantage.
11013 mono_image_append_class_to_reflection_info_set (klass);
11015 g_assert (mono_class_get_ref_info (klass) == tb);
11018 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11020 if (parent != NULL) {
11021 mono_class_setup_parent (klass, parent);
11022 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11023 const char *old_n = klass->name;
11024 /* trick to get relative numbering right when compiling corlib */
11025 klass->name = "BuildingObject";
11026 mono_class_setup_parent (klass, mono_defaults.object_class);
11027 klass->name = old_n;
11030 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11031 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11032 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11033 klass->instance_size = sizeof (MonoObject);
11034 klass->size_inited = 1;
11035 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11038 mono_class_setup_mono_type (klass);
11040 mono_class_setup_supertypes (klass);
11043 * FIXME: handle interfaces.
11046 tb->type.type = &klass->byval_arg;
11048 if (tb->nesting_type) {
11049 g_assert (tb->nesting_type->type);
11050 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11053 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11055 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11057 mono_loader_unlock ();
11061 mono_loader_unlock ();
11062 mono_error_raise_exception (&error);
11066 * mono_reflection_setup_generic_class:
11067 * @tb: a TypeBuilder object
11069 * Setup the generic class before adding the first generic parameter.
11072 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11077 * mono_reflection_create_generic_class:
11078 * @tb: a TypeBuilder object
11080 * Creates the generic class after all generic parameters have been added.
11083 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11088 klass = mono_class_from_mono_type (tb->type.type);
11090 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11092 if (klass->generic_container || (count == 0))
11095 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11097 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11099 klass->generic_container->owner.klass = klass;
11100 klass->generic_container->type_argc = count;
11101 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11103 klass->is_generic = 1;
11105 for (i = 0; i < count; i++) {
11106 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11107 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11108 klass->generic_container->type_params [i] = *param;
11109 /*Make sure we are a diferent type instance */
11110 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11111 klass->generic_container->type_params [i].info.pklass = NULL;
11112 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11114 g_assert (klass->generic_container->type_params [i].param.owner);
11117 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11121 * mono_reflection_create_internal_class:
11122 * @tb: a TypeBuilder object
11124 * Actually create the MonoClass that is associated with the TypeBuilder.
11127 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11131 klass = mono_class_from_mono_type (tb->type.type);
11133 mono_loader_lock ();
11134 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11135 MonoReflectionFieldBuilder *fb;
11137 MonoType *enum_basetype;
11139 g_assert (tb->fields != NULL);
11140 g_assert (mono_array_length (tb->fields) >= 1);
11142 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11144 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11145 mono_loader_unlock ();
11149 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11150 klass->element_class = mono_class_from_mono_type (enum_basetype);
11151 if (!klass->element_class)
11152 klass->element_class = mono_class_from_mono_type (enum_basetype);
11155 * get the element_class from the current corlib.
11157 ec = default_class_from_mono_type (enum_basetype);
11158 klass->instance_size = ec->instance_size;
11159 klass->size_inited = 1;
11161 * this is almost safe to do with enums and it's needed to be able
11162 * to create objects of the enum type (for use in SetConstant).
11164 /* FIXME: Does this mean enums can't have method overrides ? */
11165 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11167 mono_loader_unlock ();
11170 static MonoMarshalSpec*
11171 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11172 MonoReflectionMarshal *minfo)
11174 MonoMarshalSpec *res;
11176 res = image_g_new0 (image, MonoMarshalSpec, 1);
11177 res->native = (MonoMarshalNative)minfo->type;
11179 switch (minfo->type) {
11180 case MONO_NATIVE_LPARRAY:
11181 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11182 if (minfo->has_size) {
11183 res->data.array_data.param_num = minfo->param_num;
11184 res->data.array_data.num_elem = minfo->count;
11185 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11188 res->data.array_data.param_num = -1;
11189 res->data.array_data.num_elem = -1;
11190 res->data.array_data.elem_mult = -1;
11194 case MONO_NATIVE_BYVALTSTR:
11195 case MONO_NATIVE_BYVALARRAY:
11196 res->data.array_data.num_elem = minfo->count;
11199 case MONO_NATIVE_CUSTOM:
11200 if (minfo->marshaltyperef)
11201 res->data.custom_data.custom_name =
11202 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11203 if (minfo->mcookie)
11204 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11213 #endif /* !DISABLE_REFLECTION_EMIT */
11215 MonoReflectionMarshalAsAttribute*
11216 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11217 MonoMarshalSpec *spec, MonoError *error)
11219 MonoReflectionType *rt;
11220 MonoReflectionMarshalAsAttribute *minfo;
11223 mono_error_init (error);
11225 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11228 minfo->utype = spec->native;
11230 switch (minfo->utype) {
11231 case MONO_NATIVE_LPARRAY:
11232 minfo->array_subtype = spec->data.array_data.elem_type;
11233 minfo->size_const = spec->data.array_data.num_elem;
11234 if (spec->data.array_data.param_num != -1)
11235 minfo->size_param_index = spec->data.array_data.param_num;
11238 case MONO_NATIVE_BYVALTSTR:
11239 case MONO_NATIVE_BYVALARRAY:
11240 minfo->size_const = spec->data.array_data.num_elem;
11243 case MONO_NATIVE_CUSTOM:
11244 if (spec->data.custom_data.custom_name) {
11245 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11247 rt = mono_type_get_object_checked (domain, mtype, error);
11251 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11254 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11256 if (spec->data.custom_data.cookie)
11257 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11267 #ifndef DISABLE_REFLECTION_EMIT
11269 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11270 ReflectionMethodBuilder *rmb,
11271 MonoMethodSignature *sig)
11275 MonoMethodWrapper *wrapperm;
11276 MonoMarshalSpec **specs;
11277 MonoReflectionMethodAux *method_aux;
11282 mono_error_init (&error);
11284 * Methods created using a MethodBuilder should have their memory allocated
11285 * inside the image mempool, while dynamic methods should have their memory
11288 dynamic = rmb->refs != NULL;
11289 image = dynamic ? NULL : klass->image;
11292 g_assert (!klass->generic_class);
11294 mono_loader_lock ();
11296 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11297 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11298 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11300 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11302 wrapperm = (MonoMethodWrapper*)m;
11304 m->dynamic = dynamic;
11306 m->flags = rmb->attrs;
11307 m->iflags = rmb->iattrs;
11308 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11310 m->signature = sig;
11311 m->sre_method = TRUE;
11312 m->skip_visibility = rmb->skip_visibility;
11313 if (rmb->table_idx)
11314 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11316 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11317 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11318 m->string_ctor = 1;
11320 m->signature->pinvoke = 1;
11321 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11322 m->signature->pinvoke = 1;
11324 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11326 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11327 g_assert (mono_error_ok (&error));
11328 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11329 g_assert (mono_error_ok (&error));
11331 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11333 if (image_is_dynamic (klass->image))
11334 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11336 mono_loader_unlock ();
11339 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11340 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11341 MonoMethodHeader *header;
11343 gint32 max_stack, i;
11344 gint32 num_locals = 0;
11345 gint32 num_clauses = 0;
11349 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11350 code_size = rmb->ilgen->code_len;
11351 max_stack = rmb->ilgen->max_stack;
11352 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11353 if (rmb->ilgen->ex_handlers)
11354 num_clauses = method_count_clauses (rmb->ilgen);
11357 code = mono_array_addr (rmb->code, guint8, 0);
11358 code_size = mono_array_length (rmb->code);
11359 /* we probably need to run a verifier on the code... */
11369 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11370 header->code_size = code_size;
11371 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11372 memcpy ((char*)header->code, code, code_size);
11373 header->max_stack = max_stack;
11374 header->init_locals = rmb->init_locals;
11375 header->num_locals = num_locals;
11377 for (i = 0; i < num_locals; ++i) {
11378 MonoReflectionLocalBuilder *lb =
11379 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11381 header->locals [i] = image_g_new0 (image, MonoType, 1);
11382 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11385 header->num_clauses = num_clauses;
11387 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11388 rmb->ilgen, num_clauses);
11391 wrapperm->header = header;
11394 if (rmb->generic_params) {
11395 int count = mono_array_length (rmb->generic_params);
11396 MonoGenericContainer *container = rmb->generic_container;
11398 g_assert (container);
11400 container->type_argc = count;
11401 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11402 container->owner.method = m;
11403 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11405 m->is_generic = TRUE;
11406 mono_method_set_generic_container (m, container);
11408 for (i = 0; i < count; i++) {
11409 MonoReflectionGenericParam *gp =
11410 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11411 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11412 container->type_params [i] = *param;
11416 * The method signature might have pointers to generic parameters that belong to other methods.
11417 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11418 * generic parameters.
11420 for (i = 0; i < m->signature->param_count; ++i) {
11421 MonoType *t = m->signature->params [i];
11422 if (t->type == MONO_TYPE_MVAR) {
11423 MonoGenericParam *gparam = t->data.generic_param;
11424 if (gparam->num < count) {
11425 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11426 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11432 if (klass->generic_container) {
11433 container->parent = klass->generic_container;
11434 container->context.class_inst = klass->generic_container->context.class_inst;
11436 container->context.method_inst = mono_get_shared_generic_inst (container);
11440 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11444 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11446 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11447 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11448 for (i = 0; i < rmb->nrefs; ++i)
11449 data [i + 1] = rmb->refs [i];
11454 /* Parameter info */
11457 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11458 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11459 for (i = 0; i <= m->signature->param_count; ++i) {
11460 MonoReflectionParamBuilder *pb;
11461 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11462 if ((i > 0) && (pb->attrs)) {
11463 /* Make a copy since it might point to a shared type structure */
11464 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11465 m->signature->params [i - 1]->attrs = pb->attrs;
11468 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11469 MonoDynamicImage *assembly;
11471 MonoTypeEnum def_type;
11475 if (!method_aux->param_defaults) {
11476 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11477 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11479 assembly = (MonoDynamicImage*)klass->image;
11480 idx = encode_constant (assembly, pb->def_value, &def_type);
11481 /* Copy the data from the blob since it might get realloc-ed */
11482 p = assembly->blob.data + idx;
11483 len = mono_metadata_decode_blob_size (p, &p2);
11485 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11486 method_aux->param_default_types [i] = def_type;
11487 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11491 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11492 g_assert (mono_error_ok (&error));
11495 if (!method_aux->param_cattr)
11496 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11497 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11503 /* Parameter marshalling */
11506 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11507 MonoReflectionParamBuilder *pb;
11508 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11509 if (pb->marshal_info) {
11511 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11512 specs [pb->position] =
11513 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11517 if (specs != NULL) {
11519 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11520 method_aux->param_marshall = specs;
11523 if (image_is_dynamic (klass->image) && method_aux)
11524 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11526 mono_loader_unlock ();
11532 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11534 ReflectionMethodBuilder rmb;
11535 MonoMethodSignature *sig;
11537 mono_loader_lock ();
11538 sig = ctor_builder_to_signature (klass->image, mb);
11539 mono_loader_unlock ();
11541 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11544 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11545 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11547 /* If we are in a generic class, we might be called multiple times from inflate_method */
11548 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11549 /* ilgen is no longer needed */
11553 return mb->mhandle;
11557 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11559 ReflectionMethodBuilder rmb;
11560 MonoMethodSignature *sig;
11562 mono_error_init (error);
11564 mono_loader_lock ();
11565 sig = method_builder_to_signature (klass->image, mb);
11566 mono_loader_unlock ();
11568 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11571 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11572 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11574 /* If we are in a generic class, we might be called multiple times from inflate_method */
11575 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11576 /* ilgen is no longer needed */
11579 return mb->mhandle;
11582 static MonoClassField*
11583 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11585 MonoClassField *field;
11589 field = g_new0 (MonoClassField, 1);
11591 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11592 g_assert (mono_error_ok (&error));
11593 if (fb->attrs || fb->modreq || fb->modopt) {
11594 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11595 field->type->attrs = fb->attrs;
11597 g_assert (image_is_dynamic (klass->image));
11598 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11599 g_free (field->type);
11600 field->type = mono_metadata_type_dup (klass->image, custom);
11603 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11605 if (fb->offset != -1)
11606 field->offset = fb->offset;
11607 field->parent = klass;
11608 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11610 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11617 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11620 MonoReflectionTypeBuilder *tb = NULL;
11621 gboolean is_dynamic = FALSE;
11622 MonoClass *geninst;
11624 mono_loader_lock ();
11626 if (is_sre_type_builder (mono_object_class (type))) {
11627 tb = (MonoReflectionTypeBuilder *) type;
11630 } else if (is_sre_generic_instance (mono_object_class (type))) {
11631 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11632 MonoReflectionType *gtd = rgi->generic_type;
11634 if (is_sre_type_builder (mono_object_class (gtd))) {
11635 tb = (MonoReflectionTypeBuilder *)gtd;
11640 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11641 if (tb && tb->generic_container)
11642 mono_reflection_create_generic_class (tb);
11644 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11645 if (!klass->generic_container) {
11646 mono_loader_unlock ();
11650 if (klass->wastypebuilder) {
11651 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11656 mono_loader_unlock ();
11658 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11660 return &geninst->byval_arg;
11664 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11666 MonoGenericClass *gclass;
11667 MonoGenericInst *inst;
11669 g_assert (klass->generic_container);
11671 inst = mono_metadata_get_generic_inst (type_argc, types);
11672 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11674 return mono_generic_class_get_class (gclass);
11677 MonoReflectionMethod*
11678 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11682 MonoMethod *method, *inflated;
11683 MonoMethodInflated *imethod;
11684 MonoGenericContext tmp_context;
11685 MonoGenericInst *ginst;
11686 MonoType **type_argv;
11689 /*FIXME but this no longer should happen*/
11690 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11691 #ifndef DISABLE_REFLECTION_EMIT
11692 MonoReflectionMethodBuilder *mb = NULL;
11693 MonoReflectionTypeBuilder *tb;
11696 mb = (MonoReflectionMethodBuilder *) rmethod;
11697 tb = (MonoReflectionTypeBuilder *) mb->type;
11698 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11700 method = methodbuilder_to_mono_method (klass, mb, &error);
11702 mono_error_raise_exception (&error); /* FIXME don't raise here */
11704 g_assert_not_reached ();
11708 method = rmethod->method;
11711 klass = method->klass;
11713 if (method->is_inflated)
11714 method = ((MonoMethodInflated *) method)->declaring;
11716 count = mono_method_signature (method)->generic_param_count;
11717 if (count != mono_array_length (types))
11720 type_argv = g_new0 (MonoType *, count);
11721 for (i = 0; i < count; i++) {
11722 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11723 type_argv [i] = mono_reflection_type_get_handle (garg);
11725 ginst = mono_metadata_get_generic_inst (count, type_argv);
11726 g_free (type_argv);
11728 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11729 tmp_context.method_inst = ginst;
11731 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11732 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11733 imethod = (MonoMethodInflated *) inflated;
11735 /*FIXME but I think this is no longer necessary*/
11736 if (image_is_dynamic (method->klass->image)) {
11737 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11739 * This table maps metadata structures representing inflated methods/fields
11740 * to the reflection objects representing their generic definitions.
11742 mono_image_lock ((MonoImage*)image);
11743 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11744 mono_image_unlock ((MonoImage*)image);
11747 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11748 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11750 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11751 mono_error_raise_exception (&error); /* FIXME don't raise here */
11755 #ifndef DISABLE_REFLECTION_EMIT
11757 static MonoMethod *
11758 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11760 MonoMethodInflated *imethod;
11761 MonoGenericContext *context;
11765 * With generic code sharing the klass might not be inflated.
11766 * This can happen because classes inflated with their own
11767 * type arguments are "normalized" to the uninflated class.
11769 if (!klass->generic_class)
11772 context = mono_class_get_context (klass);
11774 if (klass->method.count && klass->methods) {
11775 /* Find the already created inflated method */
11776 for (i = 0; i < klass->method.count; ++i) {
11777 g_assert (klass->methods [i]->is_inflated);
11778 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11781 g_assert (i < klass->method.count);
11782 imethod = (MonoMethodInflated*)klass->methods [i];
11785 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11786 mono_error_assert_ok (&error);
11789 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11790 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11792 mono_image_lock ((MonoImage*)image);
11793 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11794 mono_image_unlock ((MonoImage*)image);
11796 return (MonoMethod *) imethod;
11799 static MonoMethod *
11800 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11802 MonoMethod *method;
11805 mono_error_init (error);
11807 MonoClass *type_class = mono_object_class (type);
11809 if (is_sre_generic_instance (type_class)) {
11810 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11811 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11812 } else if (is_sre_type_builder (type_class)) {
11813 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11814 } else if (type->type) {
11815 gklass = mono_class_from_mono_type (type->type);
11816 gklass = mono_class_get_generic_type_definition (gklass);
11818 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11821 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11822 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11823 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11825 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11829 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11830 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11833 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11834 method = ((MonoReflectionMethod *) obj)->method;
11836 method = NULL; /* prevent compiler warning */
11837 g_error ("can't handle type %s", obj->vtable->klass->name);
11840 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11843 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11845 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11847 MonoGenericClass *gclass;
11848 MonoDynamicGenericClass *dgclass;
11849 MonoClass *klass, *gklass;
11853 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11854 klass = mono_class_from_mono_type (gtype);
11855 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11856 gclass = gtype->data.generic_class;
11858 if (!gclass->is_dynamic)
11861 dgclass = (MonoDynamicGenericClass *) gclass;
11863 if (dgclass->initialized)
11866 gklass = gclass->container_class;
11867 mono_class_init (gklass);
11869 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11871 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11872 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11873 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11875 for (i = 0; i < dgclass->count_fields; i++) {
11877 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11878 MonoClassField *field, *inflated_field = NULL;
11880 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11881 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11882 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11883 field = ((MonoReflectionField *) obj)->field;
11885 field = NULL; /* prevent compiler warning */
11886 g_assert_not_reached ();
11889 dgclass->fields [i] = *field;
11890 dgclass->fields [i].parent = klass;
11891 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
11892 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
11893 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
11894 dgclass->field_generic_types [i] = field->type;
11895 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11896 dgclass->field_objects [i] = obj;
11898 if (inflated_field) {
11899 g_free (inflated_field);
11901 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11905 dgclass->initialized = TRUE;
11909 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11911 MonoDynamicGenericClass *dgclass;
11914 g_assert (gclass->is_dynamic);
11916 dgclass = (MonoDynamicGenericClass *)gclass;
11918 for (i = 0; i < dgclass->count_fields; ++i) {
11919 MonoClassField *field = dgclass->fields + i;
11920 mono_metadata_free_type (field->type);
11921 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11926 fix_partial_generic_class (MonoClass *klass)
11928 MonoClass *gklass = klass->generic_class->container_class;
11929 MonoDynamicGenericClass *dgclass;
11932 if (klass->wastypebuilder)
11935 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11936 if (klass->parent != gklass->parent) {
11938 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11939 if (mono_error_ok (&error)) {
11940 MonoClass *parent = mono_class_from_mono_type (parent_type);
11941 mono_metadata_free_type (parent_type);
11942 if (parent != klass->parent) {
11943 /*fool mono_class_setup_parent*/
11944 klass->supertypes = NULL;
11945 mono_class_setup_parent (klass, parent);
11948 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11949 mono_error_cleanup (&error);
11950 if (gklass->wastypebuilder)
11951 klass->wastypebuilder = TRUE;
11956 if (!dgclass->initialized)
11959 if (klass->method.count != gklass->method.count) {
11960 klass->method.count = gklass->method.count;
11961 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11963 for (i = 0; i < klass->method.count; i++) {
11965 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11966 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11967 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11971 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11972 klass->interface_count = gklass->interface_count;
11973 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11974 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11976 for (i = 0; i < gklass->interface_count; ++i) {
11978 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
11979 mono_error_raise_exception (&error); /* FIXME don't raise here */
11981 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11982 mono_metadata_free_type (iface_type);
11984 ensure_runtime_vtable (klass->interfaces [i], &error);
11985 mono_error_raise_exception (&error); /* FIXME don't raise here */
11987 klass->interfaces_inited = 1;
11990 if (klass->field.count != gklass->field.count) {
11991 klass->field.count = gklass->field.count;
11992 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11994 for (i = 0; i < klass->field.count; i++) {
11996 klass->fields [i] = gklass->fields [i];
11997 klass->fields [i].parent = klass;
11998 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
11999 mono_error_raise_exception (&error); /* FIXME don't raise here */
12003 /*We can only finish with this klass once it's parent has as well*/
12004 if (gklass->wastypebuilder)
12005 klass->wastypebuilder = TRUE;
12010 * ensure_generic_class_runtime_vtable:
12011 * @klass a generic class
12012 * @error set on error
12014 * Ensures that the generic container of @klass has a vtable and
12015 * returns TRUE on success. On error returns FALSE and sets @error.
12018 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12020 MonoClass *gklass = klass->generic_class->container_class;
12022 mono_error_init (error);
12024 if (!ensure_runtime_vtable (gklass, error))
12027 fix_partial_generic_class (klass);
12033 * ensure_runtime_vtable:
12035 * @error set on error
12037 * Ensures that @klass has a vtable and returns TRUE on success. On
12038 * error returns FALSE and sets @error.
12041 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12043 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12046 mono_error_init (error);
12048 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12051 if (!ensure_runtime_vtable (klass->parent, error))
12055 num = tb->ctors? mono_array_length (tb->ctors): 0;
12056 num += tb->num_methods;
12057 klass->method.count = num;
12058 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12059 num = tb->ctors? mono_array_length (tb->ctors): 0;
12060 for (i = 0; i < num; ++i) {
12061 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12064 klass->methods [i] = ctor;
12066 num = tb->num_methods;
12068 for (i = 0; i < num; ++i) {
12069 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12072 klass->methods [j++] = meth;
12075 if (tb->interfaces) {
12076 klass->interface_count = mono_array_length (tb->interfaces);
12077 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12078 for (i = 0; i < klass->interface_count; ++i) {
12079 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12080 klass->interfaces [i] = mono_class_from_mono_type (iface);
12081 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12084 klass->interfaces_inited = 1;
12086 } else if (klass->generic_class){
12087 if (!ensure_generic_class_runtime_vtable (klass, error))
12091 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12093 for (i = 0; i < klass->method.count; ++i) {
12094 MonoMethod *im = klass->methods [i];
12095 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12096 im->slot = slot_num++;
12099 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12100 mono_class_setup_interface_offsets (klass);
12101 mono_class_setup_interface_id (klass);
12105 * The generic vtable is needed even if image->run is not set since some
12106 * runtime code like ves_icall_Type_GetMethodsByName depends on
12107 * method->slot being defined.
12111 * tb->methods could not be freed since it is used for determining
12112 * overrides during dynamic vtable construction.
12119 mono_reflection_method_get_handle (MonoObject *method)
12122 MonoClass *klass = mono_object_class (method);
12123 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12124 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12125 return sr_method->method;
12127 if (is_sre_method_builder (klass)) {
12128 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12129 return mb->mhandle;
12131 if (is_sre_method_on_tb_inst (klass)) {
12132 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12133 MonoMethod *result;
12134 /*FIXME move this to a proper method and unify with resolve_object*/
12135 if (m->method_args) {
12136 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12137 mono_error_raise_exception (&error); /* FIXME don't raise here */
12139 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12140 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12141 MonoMethod *mono_method;
12143 if (is_sre_method_builder (mono_object_class (m->mb)))
12144 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12145 else if (is_sr_mono_method (mono_object_class (m->mb)))
12146 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12148 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)));
12150 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12155 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12160 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12162 MonoReflectionTypeBuilder *tb;
12164 MonoReflectionMethod *m;
12167 *num_overrides = 0;
12169 g_assert (image_is_dynamic (klass->image));
12171 if (!mono_class_get_ref_info (klass))
12174 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12176 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12180 for (i = 0; i < tb->num_methods; ++i) {
12181 MonoReflectionMethodBuilder *mb =
12182 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12183 if (mb->override_methods)
12184 onum += mono_array_length (mb->override_methods);
12189 *overrides = g_new0 (MonoMethod*, onum * 2);
12192 for (i = 0; i < tb->num_methods; ++i) {
12193 MonoReflectionMethodBuilder *mb =
12194 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12195 if (mb->override_methods) {
12196 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12197 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12199 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12200 (*overrides) [onum * 2 + 1] = mb->mhandle;
12202 g_assert (mb->mhandle);
12210 *num_overrides = onum;
12214 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12216 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12217 MonoReflectionFieldBuilder *fb;
12218 MonoClassField *field;
12219 MonoImage *image = klass->image;
12220 const char *p, *p2;
12222 guint32 len, idx, real_size = 0;
12224 klass->field.count = tb->num_fields;
12225 klass->field.first = 0;
12227 mono_error_init (error);
12229 if (tb->class_size) {
12230 if ((tb->packing_size & 0xffffff00) != 0) {
12231 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12232 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12235 klass->packing_size = tb->packing_size;
12236 real_size = klass->instance_size + tb->class_size;
12239 if (!klass->field.count) {
12240 klass->instance_size = MAX (klass->instance_size, real_size);
12244 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12245 mono_class_alloc_ext (klass);
12246 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12248 This is, guess what, a hack.
12249 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12250 On the static path no field class is resolved, only types are built. This is the right thing to do
12252 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12254 klass->size_inited = 1;
12256 for (i = 0; i < klass->field.count; ++i) {
12257 MonoArray *rva_data;
12258 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12259 field = &klass->fields [i];
12260 field->name = mono_string_to_utf8_image (image, fb->name, error);
12261 if (!mono_error_ok (error))
12264 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12265 field->type->attrs = fb->attrs;
12267 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12270 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12271 char *base = mono_array_addr (rva_data, char, 0);
12272 size_t size = mono_array_length (rva_data);
12273 char *data = (char *)mono_image_alloc (klass->image, size);
12274 memcpy (data, base, size);
12275 klass->ext->field_def_values [i].data = data;
12277 if (fb->offset != -1)
12278 field->offset = fb->offset;
12279 field->parent = klass;
12280 fb->handle = field;
12281 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12283 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12284 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12286 if (fb->def_value) {
12287 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12288 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12289 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12290 /* Copy the data from the blob since it might get realloc-ed */
12291 p = assembly->blob.data + idx;
12292 len = mono_metadata_decode_blob_size (p, &p2);
12294 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12295 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12299 klass->instance_size = MAX (klass->instance_size, real_size);
12300 mono_class_layout_fields (klass);
12304 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12306 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12307 MonoReflectionPropertyBuilder *pb;
12308 MonoImage *image = klass->image;
12309 MonoProperty *properties;
12312 mono_error_init (error);
12315 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12317 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12318 klass->ext->property.first = 0;
12320 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12321 klass->ext->properties = properties;
12322 for (i = 0; i < klass->ext->property.count; ++i) {
12323 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12324 properties [i].parent = klass;
12325 properties [i].attrs = pb->attrs;
12326 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12327 if (!mono_error_ok (error))
12329 if (pb->get_method)
12330 properties [i].get = pb->get_method->mhandle;
12331 if (pb->set_method)
12332 properties [i].set = pb->set_method->mhandle;
12334 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12335 if (pb->def_value) {
12337 const char *p, *p2;
12338 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12339 if (!klass->ext->prop_def_values)
12340 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12341 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12342 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12343 /* Copy the data from the blob since it might get realloc-ed */
12344 p = assembly->blob.data + idx;
12345 len = mono_metadata_decode_blob_size (p, &p2);
12347 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12348 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12353 MonoReflectionEvent *
12354 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12357 MonoEvent *event = g_new0 (MonoEvent, 1);
12360 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12362 event->parent = klass;
12363 event->attrs = eb->attrs;
12364 event->name = mono_string_to_utf8 (eb->name);
12365 if (eb->add_method)
12366 event->add = eb->add_method->mhandle;
12367 if (eb->remove_method)
12368 event->remove = eb->remove_method->mhandle;
12369 if (eb->raise_method)
12370 event->raise = eb->raise_method->mhandle;
12372 #ifndef MONO_SMALL_CONFIG
12373 if (eb->other_methods) {
12375 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12376 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12377 MonoReflectionMethodBuilder *mb =
12378 mono_array_get (eb->other_methods,
12379 MonoReflectionMethodBuilder*, j);
12380 event->other [j] = mb->mhandle;
12385 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12386 mono_error_raise_exception (&error); /* FIXME don't raise here */
12391 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12393 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12394 MonoReflectionEventBuilder *eb;
12395 MonoImage *image = klass->image;
12399 mono_error_init (error);
12402 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12404 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12405 klass->ext->event.first = 0;
12407 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12408 klass->ext->events = events;
12409 for (i = 0; i < klass->ext->event.count; ++i) {
12410 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12411 events [i].parent = klass;
12412 events [i].attrs = eb->attrs;
12413 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12414 if (!mono_error_ok (error))
12416 if (eb->add_method)
12417 events [i].add = eb->add_method->mhandle;
12418 if (eb->remove_method)
12419 events [i].remove = eb->remove_method->mhandle;
12420 if (eb->raise_method)
12421 events [i].raise = eb->raise_method->mhandle;
12423 #ifndef MONO_SMALL_CONFIG
12424 if (eb->other_methods) {
12426 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12427 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12428 MonoReflectionMethodBuilder *mb =
12429 mono_array_get (eb->other_methods,
12430 MonoReflectionMethodBuilder*, j);
12431 events [i].other [j] = mb->mhandle;
12435 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12440 remove_instantiations_of_and_ensure_contents (gpointer key,
12442 gpointer user_data)
12444 MonoType *type = (MonoType*)key;
12445 MonoClass *klass = (MonoClass*)user_data;
12447 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12448 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12455 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12457 mono_error_init (error);
12463 for (i = 0; i < mono_array_length (arr); ++i) {
12464 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12465 if (!mono_error_ok (error))
12470 MonoReflectionType*
12471 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12475 MonoDomain* domain;
12476 MonoReflectionType* res;
12479 domain = mono_object_domain (tb);
12480 klass = mono_class_from_mono_type (tb->type.type);
12483 * Check for user defined Type subclasses.
12485 RESOLVE_TYPE (tb->parent, &error);
12486 mono_error_raise_exception (&error); /* FIXME don't raise here */
12487 check_array_for_usertypes (tb->interfaces, &error);
12488 mono_error_raise_exception (&error); /*FIXME don't raise here */
12490 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12491 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12493 RESOLVE_TYPE (fb->type, &error);
12494 mono_error_raise_exception (&error); /* FIXME don't raise here */
12495 check_array_for_usertypes (fb->modreq, &error);
12496 mono_error_raise_exception (&error); /*FIXME don't raise here */
12497 check_array_for_usertypes (fb->modopt, &error);
12498 mono_error_raise_exception (&error); /*FIXME don't raise here */
12499 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12500 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12501 mono_error_raise_exception (&error); /* FIXME don't raise here */
12507 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12508 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12510 RESOLVE_TYPE (mb->rtype, &error);
12511 mono_error_raise_exception (&error); /* FIXME don't raise here */
12512 check_array_for_usertypes (mb->return_modreq, &error);
12513 mono_error_raise_exception (&error); /*FIXME don't raise here */
12514 check_array_for_usertypes (mb->return_modopt, &error);
12515 mono_error_raise_exception (&error); /*FIXME don't raise here */
12516 check_array_for_usertypes (mb->parameters, &error);
12517 mono_error_raise_exception (&error); /*FIXME don't raise here */
12518 if (mb->param_modreq)
12519 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12520 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12521 mono_error_raise_exception (&error); /*FIXME don't raise here */
12523 if (mb->param_modopt)
12524 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12525 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12526 mono_error_raise_exception (&error); /*FIXME don't raise here */
12532 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12533 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12535 check_array_for_usertypes (mb->parameters, &error);
12536 mono_error_raise_exception (&error); /*FIXME don't raise here */
12537 if (mb->param_modreq)
12538 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12539 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12540 mono_error_raise_exception (&error); /*FIXME don't raise here */
12542 if (mb->param_modopt)
12543 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12544 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12545 mono_error_raise_exception (&error); /*FIXME don't raise here */
12551 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12554 * we need to lock the domain because the lock will be taken inside
12555 * So, we need to keep the locking order correct.
12557 mono_loader_lock ();
12558 mono_domain_lock (domain);
12559 if (klass->wastypebuilder) {
12560 mono_domain_unlock (domain);
12561 mono_loader_unlock ();
12563 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12564 mono_error_raise_exception (&error); /* FIXME don't raise here */
12569 * Fields to set in klass:
12570 * the various flags: delegate/unicode/contextbound etc.
12572 klass->flags = tb->attrs;
12573 klass->has_cctor = 1;
12574 klass->has_finalize = 1;
12575 klass->has_finalize_inited = 1;
12577 mono_class_setup_parent (klass, klass->parent);
12578 /* fool mono_class_setup_supertypes */
12579 klass->supertypes = NULL;
12580 mono_class_setup_supertypes (klass);
12581 mono_class_setup_mono_type (klass);
12584 if (!((MonoDynamicImage*)klass->image)->run) {
12585 if (klass->generic_container) {
12586 /* FIXME: The code below can't handle generic classes */
12587 klass->wastypebuilder = TRUE;
12588 mono_loader_unlock ();
12589 mono_domain_unlock (domain);
12591 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12592 mono_error_raise_exception (&error); /* FIXME don't raise here */
12599 /* enums are done right away */
12600 if (!klass->enumtype)
12601 if (!ensure_runtime_vtable (klass, &error))
12604 if (tb->subtypes) {
12605 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12606 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12607 mono_class_alloc_ext (klass);
12608 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)));
12612 klass->nested_classes_inited = TRUE;
12614 /* fields and object layout */
12615 if (klass->parent) {
12616 if (!klass->parent->size_inited)
12617 mono_class_init (klass->parent);
12618 klass->instance_size = klass->parent->instance_size;
12619 klass->sizes.class_size = 0;
12620 klass->min_align = klass->parent->min_align;
12621 /* if the type has no fields we won't call the field_setup
12622 * routine which sets up klass->has_references.
12624 klass->has_references |= klass->parent->has_references;
12626 klass->instance_size = sizeof (MonoObject);
12627 klass->min_align = 1;
12630 /* FIXME: handle packing_size and instance_size */
12631 typebuilder_setup_fields (klass, &error);
12632 if (!mono_error_ok (&error))
12634 typebuilder_setup_properties (klass, &error);
12635 if (!mono_error_ok (&error))
12638 typebuilder_setup_events (klass, &error);
12639 if (!mono_error_ok (&error))
12642 klass->wastypebuilder = TRUE;
12645 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12646 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12647 * we want to return normal System.MonoType objects, so clear these out from the cache.
12649 * Together with this we must ensure the contents of all instances to match the created type.
12651 if (domain->type_hash && klass->generic_container)
12652 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12654 mono_domain_unlock (domain);
12655 mono_loader_unlock ();
12657 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12658 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12659 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12662 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12663 mono_error_raise_exception (&error); /* FIXME don't raise here */
12665 g_assert (res != (MonoReflectionType*)tb);
12670 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12671 klass->wastypebuilder = TRUE;
12672 mono_domain_unlock (domain);
12673 mono_loader_unlock ();
12674 mono_error_raise_exception (&error);
12679 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12681 MonoGenericParamFull *param;
12686 image = &gparam->tbuilder->module->dynamic_image->image;
12688 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12690 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12691 g_assert (mono_error_ok (&error));
12692 param->param.num = gparam->index;
12694 if (gparam->mbuilder) {
12695 if (!gparam->mbuilder->generic_container) {
12696 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12697 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12698 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12699 gparam->mbuilder->generic_container->is_method = TRUE;
12701 * Cannot set owner.method, since the MonoMethod is not created yet.
12702 * Set the image field instead, so type_in_image () works.
12704 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12705 gparam->mbuilder->generic_container->owner.image = klass->image;
12707 param->param.owner = gparam->mbuilder->generic_container;
12708 } else if (gparam->tbuilder) {
12709 if (!gparam->tbuilder->generic_container) {
12710 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12711 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12712 gparam->tbuilder->generic_container->owner.klass = klass;
12714 param->param.owner = gparam->tbuilder->generic_container;
12717 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12719 gparam->type.type = &pklass->byval_arg;
12721 mono_class_set_ref_info (pklass, gparam);
12722 mono_image_append_class_to_reflection_info_set (pklass);
12726 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12729 MonoReflectionModuleBuilder *module = sig->module;
12730 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12731 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12736 check_array_for_usertypes (sig->arguments, &error);
12737 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12739 sigbuffer_init (&buf, 32);
12741 sigbuffer_add_value (&buf, 0x07);
12742 sigbuffer_add_value (&buf, na);
12743 if (assembly != NULL){
12744 for (i = 0; i < na; ++i) {
12745 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12746 encode_reflection_type (assembly, type, &buf);
12750 buflen = buf.p - buf.buf;
12751 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12752 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12753 sigbuffer_free (&buf);
12759 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12762 MonoDynamicImage *assembly = sig->module->dynamic_image;
12763 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12768 check_array_for_usertypes (sig->arguments, &error);
12769 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12771 sigbuffer_init (&buf, 32);
12773 sigbuffer_add_value (&buf, 0x06);
12774 for (i = 0; i < na; ++i) {
12775 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12776 encode_reflection_type (assembly, type, &buf);
12779 buflen = buf.p - buf.buf;
12780 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12781 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12782 sigbuffer_free (&buf);
12788 MonoMethod *handle;
12789 MonoDomain *domain;
12790 } DynamicMethodReleaseData;
12793 * The runtime automatically clean up those after finalization.
12795 static MonoReferenceQueue *dynamic_method_queue;
12798 free_dynamic_method (void *dynamic_method)
12800 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12801 MonoDomain *domain = data->domain;
12802 MonoMethod *method = data->handle;
12805 mono_domain_lock (domain);
12806 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12807 g_hash_table_remove (domain->method_to_dyn_method, method);
12808 mono_domain_unlock (domain);
12809 g_assert (dis_link);
12810 mono_gchandle_free (dis_link);
12812 mono_runtime_free_method (domain, method);
12817 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12819 MonoReferenceQueue *queue;
12820 MonoMethod *handle;
12821 DynamicMethodReleaseData *release_data;
12822 ReflectionMethodBuilder rmb;
12823 MonoMethodSignature *sig;
12825 MonoDomain *domain;
12829 if (mono_runtime_is_shutting_down ())
12830 mono_raise_exception (mono_get_exception_invalid_operation (""));
12832 if (!(queue = dynamic_method_queue)) {
12833 mono_loader_lock ();
12834 if (!(queue = dynamic_method_queue))
12835 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12836 mono_loader_unlock ();
12839 sig = dynamic_method_to_signature (mb);
12841 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12844 * Resolve references.
12847 * Every second entry in the refs array is reserved for storing handle_class,
12848 * which is needed by the ldtoken implementation in the JIT.
12850 rmb.nrefs = mb->nrefs;
12851 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12852 for (i = 0; i < mb->nrefs; i += 2) {
12853 MonoClass *handle_class;
12855 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12857 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12858 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12860 * The referenced DynamicMethod should already be created by the managed
12861 * code, except in the case of circular references. In that case, we store
12862 * method in the refs array, and fix it up later when the referenced
12863 * DynamicMethod is created.
12865 if (method->mhandle) {
12866 ref = method->mhandle;
12868 /* FIXME: GC object stored in unmanaged memory */
12871 /* FIXME: GC object stored in unmanaged memory */
12872 method->referenced_by = g_slist_append (method->referenced_by, mb);
12874 handle_class = mono_defaults.methodhandle_class;
12876 MonoException *ex = NULL;
12877 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12879 ex = mono_get_exception_type_load (NULL, NULL);
12880 else if (mono_security_core_clr_enabled ())
12881 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12885 mono_raise_exception (ex);
12890 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12891 rmb.refs [i + 1] = handle_class;
12894 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12896 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12897 release_data = g_new (DynamicMethodReleaseData, 1);
12898 release_data->handle = handle;
12899 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12900 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12901 g_free (release_data);
12903 /* Fix up refs entries pointing at us */
12904 for (l = mb->referenced_by; l; l = l->next) {
12905 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12906 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12909 g_assert (method->mhandle);
12911 data = (gpointer*)wrapper->method_data;
12912 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12913 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12914 data [i + 1] = mb->mhandle;
12917 g_slist_free (mb->referenced_by);
12921 /* ilgen is no longer needed */
12924 domain = mono_domain_get ();
12925 mono_domain_lock (domain);
12926 if (!domain->method_to_dyn_method)
12927 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12928 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12929 mono_domain_unlock (domain);
12932 #endif /* DISABLE_REFLECTION_EMIT */
12936 * mono_reflection_is_valid_dynamic_token:
12938 * Returns TRUE if token is valid.
12942 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12944 return lookup_dyn_token (image, token) != NULL;
12947 MonoMethodSignature *
12948 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12950 MonoMethodSignature *sig;
12951 g_assert (image_is_dynamic (image));
12953 mono_error_init (error);
12955 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12959 return mono_method_signature_checked (method, error);
12962 #ifndef DISABLE_REFLECTION_EMIT
12965 * mono_reflection_lookup_dynamic_token:
12967 * Finish the Builder object pointed to by TOKEN and return the corresponding
12968 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12969 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12972 * LOCKING: Take the loader lock
12975 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12977 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12981 obj = lookup_dyn_token (assembly, token);
12984 g_error ("Could not find required dynamic token 0x%08x", token);
12990 handle_class = &klass;
12991 return resolve_object (image, obj, handle_class, context);
12995 * ensure_complete_type:
12997 * Ensure that KLASS is completed if it is a dynamic type, or references
13001 ensure_complete_type (MonoClass *klass)
13005 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13006 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13008 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13009 mono_error_raise_exception (&error); /* FIXME don't raise here */
13011 // Asserting here could break a lot of code
13012 //g_assert (klass->wastypebuilder);
13015 if (klass->generic_class) {
13016 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13019 for (i = 0; i < inst->type_argc; ++i) {
13020 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13026 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13029 gpointer result = NULL;
13031 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13032 result = mono_string_intern_checked ((MonoString*)obj, &error);
13033 mono_error_raise_exception (&error); /* FIXME don't raise here */
13034 *handle_class = mono_defaults.string_class;
13036 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13037 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13038 MonoClass *mc = mono_class_from_mono_type (type);
13039 if (!mono_class_init (mc))
13040 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13043 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13044 mono_error_raise_exception (&error); /* FIXME don't raise here */
13046 result = mono_class_from_mono_type (inflated);
13047 mono_metadata_free_type (inflated);
13049 result = mono_class_from_mono_type (type);
13051 *handle_class = mono_defaults.typehandle_class;
13053 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13054 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13055 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13056 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13057 result = ((MonoReflectionMethod*)obj)->method;
13060 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13061 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13063 *handle_class = mono_defaults.methodhandle_class;
13065 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13066 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13067 result = mb->mhandle;
13069 /* Type is not yet created */
13070 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13072 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13073 mono_error_raise_exception (&error); /* FIXME don't raise here */
13076 * Hopefully this has been filled in by calling CreateType() on the
13080 * TODO: This won't work if the application finishes another
13081 * TypeBuilder instance instead of this one.
13083 result = mb->mhandle;
13087 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13088 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13090 *handle_class = mono_defaults.methodhandle_class;
13091 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13092 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13094 result = cb->mhandle;
13096 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13098 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13099 mono_error_raise_exception (&error); /* FIXME don't raise here */
13100 result = cb->mhandle;
13104 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13105 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13107 *handle_class = mono_defaults.methodhandle_class;
13108 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13109 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13111 ensure_complete_type (field->parent);
13113 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13114 mono_error_raise_exception (&error); /* FIXME don't raise here */
13116 MonoClass *klass = mono_class_from_mono_type (inflated);
13117 MonoClassField *inflated_field;
13118 gpointer iter = NULL;
13119 mono_metadata_free_type (inflated);
13120 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13121 if (!strcmp (field->name, inflated_field->name))
13124 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13125 result = inflated_field;
13129 *handle_class = mono_defaults.fieldhandle_class;
13131 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13132 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13133 result = fb->handle;
13136 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13138 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13139 mono_error_raise_exception (&error); /* FIXME don't raise here */
13140 result = fb->handle;
13143 if (fb->handle && fb->handle->parent->generic_container) {
13144 MonoClass *klass = fb->handle->parent;
13145 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13146 mono_error_raise_exception (&error); /* FIXME don't raise here */
13148 MonoClass *inflated = mono_class_from_mono_type (type);
13150 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13152 mono_metadata_free_type (type);
13154 *handle_class = mono_defaults.fieldhandle_class;
13155 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13156 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13157 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
13160 klass = type->data.klass;
13161 if (klass->wastypebuilder) {
13162 /* Already created */
13166 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13167 mono_error_raise_exception (&error); /* FIXME don't raise here */
13168 result = type->data.klass;
13171 *handle_class = mono_defaults.typehandle_class;
13172 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13173 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13174 MonoMethodSignature *sig;
13177 if (helper->arguments)
13178 nargs = mono_array_length (helper->arguments);
13182 sig = mono_metadata_signature_alloc (image, nargs);
13183 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13184 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13186 if (helper->unmanaged_call_conv) { /* unmanaged */
13187 sig->call_convention = helper->unmanaged_call_conv - 1;
13188 sig->pinvoke = TRUE;
13189 } else if (helper->call_conv & 0x02) {
13190 sig->call_convention = MONO_CALL_VARARG;
13192 sig->call_convention = MONO_CALL_DEFAULT;
13195 sig->param_count = nargs;
13196 /* TODO: Copy type ? */
13197 sig->ret = helper->return_type->type;
13198 for (i = 0; i < nargs; ++i)
13199 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13202 *handle_class = NULL;
13203 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13204 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13205 /* Already created by the managed code */
13206 g_assert (method->mhandle);
13207 result = method->mhandle;
13208 *handle_class = mono_defaults.methodhandle_class;
13209 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13210 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13211 type = mono_class_inflate_generic_type_checked (type, context, &error);
13212 mono_error_raise_exception (&error); /* FIXME don't raise here */
13214 result = mono_class_from_mono_type (type);
13215 *handle_class = mono_defaults.typehandle_class;
13217 mono_metadata_free_type (type);
13218 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13219 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13220 type = mono_class_inflate_generic_type_checked (type, context, &error);
13221 mono_error_raise_exception (&error); /* FIXME don't raise here */
13223 result = mono_class_from_mono_type (type);
13224 *handle_class = mono_defaults.typehandle_class;
13226 mono_metadata_free_type (type);
13227 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13228 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13229 MonoClass *inflated;
13231 MonoClassField *field;
13233 if (is_sre_field_builder (mono_object_class (f->fb)))
13234 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13235 else if (is_sr_mono_field (mono_object_class (f->fb)))
13236 field = ((MonoReflectionField*)f->fb)->field;
13238 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)));
13240 type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context, &error);
13241 mono_error_raise_exception (&error); /* FIXME don't raise here */
13243 inflated = mono_class_from_mono_type (type);
13245 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13246 ensure_complete_type (field->parent);
13248 mono_metadata_free_type (type);
13249 *handle_class = mono_defaults.fieldhandle_class;
13250 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13251 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13252 MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context, &error);
13253 mono_error_raise_exception (&error); /* FIXME don't raise here */
13255 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13256 MonoMethod *method;
13258 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13259 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13260 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13261 method = ((MonoReflectionMethod *)c->cb)->method;
13263 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)));
13265 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13266 *handle_class = mono_defaults.methodhandle_class;
13267 mono_metadata_free_type (type);
13268 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13269 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13270 if (m->method_args) {
13271 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13272 mono_error_raise_exception (&error); /* FIXME don't raise here */
13274 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13275 mono_error_assert_ok (&error);
13278 MonoType *type = mono_class_inflate_generic_type_checked (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context, &error);
13279 mono_error_raise_exception (&error); /* FIXME don't raise here */
13281 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13282 MonoMethod *method;
13284 if (is_sre_method_builder (mono_object_class (m->mb)))
13285 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13286 else if (is_sr_mono_method (mono_object_class (m->mb)))
13287 method = ((MonoReflectionMethod *)m->mb)->method;
13289 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)));
13291 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13292 mono_metadata_free_type (type);
13294 *handle_class = mono_defaults.methodhandle_class;
13295 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13296 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13299 MonoMethod *method;
13303 mtype = mono_reflection_type_get_handle (m->parent);
13304 klass = mono_class_from_mono_type (mtype);
13306 /* Find the method */
13308 name = mono_string_to_utf8 (m->name);
13310 while ((method = mono_class_get_methods (klass, &iter))) {
13311 if (!strcmp (method->name, name))
13318 // FIXME: Check parameters/return value etc. match
13321 *handle_class = mono_defaults.methodhandle_class;
13322 } else if (is_sre_array (mono_object_get_class(obj)) ||
13323 is_sre_byref (mono_object_get_class(obj)) ||
13324 is_sre_pointer (mono_object_get_class(obj))) {
13325 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13326 MonoType *type = mono_reflection_type_get_handle (ref_type);
13329 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13330 mono_error_raise_exception (&error); /* FIXME don't raise here */
13332 result = mono_class_from_mono_type (inflated);
13333 mono_metadata_free_type (inflated);
13335 result = mono_class_from_mono_type (type);
13337 *handle_class = mono_defaults.typehandle_class;
13339 g_print ("%s\n", obj->vtable->klass->name);
13340 g_assert_not_reached ();
13345 #else /* DISABLE_REFLECTION_EMIT */
13348 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13350 g_assert_not_reached ();
13355 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13357 g_assert_not_reached ();
13361 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13363 g_assert_not_reached ();
13367 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13369 g_assert_not_reached ();
13373 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13375 g_assert_not_reached ();
13379 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13381 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13385 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13387 g_assert_not_reached ();
13391 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13393 g_assert_not_reached ();
13396 MonoReflectionModule *
13397 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13399 g_assert_not_reached ();
13404 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13406 g_assert_not_reached ();
13411 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13413 g_assert_not_reached ();
13418 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13419 gboolean create_open_instance, gboolean register_token, MonoError *error)
13421 g_assert_not_reached ();
13426 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13431 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13433 g_assert_not_reached ();
13437 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13440 *num_overrides = 0;
13443 MonoReflectionEvent *
13444 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13446 g_assert_not_reached ();
13450 MonoReflectionType*
13451 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13453 g_assert_not_reached ();
13458 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13460 g_assert_not_reached ();
13464 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13466 g_assert_not_reached ();
13471 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13473 g_assert_not_reached ();
13478 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13483 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13489 mono_reflection_type_get_handle (MonoReflectionType* ref)
13497 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13499 g_assert_not_reached ();
13502 #endif /* DISABLE_REFLECTION_EMIT */
13504 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13505 const static guint32 declsec_flags_map[] = {
13506 0x00000000, /* empty */
13507 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13508 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13509 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13510 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13511 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13512 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13513 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13514 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13515 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13516 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13517 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13518 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13519 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13520 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13521 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13522 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13523 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13524 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13528 * Returns flags that includes all available security action associated to the handle.
13529 * @token: metadata token (either for a class or a method)
13530 * @image: image where resides the metadata.
13533 mono_declsec_get_flags (MonoImage *image, guint32 token)
13535 int index = mono_metadata_declsec_from_index (image, token);
13536 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13537 guint32 result = 0;
13541 /* HasSecurity can be present for other, not specially encoded, attributes,
13542 e.g. SuppressUnmanagedCodeSecurityAttribute */
13546 for (i = index; i < t->rows; i++) {
13547 guint32 cols [MONO_DECL_SECURITY_SIZE];
13549 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13550 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13553 action = cols [MONO_DECL_SECURITY_ACTION];
13554 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13555 result |= declsec_flags_map [action];
13557 g_assert_not_reached ();
13564 * Get the security actions (in the form of flags) associated with the specified method.
13566 * @method: The method for which we want the declarative security flags.
13567 * Return the declarative security flags for the method (only).
13569 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13570 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13573 mono_declsec_flags_from_method (MonoMethod *method)
13575 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13576 /* FIXME: No cache (for the moment) */
13577 guint32 idx = mono_method_get_index (method);
13578 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13579 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13580 return mono_declsec_get_flags (method->klass->image, idx);
13586 * Get the security actions (in the form of flags) associated with the specified class.
13588 * @klass: The class for which we want the declarative security flags.
13589 * Return the declarative security flags for the class.
13591 * Note: We cache the flags inside the MonoClass structure as this will get
13592 * called very often (at least for each method).
13595 mono_declsec_flags_from_class (MonoClass *klass)
13597 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13598 if (!klass->ext || !klass->ext->declsec_flags) {
13601 idx = mono_metadata_token_index (klass->type_token);
13602 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13603 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13604 mono_loader_lock ();
13605 mono_class_alloc_ext (klass);
13606 mono_loader_unlock ();
13607 /* we cache the flags on classes */
13608 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13610 return klass->ext->declsec_flags;
13616 * Get the security actions (in the form of flags) associated with the specified assembly.
13618 * @assembly: The assembly for which we want the declarative security flags.
13619 * Return the declarative security flags for the assembly.
13622 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13624 guint32 idx = 1; /* there is only one assembly */
13625 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13626 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13627 return mono_declsec_get_flags (assembly->image, idx);
13632 * Fill actions for the specific index (which may either be an encoded class token or
13633 * an encoded method token) from the metadata image.
13634 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13637 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13638 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13640 MonoBoolean result = FALSE;
13642 guint32 cols [MONO_DECL_SECURITY_SIZE];
13643 int index = mono_metadata_declsec_from_index (image, token);
13646 t = &image->tables [MONO_TABLE_DECLSECURITY];
13647 for (i = index; i < t->rows; i++) {
13648 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13650 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13653 /* if present only replace (class) permissions with method permissions */
13654 /* if empty accept either class or method permissions */
13655 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13656 if (!actions->demand.blob) {
13657 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13658 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13659 actions->demand.blob = (char*) (blob + 2);
13660 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13663 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13664 if (!actions->noncasdemand.blob) {
13665 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13666 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13667 actions->noncasdemand.blob = (char*) (blob + 2);
13668 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13671 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13672 if (!actions->demandchoice.blob) {
13673 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13674 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13675 actions->demandchoice.blob = (char*) (blob + 2);
13676 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13686 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13687 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13689 guint32 idx = mono_metadata_token_index (klass->type_token);
13690 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13691 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13692 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13696 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13697 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13699 guint32 idx = mono_method_get_index (method);
13700 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13701 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13702 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13706 * Collect all actions (that requires to generate code in mini) assigned for
13707 * the specified method.
13708 * Note: Don't use the content of actions if the function return FALSE.
13711 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13713 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13714 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13715 MonoBoolean result = FALSE;
13718 /* quick exit if no declarative security is present in the metadata */
13719 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13722 /* we want the original as the wrapper is "free" of the security informations */
13723 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13724 method = mono_marshal_method_from_wrapper (method);
13729 /* First we look for method-level attributes */
13730 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13731 mono_class_init (method->klass);
13732 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13734 result = mono_declsec_get_method_demands_params (method, demands,
13735 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13738 /* Here we use (or create) the class declarative cache to look for demands */
13739 flags = mono_declsec_flags_from_class (method->klass);
13740 if (flags & mask) {
13742 mono_class_init (method->klass);
13743 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13745 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13746 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13749 /* The boolean return value is used as a shortcut in case nothing needs to
13750 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13756 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13758 * Note: Don't use the content of actions if the function return FALSE.
13761 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13763 MonoBoolean result = FALSE;
13766 /* quick exit if no declarative security is present in the metadata */
13767 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13770 /* we want the original as the wrapper is "free" of the security informations */
13771 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13772 method = mono_marshal_method_from_wrapper (method);
13777 /* results are independant - zeroize both */
13778 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13779 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13781 /* First we look for method-level attributes */
13782 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13783 mono_class_init (method->klass);
13785 result = mono_declsec_get_method_demands_params (method, cmethod,
13786 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13789 /* Here we use (or create) the class declarative cache to look for demands */
13790 flags = mono_declsec_flags_from_class (method->klass);
13791 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13792 mono_class_init (method->klass);
13794 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13795 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13802 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13804 * @klass The inherited class - this is the class that provides the security check (attributes)
13806 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13808 * Note: Don't use the content of actions if the function return FALSE.
13811 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13813 MonoBoolean result = FALSE;
13816 /* quick exit if no declarative security is present in the metadata */
13817 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13820 /* Here we use (or create) the class declarative cache to look for demands */
13821 flags = mono_declsec_flags_from_class (klass);
13822 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13823 mono_class_init (klass);
13824 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13826 result |= mono_declsec_get_class_demands_params (klass, demands,
13827 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13834 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13836 * Note: Don't use the content of actions if the function return FALSE.
13839 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13841 /* quick exit if no declarative security is present in the metadata */
13842 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13845 /* we want the original as the wrapper is "free" of the security informations */
13846 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13847 method = mono_marshal_method_from_wrapper (method);
13852 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13853 mono_class_init (method->klass);
13854 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13856 return mono_declsec_get_method_demands_params (method, demands,
13857 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13864 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13866 guint32 cols [MONO_DECL_SECURITY_SIZE];
13870 int index = mono_metadata_declsec_from_index (image, token);
13874 t = &image->tables [MONO_TABLE_DECLSECURITY];
13875 for (i = index; i < t->rows; i++) {
13876 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13878 /* shortcut - index are ordered */
13879 if (token != cols [MONO_DECL_SECURITY_PARENT])
13882 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13883 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13884 entry->blob = (char*) (metadata + 2);
13885 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13894 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13896 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13897 guint32 idx = mono_method_get_index (method);
13898 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13899 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13900 return get_declsec_action (method->klass->image, idx, action, entry);
13906 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13909 guint32 flags = mono_declsec_flags_from_class (klass);
13910 if (declsec_flags_map [action] & flags) {
13911 guint32 idx = mono_metadata_token_index (klass->type_token);
13912 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13913 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13914 return get_declsec_action (klass->image, idx, action, entry);
13920 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13922 guint32 idx = 1; /* there is only one assembly */
13923 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13924 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13926 return get_declsec_action (assembly->image, idx, action, entry);
13930 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13933 MonoObject *res, *exc;
13935 static MonoMethod *method = NULL;
13937 if (method == NULL) {
13938 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13943 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13944 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13946 g_assert (mono_class_get_ref_info (klass));
13947 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13949 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13950 mono_error_raise_exception (&error); /* FIXME don't raise here */
13952 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13954 if (exc || !mono_error_ok (&error)) {
13955 mono_error_cleanup (&error);
13958 return *(MonoBoolean*)mono_object_unbox (res);
13962 * mono_reflection_type_get_type:
13963 * @reftype: the System.Type object
13965 * Returns the MonoType* associated with the C# System.Type object @reftype.
13968 mono_reflection_type_get_type (MonoReflectionType *reftype)
13970 g_assert (reftype);
13972 return mono_reflection_type_get_handle (reftype);
13976 * mono_reflection_assembly_get_assembly:
13977 * @refassembly: the System.Reflection.Assembly object
13979 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13982 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13984 g_assert (refassembly);
13986 return refassembly->assembly;