2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
247 dynamic_images_lock (void)
249 mono_os_mutex_lock (&dynamic_images_mutex);
253 dynamic_images_unlock (void)
255 mono_os_mutex_unlock (&dynamic_images_mutex);
259 * mono_find_dynamic_image_owner:
261 * Find the dynamic image, if any, which a given pointer is located in the memory of.
264 mono_find_dynamic_image_owner (void *ptr)
266 MonoImage *owner = NULL;
269 dynamic_images_lock ();
273 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275 if (mono_mempool_contains_addr (image->mempool, ptr))
280 dynamic_images_unlock ();
286 mono_reflection_init (void)
288 mono_os_mutex_init (&dynamic_images_mutex);
292 dynamic_image_lock (MonoDynamicImage *image)
294 MONO_PREPARE_BLOCKING;
295 mono_image_lock ((MonoImage*)image);
296 MONO_FINISH_BLOCKING;
300 dynamic_image_unlock (MonoDynamicImage *image)
302 mono_image_unlock ((MonoImage*)image);
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
308 MONO_REQ_GC_UNSAFE_MODE;
310 dynamic_image_lock (assembly);
311 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312 dynamic_image_unlock (assembly);
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
318 MONO_REQ_GC_UNSAFE_MODE;
322 dynamic_image_lock (assembly);
323 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324 dynamic_image_unlock (assembly);
330 sigbuffer_init (SigBuffer *buf, int size)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 buf->buf = (char *)g_malloc (size);
336 buf->end = buf->buf + size;
340 sigbuffer_make_room (SigBuffer *buf, int size)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 if (buf->end - buf->p < size) {
345 int new_size = buf->end - buf->buf + size + 32;
346 char *p = (char *)g_realloc (buf->buf, new_size);
347 size = buf->p - buf->buf;
350 buf->end = buf->buf + new_size;
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
357 MONO_REQ_GC_NEUTRAL_MODE;
359 sigbuffer_make_room (buf, 6);
360 mono_metadata_encode_value (val, buf->p, &buf->p);
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
366 MONO_REQ_GC_NEUTRAL_MODE;
368 sigbuffer_make_room (buf, 1);
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
376 MONO_REQ_GC_NEUTRAL_MODE;
378 sigbuffer_make_room (buf, size);
379 memcpy (buf->p, p, size);
384 sigbuffer_free (SigBuffer *buf)
386 MONO_REQ_GC_NEUTRAL_MODE;
391 #ifndef DISABLE_REFLECTION_EMIT
395 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399 image_g_malloc (MonoImage *image, guint size)
401 MONO_REQ_GC_NEUTRAL_MODE;
404 return mono_image_alloc (image, size);
406 return g_malloc (size);
408 #endif /* !DISABLE_REFLECTION_EMIT */
413 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417 image_g_malloc0 (MonoImage *image, guint size)
419 MONO_REQ_GC_NEUTRAL_MODE;
422 return mono_image_alloc0 (image, size);
424 return g_malloc0 (size);
427 #ifndef DISABLE_REFLECTION_EMIT
429 image_strdup (MonoImage *image, const char *s)
431 MONO_REQ_GC_NEUTRAL_MODE;
434 return mono_image_strdup (image, s);
440 #define image_g_new(image,struct_type, n_structs) \
441 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
443 #define image_g_new0(image,struct_type, n_structs) \
444 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
448 alloc_table (MonoDynamicTable *table, guint nrows)
450 MONO_REQ_GC_NEUTRAL_MODE;
453 g_assert (table->columns);
454 if (nrows + 1 >= table->alloc_rows) {
455 while (nrows + 1 >= table->alloc_rows) {
456 if (table->alloc_rows == 0)
457 table->alloc_rows = 16;
459 table->alloc_rows *= 2;
462 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
467 make_room_in_stream (MonoDynamicStream *stream, int size)
469 MONO_REQ_GC_NEUTRAL_MODE;
471 if (size <= stream->alloc_size)
474 while (stream->alloc_size <= size) {
475 if (stream->alloc_size < 4096)
476 stream->alloc_size = 4096;
478 stream->alloc_size *= 2;
481 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
487 MONO_REQ_GC_NEUTRAL_MODE;
491 gpointer oldkey, oldval;
493 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494 return GPOINTER_TO_UINT (oldval);
496 len = strlen (str) + 1;
499 make_room_in_stream (sh, idx + len);
502 * We strdup the string even if we already copy them in sh->data
503 * so that the string pointers in the hash remain valid even if
504 * we need to realloc sh->data. We may want to avoid that later.
506 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507 memcpy (sh->data + idx, str, len);
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
515 MONO_REQ_GC_UNSAFE_MODE;
517 char *name = mono_string_to_utf8 (str);
519 idx = string_heap_insert (sh, name);
524 #ifndef DISABLE_REFLECTION_EMIT
526 string_heap_init (MonoDynamicStream *sh)
528 MONO_REQ_GC_NEUTRAL_MODE;
531 sh->alloc_size = 4096;
532 sh->data = (char *)g_malloc (4096);
533 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534 string_heap_insert (sh, "");
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
541 MONO_REQ_GC_NEUTRAL_MODE;
545 make_room_in_stream (stream, stream->index + len);
546 memcpy (stream->data + stream->index, data, len);
548 stream->index += len;
550 * align index? Not without adding an additional param that controls it since
551 * we may store a blob value in pieces.
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
559 MONO_REQ_GC_NEUTRAL_MODE;
563 make_room_in_stream (stream, stream->index + len);
564 memset (stream->data + stream->index, 0, len);
566 stream->index += len;
571 stream_data_align (MonoDynamicStream *stream)
573 MONO_REQ_GC_NEUTRAL_MODE;
576 guint32 count = stream->index % 4;
578 /* we assume the stream data will be aligned */
580 mono_image_add_stream_data (stream, buf, 4 - count);
583 #ifndef DISABLE_REFLECTION_EMIT
585 mono_blob_entry_hash (const char* str)
587 MONO_REQ_GC_NEUTRAL_MODE;
591 len = mono_metadata_decode_blob_size (str, &str);
595 for (str += 1; str < end; str++)
596 h = (h << 5) - h + *str;
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605 MONO_REQ_GC_NEUTRAL_MODE;
610 len = mono_metadata_decode_blob_size (str1, &end1);
611 len2 = mono_metadata_decode_blob_size (str2, &end2);
614 return memcmp (end1, end2, len) == 0;
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
620 MONO_REQ_GC_NEUTRAL_MODE;
624 gpointer oldkey, oldval;
626 copy = (char *)g_malloc (s1+s2);
627 memcpy (copy, b1, s1);
628 memcpy (copy + s1, b2, s2);
629 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
631 idx = GPOINTER_TO_UINT (oldval);
633 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634 mono_image_add_stream_data (&assembly->blob, b2, s2);
635 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
643 MONO_REQ_GC_NEUTRAL_MODE;
647 guint32 size = buf->p - buf->buf;
649 g_assert (size <= (buf->end - buf->buf));
650 mono_metadata_encode_value (size, b, &b);
651 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
655 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656 * dest may be misaligned.
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660 MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
664 for (elem = 0; elem < nelem; ++elem) {
690 g_assert_not_reached ();
696 memcpy (dest, val, len * nelem);
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
703 MONO_REQ_GC_UNSAFE_MODE;
707 guint32 idx = 0, len;
709 len = str->length * 2;
710 mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
713 char *swapped = g_malloc (2 * mono_string_length (str));
714 const char *p = (const char*)mono_string_chars (str);
716 swap_with_size (swapped, p, 2, mono_string_length (str));
717 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
726 #ifndef DISABLE_REFLECTION_EMIT
728 default_class_from_mono_type (MonoType *type)
730 MONO_REQ_GC_NEUTRAL_MODE;
732 switch (type->type) {
733 case MONO_TYPE_OBJECT:
734 return mono_defaults.object_class;
736 return mono_defaults.void_class;
737 case MONO_TYPE_BOOLEAN:
738 return mono_defaults.boolean_class;
740 return mono_defaults.char_class;
742 return mono_defaults.sbyte_class;
744 return mono_defaults.byte_class;
746 return mono_defaults.int16_class;
748 return mono_defaults.uint16_class;
750 return mono_defaults.int32_class;
752 return mono_defaults.uint32_class;
754 return mono_defaults.int_class;
756 return mono_defaults.uint_class;
758 return mono_defaults.int64_class;
760 return mono_defaults.uint64_class;
762 return mono_defaults.single_class;
764 return mono_defaults.double_class;
765 case MONO_TYPE_STRING:
766 return mono_defaults.string_class;
768 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769 g_assert_not_reached ();
777 * mono_class_get_ref_info:
779 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
782 mono_class_get_ref_info (MonoClass *klass)
784 MONO_REQ_GC_UNSAFE_MODE;
786 if (klass->ref_info_handle == 0)
789 return mono_gchandle_get_target (klass->ref_info_handle);
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
795 MONO_REQ_GC_UNSAFE_MODE;
797 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798 g_assert (klass->ref_info_handle != 0);
802 mono_class_free_ref_info (MonoClass *klass)
804 MONO_REQ_GC_NEUTRAL_MODE;
806 if (klass->ref_info_handle) {
807 mono_gchandle_free (klass->ref_info_handle);
808 klass->ref_info_handle = 0;
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
815 MONO_REQ_GC_NEUTRAL_MODE;
818 MonoGenericInst *class_inst;
823 class_inst = gclass->context.class_inst;
825 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826 klass = gclass->container_class;
827 sigbuffer_add_value (buf, klass->byval_arg.type);
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
830 sigbuffer_add_value (buf, class_inst->type_argc);
831 for (i = 0; i < class_inst->type_argc; ++i)
832 encode_type (assembly, class_inst->type_argv [i], buf);
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
839 MONO_REQ_GC_NEUTRAL_MODE;
842 g_assert_not_reached ();
847 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
851 case MONO_TYPE_BOOLEAN:
865 case MONO_TYPE_STRING:
866 case MONO_TYPE_OBJECT:
867 case MONO_TYPE_TYPEDBYREF:
868 sigbuffer_add_value (buf, type->type);
871 sigbuffer_add_value (buf, type->type);
872 encode_type (assembly, type->data.type, buf);
874 case MONO_TYPE_SZARRAY:
875 sigbuffer_add_value (buf, type->type);
876 encode_type (assembly, &type->data.klass->byval_arg, buf);
878 case MONO_TYPE_VALUETYPE:
879 case MONO_TYPE_CLASS: {
880 MonoClass *k = mono_class_from_mono_type (type);
882 if (k->generic_container) {
883 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884 encode_generic_class (assembly, gclass, buf);
887 * Make sure we use the correct type.
889 sigbuffer_add_value (buf, k->byval_arg.type);
891 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892 * otherwise two typerefs could point to the same type, leading to
893 * verification errors.
895 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
899 case MONO_TYPE_ARRAY:
900 sigbuffer_add_value (buf, type->type);
901 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902 sigbuffer_add_value (buf, type->data.array->rank);
903 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904 sigbuffer_add_value (buf, 0);
906 case MONO_TYPE_GENERICINST:
907 encode_generic_class (assembly, type->data.generic_class, buf);
911 sigbuffer_add_value (buf, type->type);
912 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
915 g_error ("need to encode type %x", type->type);
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
922 MONO_REQ_GC_UNSAFE_MODE;
925 sigbuffer_add_value (buf, MONO_TYPE_VOID);
929 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
935 MONO_REQ_GC_UNSAFE_MODE;
940 for (i = 0; i < mono_array_length (modreq); ++i) {
941 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
947 for (i = 0; i < mono_array_length (modopt); ++i) {
948 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
955 #ifndef DISABLE_REFLECTION_EMIT
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
959 MONO_REQ_GC_UNSAFE_MODE;
963 guint32 nparams = sig->param_count;
969 sigbuffer_init (&buf, 32);
971 * FIXME: vararg, explicit_this, differenc call_conv values...
973 idx = sig->call_convention;
975 idx |= 0x20; /* hasthis */
976 if (sig->generic_param_count)
977 idx |= 0x10; /* generic */
978 sigbuffer_add_byte (&buf, idx);
979 if (sig->generic_param_count)
980 sigbuffer_add_value (&buf, sig->generic_param_count);
981 sigbuffer_add_value (&buf, nparams);
982 encode_type (assembly, sig->ret, &buf);
983 for (i = 0; i < nparams; ++i) {
984 if (i == sig->sentinelpos)
985 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986 encode_type (assembly, sig->params [i], &buf);
988 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989 sigbuffer_free (&buf);
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
997 MONO_REQ_GC_UNSAFE_MODE;
1000 * FIXME: reuse code from method_encode_signature().
1004 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1005 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1009 sigbuffer_init (&buf, 32);
1010 /* LAMESPEC: all the call conv spec is foobared */
1011 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012 if (mb->call_conv & 2)
1013 idx |= 0x5; /* vararg */
1014 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015 idx |= 0x20; /* hasthis */
1017 idx |= 0x10; /* generic */
1018 sigbuffer_add_byte (&buf, idx);
1020 sigbuffer_add_value (&buf, ngparams);
1021 sigbuffer_add_value (&buf, nparams + notypes);
1022 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023 encode_reflection_type (assembly, mb->rtype, &buf);
1024 for (i = 0; i < nparams; ++i) {
1025 MonoArray *modreq = NULL;
1026 MonoArray *modopt = NULL;
1027 MonoReflectionType *pt;
1029 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035 encode_reflection_type (assembly, pt, &buf);
1038 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039 for (i = 0; i < notypes; ++i) {
1040 MonoReflectionType *pt;
1042 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043 encode_reflection_type (assembly, pt, &buf);
1046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047 sigbuffer_free (&buf);
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1054 MONO_REQ_GC_UNSAFE_MODE;
1056 MonoDynamicTable *table;
1058 guint32 idx, sig_idx;
1059 guint nl = mono_array_length (ilgen->locals);
1063 sigbuffer_init (&buf, 32);
1064 sigbuffer_add_value (&buf, 0x07);
1065 sigbuffer_add_value (&buf, nl);
1066 for (i = 0; i < nl; ++i) {
1067 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1070 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1072 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1074 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075 sigbuffer_free (&buf);
1077 if (assembly->standalonesig_cache == NULL)
1078 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1083 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084 idx = table->next_idx ++;
1086 alloc_table (table, table->rows);
1087 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1089 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1091 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 guint32 num_clauses = 0;
1104 MonoILExceptionInfo *ex_info;
1105 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107 if (ex_info->handlers)
1108 num_clauses += mono_array_length (ex_info->handlers);
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1120 MONO_REQ_GC_UNSAFE_MODE;
1122 MonoExceptionClause *clauses;
1123 MonoExceptionClause *clause;
1124 MonoILExceptionInfo *ex_info;
1125 MonoILExceptionBlock *ex_block;
1126 guint32 finally_start;
1127 int i, j, clause_index;;
1129 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1132 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134 finally_start = ex_info->start + ex_info->len;
1135 if (!ex_info->handlers)
1137 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139 clause = &(clauses [clause_index]);
1141 clause->flags = ex_block->type;
1142 clause->try_offset = ex_info->start;
1144 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145 clause->try_len = finally_start - ex_info->start;
1147 clause->try_len = ex_info->len;
1148 clause->handler_offset = ex_block->start;
1149 clause->handler_len = ex_block->len;
1150 if (ex_block->extype) {
1151 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1153 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154 clause->data.filter_offset = ex_block->filter_offset;
1156 clause->data.filter_offset = 0;
1158 finally_start = ex_block->start + ex_block->len;
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1169 * method_encode_code:
1171 * @assembly the assembly
1172 * @mb the managed MethodBuilder
1173 * @error set on error
1175 * Note that the return value is not sensible if @error is set.
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1180 MONO_REQ_GC_UNSAFE_MODE;
1185 gint32 max_stack, i;
1186 gint32 num_locals = 0;
1187 gint32 num_exception = 0;
1190 char fat_header [12];
1192 guint16 short_value;
1193 guint32 local_sig = 0;
1194 guint32 header_size = 12;
1197 mono_error_init (error);
1199 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1204 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1206 code = mb->ilgen->code;
1207 code_size = mb->ilgen->code_len;
1208 max_stack = mb->ilgen->max_stack;
1209 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210 if (mb->ilgen->ex_handlers)
1211 num_exception = method_count_clauses (mb->ilgen);
1215 char *name = mono_string_to_utf8 (mb->name);
1216 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1223 code_size = mono_array_length (code);
1224 max_stack = 8; /* we probably need to run a verifier on the code... */
1227 stream_data_align (&assembly->code);
1229 /* check for exceptions, maxstack, locals */
1230 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1232 if (code_size < 64 && !(code_size & 1)) {
1233 flags = (code_size << 2) | 0x2;
1234 } else if (code_size < 32 && (code_size & 1)) {
1235 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1239 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240 /* add to the fixup todo list */
1241 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244 return assembly->text_rva + idx;
1248 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1250 * FIXME: need to set also the header size in fat_flags.
1251 * (and more sects and init locals flags)
1255 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256 if (mb->init_locals)
1257 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258 fat_header [0] = fat_flags;
1259 fat_header [1] = (header_size / 4 ) << 4;
1260 short_value = GUINT16_TO_LE (max_stack);
1261 memcpy (fat_header + 2, &short_value, 2);
1262 int_value = GUINT32_TO_LE (code_size);
1263 memcpy (fat_header + 4, &int_value, 4);
1264 int_value = GUINT32_TO_LE (local_sig);
1265 memcpy (fat_header + 8, &int_value, 4);
1266 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267 /* add to the fixup todo list */
1268 if (mb->ilgen && mb->ilgen->num_token_fixups)
1269 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1271 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272 if (num_exception) {
1273 unsigned char sheader [4];
1274 MonoILExceptionInfo * ex_info;
1275 MonoILExceptionBlock * ex_block;
1278 stream_data_align (&assembly->code);
1279 /* always use fat format for now */
1280 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281 num_exception *= 6 * sizeof (guint32);
1282 num_exception += 4; /* include the size of the header */
1283 sheader [1] = num_exception & 0xff;
1284 sheader [2] = (num_exception >> 8) & 0xff;
1285 sheader [3] = (num_exception >> 16) & 0xff;
1286 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287 /* fat header, so we are already aligned */
1289 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291 if (ex_info->handlers) {
1292 int finally_start = ex_info->start + ex_info->len;
1293 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1295 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1297 val = GUINT32_TO_LE (ex_block->type);
1298 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1300 val = GUINT32_TO_LE (ex_info->start);
1301 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302 /* need fault, too, probably */
1303 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304 val = GUINT32_TO_LE (finally_start - ex_info->start);
1306 val = GUINT32_TO_LE (ex_info->len);
1307 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308 /* handler offset */
1309 val = GUINT32_TO_LE (ex_block->start);
1310 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1312 val = GUINT32_TO_LE (ex_block->len);
1313 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314 finally_start = ex_block->start + ex_block->len;
1315 if (ex_block->extype) {
1316 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1318 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319 val = ex_block->filter_offset;
1323 val = GUINT32_TO_LE (val);
1324 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1326 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1329 g_error ("No clauses for ex info block %d", i);
1333 return assembly->text_rva + idx;
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1339 MONO_REQ_GC_NEUTRAL_MODE;
1342 MonoDynamicTable *table;
1345 table = &assembly->tables [table_idx];
1347 g_assert (col < table->columns);
1349 values = table->values + table->columns;
1350 for (i = 1; i <= table->rows; ++i) {
1351 if (values [col] == token)
1353 values += table->columns;
1359 * LOCKING: Acquires the loader lock.
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1364 MONO_REQ_GC_NEUTRAL_MODE;
1366 MonoCustomAttrInfo* res;
1368 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1373 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1381 MONO_REQ_GC_UNSAFE_MODE;
1383 /* FIXME: Need to do more checks */
1384 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1387 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1397 MONO_REQ_GC_UNSAFE_MODE;
1399 int i, index, count, not_visible;
1400 MonoCustomAttrInfo *ainfo;
1401 MonoReflectionCustomAttr *cattr;
1405 /* FIXME: check in assembly the Run flag is set */
1407 count = mono_array_length (cattrs);
1409 /* Skip nonpublic attributes since MS.NET seems to do the same */
1410 /* FIXME: This needs to be done more globally */
1412 for (i = 0; i < count; ++i) {
1413 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414 if (!custom_attr_visible (image, cattr))
1417 count -= not_visible;
1419 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1421 ainfo->image = image;
1422 ainfo->num_attrs = count;
1423 ainfo->cached = alloc_img != NULL;
1425 for (i = 0; i < count; ++i) {
1426 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427 if (custom_attr_visible (image, cattr)) {
1428 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430 ainfo->attrs [index].ctor = cattr->ctor->method;
1431 ainfo->attrs [index].data = saved;
1432 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1440 #ifndef DISABLE_REFLECTION_EMIT
1442 * LOCKING: Acquires the loader lock.
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1447 MONO_REQ_GC_UNSAFE_MODE;
1449 MonoCustomAttrInfo *ainfo, *tmp;
1451 if (!cattrs || !mono_array_length (cattrs))
1454 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1456 mono_loader_lock ();
1457 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1459 mono_custom_attrs_free (tmp);
1460 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461 mono_loader_unlock ();
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1469 MONO_REQ_GC_NEUTRAL_MODE;
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 (method);
7558 if (!image_is_dynamic (image)) {
7559 /* Obtain local vars signature token */
7560 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7561 ptr = mono_image_rva_map (image, method_rva);
7562 flags = *(const unsigned char *) ptr;
7563 format = flags & METHOD_HEADER_FORMAT_MASK;
7565 case METHOD_HEADER_TINY_FORMAT:
7566 local_var_sig_token = 0;
7568 case METHOD_HEADER_FAT_FORMAT:
7572 local_var_sig_token = read32 (ptr);
7575 g_assert_not_reached ();
7578 local_var_sig_token = 0; //FIXME
7580 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7581 mono_error_raise_exception (&error); /* FIXME don't raise here */
7583 ret->init_locals = header->init_locals;
7584 ret->max_stack = header->max_stack;
7585 ret->local_var_sig_token = local_var_sig_token;
7586 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7587 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7590 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7591 for (i = 0; i < header->num_locals; ++i) {
7592 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7593 mono_error_raise_exception (&error); /* FIXME don't raise here */
7595 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7596 mono_error_raise_exception (&error); /* FIXME don't raise here */
7598 MONO_OBJECT_SETREF (info, local_type, rt);
7600 info->is_pinned = header->locals [i]->pinned;
7601 info->local_index = i;
7602 mono_array_setref (ret->locals, i, info);
7606 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7607 for (i = 0; i < header->num_clauses; ++i) {
7608 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7609 mono_error_raise_exception (&error); /* FIXME don't raise here */
7610 MonoExceptionClause *clause = &header->clauses [i];
7612 info->flags = clause->flags;
7613 info->try_offset = clause->try_offset;
7614 info->try_length = clause->try_len;
7615 info->handler_offset = clause->handler_offset;
7616 info->handler_length = clause->handler_len;
7617 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7618 info->filter_offset = clause->data.filter_offset;
7619 else if (clause->data.catch_class) {
7620 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7621 mono_error_raise_exception (&error); /* FIXME don't raise here */
7623 MONO_OBJECT_SETREF (info, catch_type, rt);
7626 mono_array_setref (ret->clauses, i, info);
7629 mono_metadata_free_mh (header);
7630 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7635 * mono_get_dbnull_object:
7636 * @domain: Domain where the object lives
7638 * Returns the System.DBNull.Value singleton object
7640 * Used as the value for ParameterInfo.DefaultValue
7643 mono_get_dbnull_object (MonoDomain *domain)
7646 static MonoClassField *dbnull_value_field = NULL;
7648 if (!dbnull_value_field) {
7649 MonoClass *dbnull_klass;
7650 dbnull_klass = mono_class_get_dbnull_class ();
7651 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7652 g_assert (dbnull_value_field);
7654 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7660 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7662 guint32 param_index, i, lastp, crow = 0;
7663 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7666 MonoClass *klass = method->klass;
7667 MonoImage *image = klass->image;
7668 MonoMethodSignature *methodsig = mono_method_signature (method);
7670 MonoTableInfo *constt;
7671 MonoTableInfo *methodt;
7672 MonoTableInfo *paramt;
7674 if (!methodsig->param_count)
7677 mono_class_init (klass);
7679 if (image_is_dynamic (klass->image)) {
7680 MonoReflectionMethodAux *aux;
7681 if (method->is_inflated)
7682 method = ((MonoMethodInflated*)method)->declaring;
7683 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7684 if (aux && aux->param_defaults) {
7685 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7686 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7691 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7692 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7693 constt = &image->tables [MONO_TABLE_CONSTANT];
7695 idx = mono_method_get_index (method) - 1;
7696 g_assert (idx != -1);
7698 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7699 if (idx + 1 < methodt->rows)
7700 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7702 lastp = paramt->rows + 1;
7704 for (i = param_index; i < lastp; ++i) {
7707 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7708 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7710 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7713 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7718 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7719 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7720 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7727 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7733 MonoType *basetype = type;
7738 klass = mono_class_from_mono_type (type);
7739 if (klass->valuetype) {
7740 object = mono_object_new_checked (domain, klass, &error);
7741 mono_error_raise_exception (&error); /* FIXME don't raise here */
7742 retval = ((gchar *) object + sizeof (MonoObject));
7743 if (klass->enumtype)
7744 basetype = mono_class_enum_basetype (klass);
7749 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7756 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7759 gboolean quoted = FALSE;
7761 memset (assembly, 0, sizeof (MonoAssemblyName));
7762 assembly->culture = "";
7763 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7770 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7781 /* Remove trailing whitespace */
7783 while (*s && g_ascii_isspace (*s))
7786 while (g_ascii_isspace (*p))
7789 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7791 assembly->major = strtoul (p, &s, 10);
7792 if (s == p || *s != '.')
7795 assembly->minor = strtoul (p, &s, 10);
7796 if (s == p || *s != '.')
7799 assembly->build = strtoul (p, &s, 10);
7800 if (s == p || *s != '.')
7803 assembly->revision = strtoul (p, &s, 10);
7807 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7809 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7810 assembly->culture = "";
7813 assembly->culture = p;
7814 while (*p && *p != ',') {
7818 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7820 if (strncmp (p, "null", 4) == 0) {
7825 while (*p && *p != ',') {
7828 len = (p - start + 1);
7829 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7830 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7831 g_strlcpy ((char*)assembly->public_key_token, start, len);
7834 while (*p && *p != ',')
7838 while (g_ascii_isspace (*p) || *p == ',') {
7852 * mono_reflection_parse_type:
7855 * Parse a type name as accepted by the GetType () method and output the info
7856 * extracted in the info structure.
7857 * the name param will be mangled, so, make a copy before passing it to this function.
7858 * The fields in info will be valid until the memory pointed to by name is valid.
7860 * See also mono_type_get_name () below.
7862 * Returns: 0 on parse error.
7865 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7866 MonoTypeNameParse *info)
7868 char *start, *p, *w, *last_point, *startn;
7869 int in_modifiers = 0;
7870 int isbyref = 0, rank = 0, isptr = 0;
7872 start = p = w = name;
7874 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7875 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7876 info->name = info->name_space = NULL;
7877 info->nested = NULL;
7878 info->modifiers = NULL;
7879 info->type_arguments = NULL;
7881 /* last_point separates the namespace from the name */
7884 while (*p == ' ') p++, start++, w++, name++;
7889 *p = 0; /* NULL terminate the name */
7891 info->nested = g_list_append (info->nested, startn);
7892 /* we have parsed the nesting namespace + name */
7896 info->name_space = start;
7898 info->name = last_point + 1;
7900 info->name_space = (char *)"";
7928 info->name_space = start;
7930 info->name = last_point + 1;
7932 info->name_space = (char *)"";
7939 if (isbyref) /* only one level allowed by the spec */
7943 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7947 if (isbyref) /* pointer to ref not okay */
7949 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7954 if (isbyref) /* array of ref and generic ref are not okay */
7956 //Decide if it's an array of a generic argument list
7961 if (*p == ',' || *p == '*' || *p == ']') { //array
7969 else if (*p == '*') /* '*' means unknown lower bound */
7970 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7977 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7979 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7982 info->type_arguments = g_ptr_array_new ();
7984 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7985 gboolean fqname = FALSE;
7987 g_ptr_array_add (info->type_arguments, subinfo);
7989 while (*p == ' ') p++;
7995 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7998 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7999 if (fqname && (*p != ']')) {
8007 while (*p && (*p != ']'))
8015 if (g_ascii_isspace (*aname)) {
8022 !assembly_name_to_aname (&subinfo->assembly, aname))
8024 } else if (fqname && (*p == ']')) {
8046 if (g_ascii_isspace (*p)) {
8053 return 0; /* missing assembly name */
8054 if (!assembly_name_to_aname (&info->assembly, p))
8060 if (info->assembly.name)
8063 // *w = 0; /* terminate class name */
8065 if (!info->name || !*info->name)
8069 /* add other consistency checks */
8075 * mono_identifier_unescape_type_name_chars:
8076 * @identifier: the display name of a mono type
8079 * The name in internal form, that is without escaping backslashes.
8081 * The string is modified in place!
8084 mono_identifier_unescape_type_name_chars(char* identifier)
8089 for (w = r = identifier; *r != 0; r++)
8107 mono_identifier_unescape_info (MonoTypeNameParse* info);
8110 unescape_each_type_argument(void* data, void* user_data)
8112 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8113 mono_identifier_unescape_info (info);
8117 unescape_each_nested_name (void* data, void* user_data)
8119 char* nested_name = (char*) data;
8120 mono_identifier_unescape_type_name_chars(nested_name);
8124 * mono_identifier_unescape_info:
8126 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8130 * Destructively updates the info by unescaping the identifiers that
8131 * comprise the type namespace, name, nested types (if any) and
8132 * generic type arguments (if any).
8134 * The resulting info has the names in internal form.
8138 mono_identifier_unescape_info (MonoTypeNameParse *info)
8142 mono_identifier_unescape_type_name_chars(info->name_space);
8143 mono_identifier_unescape_type_name_chars(info->name);
8144 // but don't escape info->assembly
8145 if (info->type_arguments)
8146 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8148 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8152 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8154 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8156 mono_identifier_unescape_info (info);
8162 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8164 gboolean type_resolve = FALSE;
8166 MonoImage *rootimage = image;
8168 if (info->assembly.name) {
8169 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8170 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8172 * This could happen in the AOT compiler case when the search hook is not
8175 assembly = image->assembly;
8177 /* then we must load the assembly ourselve - see #60439 */
8178 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8182 image = assembly->image;
8183 } else if (!image) {
8184 image = mono_defaults.corlib;
8187 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8188 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8189 image = mono_defaults.corlib;
8190 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8197 * mono_reflection_get_type_internal:
8199 * Returns: may return NULL on success, sets error on failure.
8202 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8207 gboolean bounded = FALSE;
8209 mono_error_init (error);
8211 image = mono_defaults.corlib;
8214 rootimage = mono_defaults.corlib;
8217 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8219 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8224 for (mod = info->nested; mod; mod = mod->next) {
8225 gpointer iter = NULL;
8229 mono_class_init (parent);
8231 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8233 char *nested_name, *nested_nspace;
8234 gboolean match = TRUE;
8236 lastp = strrchr ((const char *)mod->data, '.');
8238 /* Nested classes can have namespaces */
8241 nested_name = g_strdup (lastp + 1);
8242 nspace_len = lastp - (char*)mod->data;
8243 nested_nspace = (char *)g_malloc (nspace_len + 1);
8244 memcpy (nested_nspace, mod->data, nspace_len);
8245 nested_nspace [nspace_len] = '\0';
8248 nested_name = (char *)mod->data;
8249 nested_nspace = NULL;
8252 if (nested_nspace) {
8254 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8257 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8263 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8266 if (strcmp (klass->name, nested_name) != 0)
8271 g_free (nested_name);
8272 g_free (nested_nspace);
8284 if (info->type_arguments) {
8285 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8286 MonoReflectionType *the_type;
8290 for (i = 0; i < info->type_arguments->len; i++) {
8291 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8293 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8294 if (!type_args [i]) {
8300 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8304 instance = mono_reflection_bind_generic_parameters (
8305 the_type, info->type_arguments->len, type_args);
8311 klass = mono_class_from_mono_type (instance);
8314 for (mod = info->modifiers; mod; mod = mod->next) {
8315 modval = GPOINTER_TO_UINT (mod->data);
8316 if (!modval) { /* byref: must be last modifier */
8317 return &klass->this_arg;
8318 } else if (modval == -1) {
8319 klass = mono_ptr_class_get (&klass->byval_arg);
8320 } else if (modval == -2) {
8322 } else { /* array rank */
8323 klass = mono_bounded_array_class_get (klass, modval, bounded);
8327 return &klass->byval_arg;
8331 * mono_reflection_get_type:
8332 * @image: a metadata context
8333 * @info: type description structure
8334 * @ignorecase: flag for case-insensitive string compares
8335 * @type_resolve: whenever type resolve was already tried
8337 * Build a MonoType from the type description in @info.
8342 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8343 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8347 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8349 MonoReflectionAssemblyBuilder *abuilder;
8353 mono_error_init (error);
8354 g_assert (assembly_is_dynamic (assembly));
8355 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8359 /* Enumerate all modules */
8362 if (abuilder->modules) {
8363 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8364 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8365 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8368 if (!mono_error_ok (error))
8373 if (!type && abuilder->loaded_modules) {
8374 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8375 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8376 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8379 if (!mono_error_ok (error))
8388 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8392 MonoReflectionAssembly *assembly;
8396 if (image && image_is_dynamic (image))
8397 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8399 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8401 if (!mono_error_ok (&error))
8402 mono_error_raise_exception (&error); /* FIXME don't raise here */
8406 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8413 *type_resolve = TRUE;
8416 /* Reconstruct the type name */
8417 fullName = g_string_new ("");
8418 if (info->name_space && (info->name_space [0] != '\0'))
8419 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8421 g_string_printf (fullName, "%s", info->name);
8422 for (mod = info->nested; mod; mod = mod->next)
8423 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8425 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8426 mono_error_raise_exception (&error); /* FIXME don't raise here */
8429 if (assembly_is_dynamic (assembly->assembly))
8430 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8431 info, ignorecase, &error);
8433 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8434 info, ignorecase, &error);
8436 g_string_free (fullName, TRUE);
8437 if (!mono_error_ok (&error))
8438 mono_error_raise_exception (&error); /* FIXME don't raise here */
8443 mono_reflection_free_type_info (MonoTypeNameParse *info)
8445 g_list_free (info->modifiers);
8446 g_list_free (info->nested);
8448 if (info->type_arguments) {
8451 for (i = 0; i < info->type_arguments->len; i++) {
8452 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8454 mono_reflection_free_type_info (subinfo);
8455 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8459 g_ptr_array_free (info->type_arguments, TRUE);
8464 * mono_reflection_type_from_name:
8466 * @image: a metadata context (can be NULL).
8468 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8469 * it defaults to get the type from @image or, if @image is NULL or loading
8470 * from it fails, uses corlib.
8474 mono_reflection_type_from_name (char *name, MonoImage *image)
8476 MonoType *type = NULL;
8477 MonoTypeNameParse info;
8480 /* Make a copy since parse_type modifies its argument */
8481 tmp = g_strdup (name);
8483 /*g_print ("requested type %s\n", str);*/
8484 if (mono_reflection_parse_type (tmp, &info)) {
8485 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8489 mono_reflection_free_type_info (&info);
8494 * mono_reflection_get_token:
8496 * Return the metadata token of OBJ which should be an object
8497 * representing a metadata element.
8500 mono_reflection_get_token (MonoObject *obj)
8505 klass = obj->vtable->klass;
8507 if (strcmp (klass->name, "MethodBuilder") == 0) {
8508 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8510 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8511 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8512 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8514 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8515 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8516 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8518 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8519 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8520 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8521 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8522 } else if (strcmp (klass->name, "MonoType") == 0) {
8523 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8524 MonoClass *mc = mono_class_from_mono_type (type);
8525 if (!mono_class_init (mc))
8526 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8528 token = mc->type_token;
8529 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8530 strcmp (klass->name, "MonoMethod") == 0 ||
8531 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8532 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8533 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8534 if (m->method->is_inflated) {
8535 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8536 return inflated->declaring->token;
8538 token = m->method->token;
8540 } else if (strcmp (klass->name, "MonoField") == 0) {
8541 MonoReflectionField *f = (MonoReflectionField*)obj;
8543 if (is_field_on_inst (f->field)) {
8544 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8546 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8547 int field_index = f->field - dgclass->fields;
8550 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8551 obj = dgclass->field_objects [field_index];
8552 return mono_reflection_get_token (obj);
8555 token = mono_class_get_field_token (f->field);
8556 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8557 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8559 token = mono_class_get_property_token (p->property);
8560 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8561 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8563 token = mono_class_get_event_token (p->event);
8564 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8565 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8566 MonoClass *member_class = mono_object_class (p->MemberImpl);
8567 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8569 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8570 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8571 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8574 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8575 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8577 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8578 MonoException *ex = mono_get_exception_not_implemented (msg);
8580 mono_raise_exception (ex);
8587 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8591 int slen = mono_metadata_decode_value (p, &p);
8593 mono_error_init (error);
8595 n = (char *)g_memdup (p, slen + 1);
8597 t = mono_reflection_type_from_name (n, image);
8599 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8600 /* We don't free n, it's consumed by mono_error */
8601 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8607 return mono_class_from_mono_type (t);
8611 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8613 int slen, type = t->type;
8614 MonoClass *tklass = t->data.klass;
8616 mono_error_init (error);
8622 case MONO_TYPE_BOOLEAN: {
8623 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8628 case MONO_TYPE_CHAR:
8630 case MONO_TYPE_I2: {
8631 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8636 #if SIZEOF_VOID_P == 4
8642 case MONO_TYPE_I4: {
8643 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8648 #if SIZEOF_VOID_P == 8
8649 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8653 case MONO_TYPE_I8: {
8654 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8659 case MONO_TYPE_R8: {
8660 double *val = (double *)g_malloc (sizeof (double));
8665 case MONO_TYPE_VALUETYPE:
8666 if (t->data.klass->enumtype) {
8667 type = mono_class_enum_basetype (t->data.klass)->type;
8670 MonoClass *k = t->data.klass;
8672 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8673 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8679 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8682 case MONO_TYPE_STRING:
8683 if (*p == (char)0xFF) {
8687 slen = mono_metadata_decode_value (p, &p);
8689 return mono_string_new_len (mono_domain_get (), p, slen);
8690 case MONO_TYPE_CLASS: {
8691 MonoReflectionType *rt;
8694 if (*p == (char)0xFF) {
8699 slen = mono_metadata_decode_value (p, &p);
8700 n = (char *)g_memdup (p, slen + 1);
8702 t = mono_reflection_type_from_name (n, image);
8704 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8705 /* We don't free n, it's consumed by mono_error */
8706 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8712 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8713 if (!mono_error_ok (error))
8718 case MONO_TYPE_OBJECT: {
8721 MonoClass *subc = NULL;
8726 } else if (subt == 0x0E) {
8727 type = MONO_TYPE_STRING;
8729 } else if (subt == 0x1D) {
8730 MonoType simple_type = {{0}};
8734 type = MONO_TYPE_SZARRAY;
8735 if (etype == 0x50) {
8736 tklass = mono_defaults.systemtype_class;
8737 } else if (etype == 0x55) {
8738 tklass = load_cattr_enum_type (image, p, &p, error);
8739 if (!mono_error_ok (error))
8743 /* See Partition II, Appendix B3 */
8744 etype = MONO_TYPE_OBJECT;
8745 simple_type.type = (MonoTypeEnum)etype;
8746 tklass = mono_class_from_mono_type (&simple_type);
8749 } else if (subt == 0x55) {
8752 slen = mono_metadata_decode_value (p, &p);
8753 n = (char *)g_memdup (p, slen + 1);
8755 t = mono_reflection_type_from_name (n, image);
8757 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8758 /* We don't free n, it's consumed by mono_error */
8759 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8764 subc = mono_class_from_mono_type (t);
8765 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8766 MonoType simple_type = {{0}};
8767 simple_type.type = (MonoTypeEnum)subt;
8768 subc = mono_class_from_mono_type (&simple_type);
8770 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8772 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8774 if (mono_error_ok (error)) {
8775 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8776 g_assert (!subc->has_references);
8777 if (mono_error_ok (error))
8778 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8784 case MONO_TYPE_SZARRAY: {
8786 guint32 i, alen, basetype;
8789 if (alen == 0xffffffff) {
8793 arr = mono_array_new (mono_domain_get(), tklass, alen);
8794 basetype = tklass->byval_arg.type;
8795 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8796 basetype = mono_class_enum_basetype (tklass)->type;
8801 case MONO_TYPE_BOOLEAN:
8802 for (i = 0; i < alen; i++) {
8803 MonoBoolean val = *p++;
8804 mono_array_set (arr, MonoBoolean, i, val);
8807 case MONO_TYPE_CHAR:
8810 for (i = 0; i < alen; i++) {
8811 guint16 val = read16 (p);
8812 mono_array_set (arr, guint16, i, val);
8819 for (i = 0; i < alen; i++) {
8820 guint32 val = read32 (p);
8821 mono_array_set (arr, guint32, i, val);
8826 for (i = 0; i < alen; i++) {
8829 mono_array_set (arr, double, i, val);
8835 for (i = 0; i < alen; i++) {
8836 guint64 val = read64 (p);
8837 mono_array_set (arr, guint64, i, val);
8841 case MONO_TYPE_CLASS:
8842 case MONO_TYPE_OBJECT:
8843 case MONO_TYPE_STRING:
8844 case MONO_TYPE_SZARRAY:
8845 for (i = 0; i < alen; i++) {
8846 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8847 if (!mono_error_ok (error))
8849 mono_array_setref (arr, i, item);
8853 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8859 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8865 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8867 static MonoMethod *ctor;
8869 void *params [2], *unboxed;
8871 mono_error_init (error);
8874 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8876 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8877 return_val_if_nok (error, NULL);
8880 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8881 return_val_if_nok (error, NULL);
8882 unboxed = mono_object_unbox (retval);
8884 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8885 return_val_if_nok (error, NULL);
8891 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8893 static MonoMethod *ctor;
8895 void *unboxed, *params [2];
8897 mono_error_init (error);
8900 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8903 params [1] = typedarg;
8904 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8905 return_val_if_nok (error, NULL);
8907 unboxed = mono_object_unbox (retval);
8909 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8910 return_val_if_nok (error, NULL);
8916 type_is_reference (MonoType *type)
8918 switch (type->type) {
8919 case MONO_TYPE_BOOLEAN:
8920 case MONO_TYPE_CHAR:
8933 case MONO_TYPE_VALUETYPE:
8941 free_param_data (MonoMethodSignature *sig, void **params) {
8943 for (i = 0; i < sig->param_count; ++i) {
8944 if (!type_is_reference (sig->params [i]))
8945 g_free (params [i]);
8950 * Find the field index in the metadata FieldDef table.
8953 find_field_index (MonoClass *klass, MonoClassField *field) {
8956 for (i = 0; i < klass->field.count; ++i) {
8957 if (field == &klass->fields [i])
8958 return klass->field.first + 1 + i;
8964 * Find the property index in the metadata Property table.
8967 find_property_index (MonoClass *klass, MonoProperty *property) {
8970 for (i = 0; i < klass->ext->property.count; ++i) {
8971 if (property == &klass->ext->properties [i])
8972 return klass->ext->property.first + 1 + i;
8978 * Find the event index in the metadata Event table.
8981 find_event_index (MonoClass *klass, MonoEvent *event) {
8984 for (i = 0; i < klass->ext->event.count; ++i) {
8985 if (event == &klass->ext->events [i])
8986 return klass->ext->event.first + 1 + i;
8992 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8994 const char *p = (const char*)data;
8996 guint32 i, j, num_named;
8998 void *params_buf [32];
8999 void **params = NULL;
9000 MonoMethodSignature *sig;
9001 MonoObject *exc = NULL;
9003 mono_error_init (error);
9005 mono_class_init (method->klass);
9007 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9008 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9013 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9014 if (!mono_error_ok (error)) return NULL;
9016 mono_runtime_invoke_checked (method, attr, NULL, error);
9017 if (!mono_error_ok (error))
9023 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9026 /*g_print ("got attr %s\n", method->klass->name);*/
9028 sig = mono_method_signature (method);
9029 if (sig->param_count < 32) {
9030 params = params_buf;
9031 memset (params, 0, sizeof (void*) * sig->param_count);
9033 /* Allocate using GC so it gets GC tracking */
9034 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9039 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9040 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9041 if (!mono_error_ok (error))
9046 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9047 if (!mono_error_ok (error)) goto fail;
9049 mono_runtime_try_invoke (method, attr, params, &exc, error);
9050 if (!mono_error_ok (error))
9055 num_named = read16 (named);
9057 for (j = 0; j < num_named; j++) {
9059 char *name, named_type, data_type;
9060 named_type = *named++;
9061 data_type = *named++; /* type of data */
9062 if (data_type == MONO_TYPE_SZARRAY)
9063 data_type = *named++;
9064 if (data_type == MONO_TYPE_ENUM) {
9067 type_len = mono_metadata_decode_blob_size (named, &named);
9068 type_name = (char *)g_malloc (type_len + 1);
9069 memcpy (type_name, named, type_len);
9070 type_name [type_len] = 0;
9072 /* FIXME: lookup the type and check type consistency */
9075 name_len = mono_metadata_decode_blob_size (named, &named);
9076 name = (char *)g_malloc (name_len + 1);
9077 memcpy (name, named, name_len);
9078 name [name_len] = 0;
9080 if (named_type == 0x53) {
9081 MonoClassField *field;
9084 /* how this fail is a blackbox */
9085 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9087 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9092 val = load_cattr_value (image, field->type, named, &named, error);
9093 if (!mono_error_ok (error)) {
9095 if (!type_is_reference (field->type))
9100 mono_field_set_value (attr, field, val);
9101 if (!type_is_reference (field->type))
9103 } else if (named_type == 0x54) {
9106 MonoType *prop_type;
9108 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9111 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9117 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9122 /* can we have more that 1 arg in a custom attr named property? */
9123 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9124 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9126 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9127 if (!mono_error_ok (error)) {
9129 if (!type_is_reference (prop_type))
9130 g_free (pparams [0]);
9135 mono_property_set_value (prop, attr, pparams, NULL);
9136 if (!type_is_reference (prop_type))
9137 g_free (pparams [0]);
9142 free_param_data (method->signature, params);
9143 if (params != params_buf)
9144 mono_gc_free_fixed (params);
9149 free_param_data (method->signature, params);
9150 if (params != params_buf)
9151 mono_gc_free_fixed (params);
9153 mono_raise_exception ((MonoException*)exc);
9158 * mono_reflection_create_custom_attr_data_args:
9160 * Create an array of typed and named arguments from the cattr blob given by DATA.
9161 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9162 * NAMED_ARG_INFO will contain information about the named arguments.
9165 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)
9167 MonoArray *typedargs, *namedargs;
9168 MonoClass *attrklass;
9170 const char *p = (const char*)data;
9172 guint32 i, j, num_named;
9173 CattrNamedArg *arginfo = NULL;
9177 *named_arg_info = NULL;
9179 mono_error_init (error);
9181 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9182 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9186 mono_class_init (method->klass);
9188 domain = mono_domain_get ();
9190 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9193 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9197 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9201 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9202 if (!mono_error_ok (error)) {
9203 if (!type_is_reference (mono_method_signature (method)->params [i]))
9208 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9209 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9210 mono_array_setref (typedargs, i, obj);
9212 if (!type_is_reference (mono_method_signature (method)->params [i]))
9217 num_named = read16 (named);
9218 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9220 attrklass = method->klass;
9222 arginfo = g_new0 (CattrNamedArg, num_named);
9223 *named_arg_info = arginfo;
9225 for (j = 0; j < num_named; j++) {
9227 char *name, named_type, data_type;
9228 named_type = *named++;
9229 data_type = *named++; /* type of data */
9230 if (data_type == MONO_TYPE_SZARRAY)
9231 data_type = *named++;
9232 if (data_type == MONO_TYPE_ENUM) {
9235 type_len = mono_metadata_decode_blob_size (named, &named);
9236 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9239 type_name = (char *)g_malloc (type_len + 1);
9240 memcpy (type_name, named, type_len);
9241 type_name [type_len] = 0;
9243 /* FIXME: lookup the type and check type consistency */
9246 name_len = mono_metadata_decode_blob_size (named, &named);
9247 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9249 name = (char *)g_malloc (name_len + 1);
9250 memcpy (name, named, name_len);
9251 name [name_len] = 0;
9253 if (named_type == 0x53) {
9255 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9263 arginfo [j].type = field->type;
9264 arginfo [j].field = field;
9266 val = load_cattr_value (image, field->type, named, &named, error);
9267 if (!mono_error_ok (error)) {
9268 if (!type_is_reference (field->type))
9274 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9275 mono_array_setref (namedargs, j, obj);
9276 if (!type_is_reference (field->type))
9278 } else if (named_type == 0x54) {
9280 MonoType *prop_type;
9281 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9284 if (!prop || !prop->set) {
9289 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9290 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9292 arginfo [j].type = prop_type;
9293 arginfo [j].prop = prop;
9295 val = load_cattr_value (image, prop_type, named, &named, error);
9296 if (!mono_error_ok (error)) {
9297 if (!type_is_reference (prop_type))
9303 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9304 mono_array_setref (namedargs, j, obj);
9305 if (!type_is_reference (prop_type))
9311 *typed_args = typedargs;
9312 *named_args = namedargs;
9315 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9317 *named_arg_info = NULL;
9321 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9324 MonoArray *typedargs, *namedargs;
9327 CattrNamedArg *arginfo = NULL;
9331 mono_error_init (&error);
9339 image = assembly->assembly->image;
9340 method = ref_method->method;
9341 domain = mono_object_domain (ref_method);
9343 if (!mono_class_init (method->klass))
9344 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9346 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9347 if (!mono_error_ok (&error))
9350 if (mono_loader_get_last_error ()) {
9351 mono_error_set_from_loader_error (&error);
9355 if (!typedargs || !namedargs)
9358 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9359 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9360 MonoObject *typedarg;
9362 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9363 if (!is_ok (&error))
9365 mono_array_setref (typedargs, i, typedarg);
9368 for (i = 0; i < mono_array_length (namedargs); ++i) {
9369 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9370 MonoObject *typedarg, *namedarg, *minfo;
9372 if (arginfo [i].prop) {
9373 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9377 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9378 if (!mono_error_ok (&error))
9382 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9383 if (!is_ok (&error))
9385 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9386 if (!is_ok (&error))
9389 mono_array_setref (namedargs, i, namedarg);
9392 *ctor_args = typedargs;
9393 *named_args = namedargs;
9396 mono_error_raise_exception (&error);
9401 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9403 static MonoMethod *ctor;
9409 mono_error_init (error);
9411 g_assert (image->assembly);
9414 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9416 domain = mono_domain_get ();
9417 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9418 return_val_if_nok (error, NULL);
9419 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9420 return_val_if_nok (error, NULL);
9421 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9422 return_val_if_nok (error, NULL);
9423 params [2] = (gpointer)&cattr->data;
9424 params [3] = &cattr->data_size;
9426 mono_runtime_invoke_checked (ctor, attr, params, error);
9427 return_val_if_nok (error, NULL);
9432 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9438 mono_error_init (error);
9441 for (i = 0; i < cinfo->num_attrs; ++i) {
9442 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9446 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9448 for (i = 0; i < cinfo->num_attrs; ++i) {
9449 if (!cinfo->attrs [i].ctor) {
9450 /* The cattr type is not finished yet */
9451 /* We should include the type name but cinfo doesn't contain it */
9452 mono_error_set_type_load_name (error, NULL, NULL, "");
9455 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9456 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9457 if (!mono_error_ok (error))
9459 mono_array_setref (result, n, attr);
9467 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9470 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9471 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9477 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9483 mono_error_init (error);
9484 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9485 for (i = 0; i < cinfo->num_attrs; ++i) {
9486 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9487 return_val_if_nok (error, NULL);
9488 mono_array_setref (result, i, attr);
9494 * mono_custom_attrs_from_index:
9496 * Returns: NULL if no attributes are found or if a loading error occurs.
9499 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9501 guint32 mtoken, i, len;
9502 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9504 MonoCustomAttrInfo *ainfo;
9505 GList *tmp, *list = NULL;
9507 MonoCustomAttrEntry* attr;
9509 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9511 i = mono_metadata_custom_attrs_from_index (image, idx);
9515 while (i < ca->rows) {
9516 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9518 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9521 len = g_list_length (list);
9524 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9525 ainfo->num_attrs = len;
9526 ainfo->image = image;
9527 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9529 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9530 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9531 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9532 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9533 mtoken |= MONO_TOKEN_METHOD_DEF;
9535 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9536 mtoken |= MONO_TOKEN_MEMBER_REF;
9539 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9542 attr = &ainfo->attrs [i - 1];
9543 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9545 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9546 mono_loader_set_error_from_mono_error (&error);
9552 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9553 /*FIXME raising an exception here doesn't make any sense*/
9554 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9559 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9560 attr->data_size = mono_metadata_decode_value (data, &data);
9561 attr->data = (guchar*)data;
9569 mono_custom_attrs_from_method (MonoMethod *method)
9574 * An instantiated method has the same cattrs as the generic method definition.
9576 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9577 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9579 if (method->is_inflated)
9580 method = ((MonoMethodInflated *) method)->declaring;
9582 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9583 return lookup_custom_attr (method->klass->image, method);
9586 /* Synthetic methods */
9589 idx = mono_method_get_index (method);
9590 idx <<= MONO_CUSTOM_ATTR_BITS;
9591 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9592 return mono_custom_attrs_from_index (method->klass->image, idx);
9596 mono_custom_attrs_from_class (MonoClass *klass)
9600 if (klass->generic_class)
9601 klass = klass->generic_class->container_class;
9603 if (image_is_dynamic (klass->image))
9604 return lookup_custom_attr (klass->image, klass);
9606 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9607 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9608 idx <<= MONO_CUSTOM_ATTR_BITS;
9609 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9611 idx = mono_metadata_token_index (klass->type_token);
9612 idx <<= MONO_CUSTOM_ATTR_BITS;
9613 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9615 return mono_custom_attrs_from_index (klass->image, idx);
9619 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9623 if (image_is_dynamic (assembly->image))
9624 return lookup_custom_attr (assembly->image, assembly);
9625 idx = 1; /* there is only one assembly */
9626 idx <<= MONO_CUSTOM_ATTR_BITS;
9627 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9628 return mono_custom_attrs_from_index (assembly->image, idx);
9631 static MonoCustomAttrInfo*
9632 mono_custom_attrs_from_module (MonoImage *image)
9636 if (image_is_dynamic (image))
9637 return lookup_custom_attr (image, image);
9638 idx = 1; /* there is only one module */
9639 idx <<= MONO_CUSTOM_ATTR_BITS;
9640 idx |= MONO_CUSTOM_ATTR_MODULE;
9641 return mono_custom_attrs_from_index (image, idx);
9645 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9649 if (image_is_dynamic (klass->image)) {
9650 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9651 return lookup_custom_attr (klass->image, property);
9653 idx = find_property_index (klass, property);
9654 idx <<= MONO_CUSTOM_ATTR_BITS;
9655 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9656 return mono_custom_attrs_from_index (klass->image, idx);
9660 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9664 if (image_is_dynamic (klass->image)) {
9665 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9666 return lookup_custom_attr (klass->image, event);
9668 idx = find_event_index (klass, event);
9669 idx <<= MONO_CUSTOM_ATTR_BITS;
9670 idx |= MONO_CUSTOM_ATTR_EVENT;
9671 return mono_custom_attrs_from_index (klass->image, idx);
9675 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9678 if (image_is_dynamic (klass->image)) {
9679 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9680 return lookup_custom_attr (klass->image, field);
9682 idx = find_field_index (klass, field);
9683 idx <<= MONO_CUSTOM_ATTR_BITS;
9684 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9685 return mono_custom_attrs_from_index (klass->image, idx);
9689 * mono_custom_attrs_from_param:
9690 * @method: handle to the method that we want to retrieve custom parameter information from
9691 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9693 * The result must be released with mono_custom_attrs_free().
9695 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9698 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9701 guint32 i, idx, method_index;
9702 guint32 param_list, param_last, param_pos, found;
9704 MonoReflectionMethodAux *aux;
9707 * An instantiated method has the same cattrs as the generic method definition.
9709 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9710 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9712 if (method->is_inflated)
9713 method = ((MonoMethodInflated *) method)->declaring;
9715 if (image_is_dynamic (method->klass->image)) {
9716 MonoCustomAttrInfo *res, *ainfo;
9719 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9720 if (!aux || !aux->param_cattr)
9723 /* Need to copy since it will be freed later */
9724 ainfo = aux->param_cattr [param];
9727 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9728 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9729 memcpy (res, ainfo, size);
9733 image = method->klass->image;
9734 method_index = mono_method_get_index (method);
9737 ca = &image->tables [MONO_TABLE_METHOD];
9739 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9740 if (method_index == ca->rows) {
9741 ca = &image->tables [MONO_TABLE_PARAM];
9742 param_last = ca->rows + 1;
9744 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9745 ca = &image->tables [MONO_TABLE_PARAM];
9748 for (i = param_list; i < param_last; ++i) {
9749 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9750 if (param_pos == param) {
9758 idx <<= MONO_CUSTOM_ATTR_BITS;
9759 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9760 return mono_custom_attrs_from_index (image, idx);
9764 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9768 for (i = 0; i < ainfo->num_attrs; ++i) {
9769 klass = ainfo->attrs [i].ctor->klass;
9770 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9777 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9780 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9781 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9786 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9792 mono_error_init (error);
9795 for (i = 0; i < ainfo->num_attrs; ++i) {
9796 klass = ainfo->attrs [i].ctor->klass;
9797 if (mono_class_has_parent (klass, attr_klass)) {
9802 if (attr_index == -1)
9805 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9806 if (!mono_error_ok (error))
9808 return mono_array_get (attrs, MonoObject*, attr_index);
9812 * mono_reflection_get_custom_attrs_info:
9813 * @obj: a reflection object handle
9815 * Return the custom attribute info for attributes defined for the
9816 * reflection handle @obj. The objects.
9818 * FIXME this function leaks like a sieve for SRE objects.
9821 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9824 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9825 mono_error_assert_ok (&error);
9830 * mono_reflection_get_custom_attrs_info_checked:
9831 * @obj: a reflection object handle
9832 * @error: set on error
9834 * Return the custom attribute info for attributes defined for the
9835 * reflection handle @obj. The objects.
9837 * On failure returns NULL and sets @error.
9839 * FIXME this function leaks like a sieve for SRE objects.
9842 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9845 MonoCustomAttrInfo *cinfo = NULL;
9847 mono_error_init (error);
9849 klass = obj->vtable->klass;
9850 if (klass == mono_defaults.monotype_class) {
9851 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9852 klass = mono_class_from_mono_type (type);
9853 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9854 cinfo = mono_custom_attrs_from_class (klass);
9855 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9856 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9857 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9858 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9859 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9860 cinfo = mono_custom_attrs_from_module (module->image);
9861 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9862 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9863 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9864 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9865 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9866 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9867 } else if (strcmp ("MonoField", klass->name) == 0) {
9868 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9869 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9870 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9871 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9872 cinfo = mono_custom_attrs_from_method (rmethod->method);
9873 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9874 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9875 cinfo = mono_custom_attrs_from_method (rmethod->method);
9876 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9877 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9878 MonoClass *member_class = mono_object_class (param->MemberImpl);
9879 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9880 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9881 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9882 } else if (is_sr_mono_property (member_class)) {
9883 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9885 if (!(method = prop->property->get))
9886 method = prop->property->set;
9889 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9891 #ifndef DISABLE_REFLECTION_EMIT
9892 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9893 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
9894 return_val_if_nok (error, NULL);
9895 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9896 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9897 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9898 MonoMethod *method = NULL;
9899 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9900 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9901 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9902 method = ((MonoReflectionMethod *)c->cb)->method;
9904 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));
9906 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9910 char *type_name = mono_type_get_full_name (member_class);
9911 mono_error_set_generic_error (error, "System", "NotSupportedException",
9912 "Custom attributes on a ParamInfo with member %s are not supported",
9917 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9918 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9919 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9920 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9921 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9922 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9923 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9924 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9925 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9926 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9927 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9928 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9929 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9930 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9931 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9932 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9933 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9934 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9935 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9936 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9937 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
9938 return_val_if_nok (error, NULL);
9939 } else { /* handle other types here... */
9940 g_error ("get custom attrs not yet supported for %s", klass->name);
9947 * mono_reflection_get_custom_attrs_by_type:
9948 * @obj: a reflection object handle
9950 * Return an array with all the custom attributes defined of the
9951 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9952 * of that type are returned. The objects are fully build. Return NULL if a loading error
9956 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9959 MonoCustomAttrInfo *cinfo;
9961 mono_error_init (error);
9963 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
9964 return_val_if_nok (error, NULL);
9966 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9970 mono_custom_attrs_free (cinfo);
9972 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9973 if (mono_loader_get_last_error ()) {
9974 mono_error_set_from_loader_error (error);
9977 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9984 * mono_reflection_get_custom_attrs:
9985 * @obj: a reflection object handle
9987 * Return an array with all the custom attributes defined of the
9988 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9992 mono_reflection_get_custom_attrs (MonoObject *obj)
9996 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10000 * mono_reflection_get_custom_attrs_data:
10001 * @obj: a reflection obj handle
10003 * Returns an array of System.Reflection.CustomAttributeData,
10004 * which include information about attributes reflected on
10005 * types loaded using the Reflection Only methods
10008 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10012 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10013 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10018 * mono_reflection_get_custom_attrs_data_checked:
10019 * @obj: a reflection obj handle
10020 * @error: set on error
10022 * Returns an array of System.Reflection.CustomAttributeData,
10023 * which include information about attributes reflected on
10024 * types loaded using the Reflection Only methods
10027 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10030 MonoCustomAttrInfo *cinfo;
10032 mono_error_init (error);
10034 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10035 return_val_if_nok (error, NULL);
10037 result = mono_custom_attrs_data_construct (cinfo, error);
10038 return_val_if_nok (error, NULL);
10039 if (!cinfo->cached)
10040 mono_custom_attrs_free (cinfo);
10042 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10044 if (mono_loader_get_last_error ())
10045 mono_error_set_from_loader_error (error);
10050 static MonoReflectionType*
10051 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10053 static MonoMethod *method_get_underlying_system_type = NULL;
10054 MonoReflectionType *rt;
10055 MonoMethod *usertype_method;
10057 mono_error_init (error);
10059 if (!method_get_underlying_system_type)
10060 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10062 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10064 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10071 is_corlib_type (MonoClass *klass)
10073 return klass->image == mono_defaults.corlib;
10076 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10077 static MonoClass *cached_class; \
10078 if (cached_class) \
10079 return cached_class == _class; \
10080 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10081 cached_class = _class; \
10088 #ifndef DISABLE_REFLECTION_EMIT
10090 is_sre_array (MonoClass *klass)
10092 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10096 is_sre_byref (MonoClass *klass)
10098 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10102 is_sre_pointer (MonoClass *klass)
10104 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10108 is_sre_generic_instance (MonoClass *klass)
10110 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10114 is_sre_type_builder (MonoClass *klass)
10116 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10120 is_sre_method_builder (MonoClass *klass)
10122 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10126 is_sre_ctor_builder (MonoClass *klass)
10128 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10132 is_sre_field_builder (MonoClass *klass)
10134 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10138 is_sre_method_on_tb_inst (MonoClass *klass)
10140 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10144 is_sre_ctor_on_tb_inst (MonoClass *klass)
10146 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10150 mono_reflection_type_get_handle (MonoReflectionType* ref)
10159 if (is_usertype (ref)) {
10160 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10161 mono_error_raise_exception (&error); /* FIXME don't raise here */
10162 if (ref == NULL || is_usertype (ref))
10168 klass = mono_object_class (ref);
10170 if (is_sre_array (klass)) {
10172 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10173 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10175 if (sre_array->rank == 0) //single dimentional array
10176 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10178 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10179 sre_array->type.type = res;
10181 } else if (is_sre_byref (klass)) {
10183 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10184 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10186 res = &mono_class_from_mono_type (base)->this_arg;
10187 sre_byref->type.type = res;
10189 } else if (is_sre_pointer (klass)) {
10191 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10192 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10194 res = &mono_ptr_class_get (base)->byval_arg;
10195 sre_pointer->type.type = res;
10197 } else if (is_sre_generic_instance (klass)) {
10198 MonoType *res, **types;
10199 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10202 count = mono_array_length (gclass->type_arguments);
10203 types = g_new0 (MonoType*, count);
10204 for (i = 0; i < count; ++i) {
10205 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10206 types [i] = mono_reflection_type_get_handle (t);
10213 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10216 gclass->type.type = res;
10220 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10227 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10229 mono_reflection_type_get_handle (type);
10233 mono_reflection_register_with_runtime (MonoReflectionType *type)
10235 MonoType *res = mono_reflection_type_get_handle (type);
10236 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10240 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10242 klass = mono_class_from_mono_type (res);
10244 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10245 mono_domain_lock (domain);
10247 if (!image_is_dynamic (klass->image)) {
10248 mono_class_setup_supertypes (klass);
10250 if (!domain->type_hash)
10251 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10252 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10253 mono_g_hash_table_insert (domain->type_hash, res, type);
10255 mono_domain_unlock (domain);
10256 mono_loader_unlock ();
10260 * LOCKING: Assumes the loader lock is held.
10262 static MonoMethodSignature*
10263 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10264 MonoMethodSignature *sig;
10267 count = parameters? mono_array_length (parameters): 0;
10269 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10270 sig->param_count = count;
10271 sig->sentinelpos = -1; /* FIXME */
10272 for (i = 0; i < count; ++i)
10273 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10278 * LOCKING: Assumes the loader lock is held.
10280 static MonoMethodSignature*
10281 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10282 MonoMethodSignature *sig;
10284 sig = parameters_to_signature (image, ctor->parameters);
10285 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10286 sig->ret = &mono_defaults.void_class->byval_arg;
10291 * LOCKING: Assumes the loader lock is held.
10293 static MonoMethodSignature*
10294 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10295 MonoMethodSignature *sig;
10297 sig = parameters_to_signature (image, method->parameters);
10298 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10299 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10300 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10304 static MonoMethodSignature*
10305 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10306 MonoMethodSignature *sig;
10308 sig = parameters_to_signature (NULL, method->parameters);
10309 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10310 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10311 sig->generic_param_count = 0;
10316 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10318 MonoClass *klass = mono_object_class (prop);
10319 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10320 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10321 *name = mono_string_to_utf8 (pb->name);
10322 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10324 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10325 *name = g_strdup (p->property->name);
10326 if (p->property->get)
10327 *type = mono_method_signature (p->property->get)->ret;
10329 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10334 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10336 MonoClass *klass = mono_object_class (field);
10337 if (strcmp (klass->name, "FieldBuilder") == 0) {
10338 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10339 *name = mono_string_to_utf8 (fb->name);
10340 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10342 MonoReflectionField *f = (MonoReflectionField *)field;
10343 *name = g_strdup (mono_field_get_name (f->field));
10344 *type = f->field->type;
10348 #else /* DISABLE_REFLECTION_EMIT */
10351 mono_reflection_register_with_runtime (MonoReflectionType *type)
10353 /* This is empty */
10357 is_sre_type_builder (MonoClass *klass)
10363 is_sre_generic_instance (MonoClass *klass)
10369 init_type_builder_generics (MonoObject *type)
10373 #endif /* !DISABLE_REFLECTION_EMIT */
10377 is_sr_mono_field (MonoClass *klass)
10379 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10383 is_sr_mono_property (MonoClass *klass)
10385 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10389 is_sr_mono_method (MonoClass *klass)
10391 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10395 is_sr_mono_cmethod (MonoClass *klass)
10397 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10401 is_sr_mono_generic_method (MonoClass *klass)
10403 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10407 is_sr_mono_generic_cmethod (MonoClass *klass)
10409 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10413 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10415 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10419 is_usertype (MonoReflectionType *ref)
10421 MonoClass *klass = mono_object_class (ref);
10422 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10425 static MonoReflectionType*
10426 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10428 mono_error_init (error);
10429 if (!type || type->type)
10432 if (is_usertype (type)) {
10433 type = mono_reflection_type_get_underlying_system_type (type, error);
10434 return_val_if_nok (error, NULL);
10435 if (is_usertype (type)) {
10436 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10444 * Encode a value in a custom attribute stream of bytes.
10445 * The value to encode is either supplied as an object in argument val
10446 * (valuetypes are boxed), or as a pointer to the data in the
10448 * @type represents the type of the value
10449 * @buffer is the start of the buffer
10450 * @p the current position in the buffer
10451 * @buflen contains the size of the buffer and is used to return the new buffer size
10452 * if this needs to be realloced.
10453 * @retbuffer and @retp return the start and the position of the buffer
10456 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10458 MonoTypeEnum simple_type;
10460 if ((p-buffer) + 10 >= *buflen) {
10463 newbuf = (char *)g_realloc (buffer, *buflen);
10464 p = newbuf + (p-buffer);
10468 argval = ((char*)arg + sizeof (MonoObject));
10469 simple_type = type->type;
10471 switch (simple_type) {
10472 case MONO_TYPE_BOOLEAN:
10477 case MONO_TYPE_CHAR:
10480 swap_with_size (p, argval, 2, 1);
10486 swap_with_size (p, argval, 4, 1);
10490 swap_with_size (p, argval, 8, 1);
10495 swap_with_size (p, argval, 8, 1);
10498 case MONO_TYPE_VALUETYPE:
10499 if (type->data.klass->enumtype) {
10500 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10503 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10506 case MONO_TYPE_STRING: {
10513 str = mono_string_to_utf8 ((MonoString*)arg);
10514 slen = strlen (str);
10515 if ((p-buffer) + 10 + slen >= *buflen) {
10519 newbuf = (char *)g_realloc (buffer, *buflen);
10520 p = newbuf + (p-buffer);
10523 mono_metadata_encode_value (slen, p, &p);
10524 memcpy (p, str, slen);
10529 case MONO_TYPE_CLASS: {
10537 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10538 slen = strlen (str);
10539 if ((p-buffer) + 10 + slen >= *buflen) {
10543 newbuf = (char *)g_realloc (buffer, *buflen);
10544 p = newbuf + (p-buffer);
10547 mono_metadata_encode_value (slen, p, &p);
10548 memcpy (p, str, slen);
10553 case MONO_TYPE_SZARRAY: {
10555 MonoClass *eclass, *arg_eclass;
10558 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10561 len = mono_array_length ((MonoArray*)arg);
10563 *p++ = (len >> 8) & 0xff;
10564 *p++ = (len >> 16) & 0xff;
10565 *p++ = (len >> 24) & 0xff;
10567 *retbuffer = buffer;
10568 eclass = type->data.klass;
10569 arg_eclass = mono_object_class (arg)->element_class;
10572 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10573 eclass = mono_defaults.object_class;
10575 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10576 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10577 int elsize = mono_class_array_element_size (arg_eclass);
10578 for (i = 0; i < len; ++i) {
10579 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10582 } else if (eclass->valuetype && arg_eclass->valuetype) {
10583 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10584 int elsize = mono_class_array_element_size (eclass);
10585 for (i = 0; i < len; ++i) {
10586 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10590 for (i = 0; i < len; ++i) {
10591 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10596 case MONO_TYPE_OBJECT: {
10602 * The parameter type is 'object' but the type of the actual
10603 * argument is not. So we have to add type information to the blob
10604 * too. This is completely undocumented in the spec.
10608 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10613 klass = mono_object_class (arg);
10615 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10618 } else if (klass->enumtype) {
10620 } else if (klass == mono_defaults.string_class) {
10621 simple_type = MONO_TYPE_STRING;
10624 } else if (klass->rank == 1) {
10626 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10627 /* See Partition II, Appendix B3 */
10630 *p++ = klass->element_class->byval_arg.type;
10631 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10633 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10634 *p++ = simple_type = klass->byval_arg.type;
10637 g_error ("unhandled type in custom attr");
10639 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10640 slen = strlen (str);
10641 if ((p-buffer) + 10 + slen >= *buflen) {
10645 newbuf = (char *)g_realloc (buffer, *buflen);
10646 p = newbuf + (p-buffer);
10649 mono_metadata_encode_value (slen, p, &p);
10650 memcpy (p, str, slen);
10653 simple_type = mono_class_enum_basetype (klass)->type;
10657 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10660 *retbuffer = buffer;
10664 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10666 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10667 char *str = type_get_qualified_name (type, NULL);
10668 int slen = strlen (str);
10672 * This seems to be optional...
10675 mono_metadata_encode_value (slen, p, &p);
10676 memcpy (p, str, slen);
10679 } else if (type->type == MONO_TYPE_OBJECT) {
10681 } else if (type->type == MONO_TYPE_CLASS) {
10682 /* it should be a type: encode_cattr_value () has the check */
10685 mono_metadata_encode_value (type->type, p, &p);
10686 if (type->type == MONO_TYPE_SZARRAY)
10687 /* See the examples in Partition VI, Annex B */
10688 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10694 #ifndef DISABLE_REFLECTION_EMIT
10696 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10699 /* Preallocate a large enough buffer */
10700 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10701 char *str = type_get_qualified_name (type, NULL);
10702 len = strlen (str);
10704 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10705 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10706 len = strlen (str);
10711 len += strlen (name);
10713 if ((p-buffer) + 20 + len >= *buflen) {
10717 newbuf = (char *)g_realloc (buffer, *buflen);
10718 p = newbuf + (p-buffer);
10722 encode_field_or_prop_type (type, p, &p);
10724 len = strlen (name);
10725 mono_metadata_encode_value (len, p, &p);
10726 memcpy (p, name, len);
10728 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10730 *retbuffer = buffer;
10734 * mono_reflection_get_custom_attrs_blob:
10735 * @ctor: custom attribute constructor
10736 * @ctorArgs: arguments o the constructor
10742 * Creates the blob of data that needs to be saved in the metadata and that represents
10743 * the custom attributed described by @ctor, @ctorArgs etc.
10744 * Returns: a Byte array representing the blob of data.
10747 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10750 MonoMethodSignature *sig;
10755 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10756 /* sig is freed later so allocate it in the heap */
10757 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10759 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10762 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10764 p = buffer = (char *)g_malloc (buflen);
10765 /* write the prolog */
10768 for (i = 0; i < sig->param_count; ++i) {
10769 arg = mono_array_get (ctorArgs, MonoObject*, i);
10770 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10774 i += mono_array_length (properties);
10776 i += mono_array_length (fields);
10778 *p++ = (i >> 8) & 0xff;
10781 for (i = 0; i < mono_array_length (properties); ++i) {
10785 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10786 get_prop_name_and_type (prop, &pname, &ptype);
10787 *p++ = 0x54; /* PROPERTY signature */
10788 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10795 for (i = 0; i < mono_array_length (fields); ++i) {
10799 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10800 get_field_name_and_type (field, &fname, &ftype);
10801 *p++ = 0x53; /* FIELD signature */
10802 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10807 g_assert (p - buffer <= buflen);
10808 buflen = p - buffer;
10809 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10810 p = mono_array_addr (result, char, 0);
10811 memcpy (p, buffer, buflen);
10813 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10819 * mono_reflection_setup_internal_class:
10820 * @tb: a TypeBuilder object
10822 * Creates a MonoClass that represents the TypeBuilder.
10823 * This is a trick that lets us simplify a lot of reflection code
10824 * (and will allow us to support Build and Run assemblies easier).
10827 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10830 MonoClass *klass, *parent;
10832 RESOLVE_TYPE (tb->parent, &error);
10833 mono_error_raise_exception (&error); /* FIXME don't raise here */
10835 mono_loader_lock ();
10838 /* check so we can compile corlib correctly */
10839 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10840 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10841 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10843 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10849 /* the type has already being created: it means we just have to change the parent */
10850 if (tb->type.type) {
10851 klass = mono_class_from_mono_type (tb->type.type);
10852 klass->parent = NULL;
10853 /* fool mono_class_setup_parent */
10854 klass->supertypes = NULL;
10855 mono_class_setup_parent (klass, parent);
10856 mono_class_setup_mono_type (klass);
10857 mono_loader_unlock ();
10861 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10863 klass->image = &tb->module->dynamic_image->image;
10865 klass->inited = 1; /* we lie to the runtime */
10866 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10867 if (!mono_error_ok (&error))
10869 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10870 if (!mono_error_ok (&error))
10872 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10873 klass->flags = tb->attrs;
10875 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10877 klass->element_class = klass;
10879 if (mono_class_get_ref_info (klass) == NULL) {
10881 mono_class_set_ref_info (klass, tb);
10883 /* Put into cache so mono_class_get_checked () will find it.
10884 Skip nested types as those should not be available on the global scope. */
10885 if (!tb->nesting_type)
10886 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10889 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10890 by performing a mono_class_get which does the full resolution.
10892 Working around this semantics would require us to write a lot of code for no clear advantage.
10894 mono_image_append_class_to_reflection_info_set (klass);
10896 g_assert (mono_class_get_ref_info (klass) == tb);
10899 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10901 if (parent != NULL) {
10902 mono_class_setup_parent (klass, parent);
10903 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10904 const char *old_n = klass->name;
10905 /* trick to get relative numbering right when compiling corlib */
10906 klass->name = "BuildingObject";
10907 mono_class_setup_parent (klass, mono_defaults.object_class);
10908 klass->name = old_n;
10911 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10912 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10913 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10914 klass->instance_size = sizeof (MonoObject);
10915 klass->size_inited = 1;
10916 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10919 mono_class_setup_mono_type (klass);
10921 mono_class_setup_supertypes (klass);
10924 * FIXME: handle interfaces.
10927 tb->type.type = &klass->byval_arg;
10929 if (tb->nesting_type) {
10930 g_assert (tb->nesting_type->type);
10931 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10934 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10936 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10938 mono_loader_unlock ();
10942 mono_loader_unlock ();
10943 mono_error_raise_exception (&error);
10947 * mono_reflection_setup_generic_class:
10948 * @tb: a TypeBuilder object
10950 * Setup the generic class before adding the first generic parameter.
10953 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10958 * mono_reflection_create_generic_class:
10959 * @tb: a TypeBuilder object
10961 * Creates the generic class after all generic parameters have been added.
10964 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10969 klass = mono_class_from_mono_type (tb->type.type);
10971 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10973 if (klass->generic_container || (count == 0))
10976 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10978 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10980 klass->generic_container->owner.klass = klass;
10981 klass->generic_container->type_argc = count;
10982 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10984 klass->is_generic = 1;
10986 for (i = 0; i < count; i++) {
10987 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10988 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10989 klass->generic_container->type_params [i] = *param;
10990 /*Make sure we are a diferent type instance */
10991 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10992 klass->generic_container->type_params [i].info.pklass = NULL;
10993 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10995 g_assert (klass->generic_container->type_params [i].param.owner);
10998 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11002 * mono_reflection_create_internal_class:
11003 * @tb: a TypeBuilder object
11005 * Actually create the MonoClass that is associated with the TypeBuilder.
11008 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11012 klass = mono_class_from_mono_type (tb->type.type);
11014 mono_loader_lock ();
11015 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11016 MonoReflectionFieldBuilder *fb;
11018 MonoType *enum_basetype;
11020 g_assert (tb->fields != NULL);
11021 g_assert (mono_array_length (tb->fields) >= 1);
11023 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11025 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11026 mono_loader_unlock ();
11030 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11031 klass->element_class = mono_class_from_mono_type (enum_basetype);
11032 if (!klass->element_class)
11033 klass->element_class = mono_class_from_mono_type (enum_basetype);
11036 * get the element_class from the current corlib.
11038 ec = default_class_from_mono_type (enum_basetype);
11039 klass->instance_size = ec->instance_size;
11040 klass->size_inited = 1;
11042 * this is almost safe to do with enums and it's needed to be able
11043 * to create objects of the enum type (for use in SetConstant).
11045 /* FIXME: Does this mean enums can't have method overrides ? */
11046 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11048 mono_loader_unlock ();
11051 static MonoMarshalSpec*
11052 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11053 MonoReflectionMarshal *minfo)
11055 MonoMarshalSpec *res;
11057 res = image_g_new0 (image, MonoMarshalSpec, 1);
11058 res->native = (MonoMarshalNative)minfo->type;
11060 switch (minfo->type) {
11061 case MONO_NATIVE_LPARRAY:
11062 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11063 if (minfo->has_size) {
11064 res->data.array_data.param_num = minfo->param_num;
11065 res->data.array_data.num_elem = minfo->count;
11066 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11069 res->data.array_data.param_num = -1;
11070 res->data.array_data.num_elem = -1;
11071 res->data.array_data.elem_mult = -1;
11075 case MONO_NATIVE_BYVALTSTR:
11076 case MONO_NATIVE_BYVALARRAY:
11077 res->data.array_data.num_elem = minfo->count;
11080 case MONO_NATIVE_CUSTOM:
11081 if (minfo->marshaltyperef)
11082 res->data.custom_data.custom_name =
11083 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11084 if (minfo->mcookie)
11085 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11094 #endif /* !DISABLE_REFLECTION_EMIT */
11096 MonoReflectionMarshalAsAttribute*
11097 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11098 MonoMarshalSpec *spec, MonoError *error)
11100 MonoReflectionType *rt;
11101 MonoReflectionMarshalAsAttribute *minfo;
11104 mono_error_init (error);
11106 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11109 minfo->utype = spec->native;
11111 switch (minfo->utype) {
11112 case MONO_NATIVE_LPARRAY:
11113 minfo->array_subtype = spec->data.array_data.elem_type;
11114 minfo->size_const = spec->data.array_data.num_elem;
11115 if (spec->data.array_data.param_num != -1)
11116 minfo->size_param_index = spec->data.array_data.param_num;
11119 case MONO_NATIVE_BYVALTSTR:
11120 case MONO_NATIVE_BYVALARRAY:
11121 minfo->size_const = spec->data.array_data.num_elem;
11124 case MONO_NATIVE_CUSTOM:
11125 if (spec->data.custom_data.custom_name) {
11126 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11128 rt = mono_type_get_object_checked (domain, mtype, error);
11132 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11135 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11137 if (spec->data.custom_data.cookie)
11138 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11148 #ifndef DISABLE_REFLECTION_EMIT
11150 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11151 ReflectionMethodBuilder *rmb,
11152 MonoMethodSignature *sig)
11156 MonoMethodWrapper *wrapperm;
11157 MonoMarshalSpec **specs;
11158 MonoReflectionMethodAux *method_aux;
11163 mono_error_init (&error);
11165 * Methods created using a MethodBuilder should have their memory allocated
11166 * inside the image mempool, while dynamic methods should have their memory
11169 dynamic = rmb->refs != NULL;
11170 image = dynamic ? NULL : klass->image;
11173 g_assert (!klass->generic_class);
11175 mono_loader_lock ();
11177 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11178 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11179 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11181 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11183 wrapperm = (MonoMethodWrapper*)m;
11185 m->dynamic = dynamic;
11187 m->flags = rmb->attrs;
11188 m->iflags = rmb->iattrs;
11189 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11191 m->signature = sig;
11192 m->sre_method = TRUE;
11193 m->skip_visibility = rmb->skip_visibility;
11194 if (rmb->table_idx)
11195 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11197 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11198 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11199 m->string_ctor = 1;
11201 m->signature->pinvoke = 1;
11202 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11203 m->signature->pinvoke = 1;
11205 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11207 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11208 g_assert (mono_error_ok (&error));
11209 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11210 g_assert (mono_error_ok (&error));
11212 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11214 if (image_is_dynamic (klass->image))
11215 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11217 mono_loader_unlock ();
11220 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11221 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11222 MonoMethodHeader *header;
11224 gint32 max_stack, i;
11225 gint32 num_locals = 0;
11226 gint32 num_clauses = 0;
11230 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11231 code_size = rmb->ilgen->code_len;
11232 max_stack = rmb->ilgen->max_stack;
11233 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11234 if (rmb->ilgen->ex_handlers)
11235 num_clauses = method_count_clauses (rmb->ilgen);
11238 code = mono_array_addr (rmb->code, guint8, 0);
11239 code_size = mono_array_length (rmb->code);
11240 /* we probably need to run a verifier on the code... */
11250 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11251 header->code_size = code_size;
11252 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11253 memcpy ((char*)header->code, code, code_size);
11254 header->max_stack = max_stack;
11255 header->init_locals = rmb->init_locals;
11256 header->num_locals = num_locals;
11258 for (i = 0; i < num_locals; ++i) {
11259 MonoReflectionLocalBuilder *lb =
11260 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11262 header->locals [i] = image_g_new0 (image, MonoType, 1);
11263 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11266 header->num_clauses = num_clauses;
11268 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11269 rmb->ilgen, num_clauses);
11272 wrapperm->header = header;
11275 if (rmb->generic_params) {
11276 int count = mono_array_length (rmb->generic_params);
11277 MonoGenericContainer *container = rmb->generic_container;
11279 g_assert (container);
11281 container->type_argc = count;
11282 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11283 container->owner.method = m;
11284 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11286 m->is_generic = TRUE;
11287 mono_method_set_generic_container (m, container);
11289 for (i = 0; i < count; i++) {
11290 MonoReflectionGenericParam *gp =
11291 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11292 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11293 container->type_params [i] = *param;
11297 * The method signature might have pointers to generic parameters that belong to other methods.
11298 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11299 * generic parameters.
11301 for (i = 0; i < m->signature->param_count; ++i) {
11302 MonoType *t = m->signature->params [i];
11303 if (t->type == MONO_TYPE_MVAR) {
11304 MonoGenericParam *gparam = t->data.generic_param;
11305 if (gparam->num < count) {
11306 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11307 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11313 if (klass->generic_container) {
11314 container->parent = klass->generic_container;
11315 container->context.class_inst = klass->generic_container->context.class_inst;
11317 container->context.method_inst = mono_get_shared_generic_inst (container);
11321 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11325 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11327 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11328 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11329 for (i = 0; i < rmb->nrefs; ++i)
11330 data [i + 1] = rmb->refs [i];
11335 /* Parameter info */
11338 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11339 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11340 for (i = 0; i <= m->signature->param_count; ++i) {
11341 MonoReflectionParamBuilder *pb;
11342 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11343 if ((i > 0) && (pb->attrs)) {
11344 /* Make a copy since it might point to a shared type structure */
11345 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11346 m->signature->params [i - 1]->attrs = pb->attrs;
11349 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11350 MonoDynamicImage *assembly;
11352 MonoTypeEnum def_type;
11356 if (!method_aux->param_defaults) {
11357 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11358 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11360 assembly = (MonoDynamicImage*)klass->image;
11361 idx = encode_constant (assembly, pb->def_value, &def_type);
11362 /* Copy the data from the blob since it might get realloc-ed */
11363 p = assembly->blob.data + idx;
11364 len = mono_metadata_decode_blob_size (p, &p2);
11366 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11367 method_aux->param_default_types [i] = def_type;
11368 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11372 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11373 g_assert (mono_error_ok (&error));
11376 if (!method_aux->param_cattr)
11377 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11378 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11384 /* Parameter marshalling */
11387 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11388 MonoReflectionParamBuilder *pb;
11389 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11390 if (pb->marshal_info) {
11392 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11393 specs [pb->position] =
11394 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11398 if (specs != NULL) {
11400 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11401 method_aux->param_marshall = specs;
11404 if (image_is_dynamic (klass->image) && method_aux)
11405 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11407 mono_loader_unlock ();
11413 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11415 ReflectionMethodBuilder rmb;
11416 MonoMethodSignature *sig;
11418 mono_loader_lock ();
11419 sig = ctor_builder_to_signature (klass->image, mb);
11420 mono_loader_unlock ();
11422 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11425 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11426 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11428 /* If we are in a generic class, we might be called multiple times from inflate_method */
11429 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11430 /* ilgen is no longer needed */
11434 return mb->mhandle;
11438 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11440 ReflectionMethodBuilder rmb;
11441 MonoMethodSignature *sig;
11443 mono_error_init (error);
11445 mono_loader_lock ();
11446 sig = method_builder_to_signature (klass->image, mb);
11447 mono_loader_unlock ();
11449 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11452 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11453 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11455 /* If we are in a generic class, we might be called multiple times from inflate_method */
11456 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11457 /* ilgen is no longer needed */
11460 return mb->mhandle;
11463 static MonoClassField*
11464 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11466 MonoClassField *field;
11470 field = g_new0 (MonoClassField, 1);
11472 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11473 g_assert (mono_error_ok (&error));
11474 if (fb->attrs || fb->modreq || fb->modopt) {
11475 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11476 field->type->attrs = fb->attrs;
11478 g_assert (image_is_dynamic (klass->image));
11479 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11480 g_free (field->type);
11481 field->type = mono_metadata_type_dup (klass->image, custom);
11484 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11486 if (fb->offset != -1)
11487 field->offset = fb->offset;
11488 field->parent = klass;
11489 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11491 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11498 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11501 MonoReflectionTypeBuilder *tb = NULL;
11502 gboolean is_dynamic = FALSE;
11503 MonoClass *geninst;
11505 mono_loader_lock ();
11507 if (is_sre_type_builder (mono_object_class (type))) {
11508 tb = (MonoReflectionTypeBuilder *) type;
11511 } else if (is_sre_generic_instance (mono_object_class (type))) {
11512 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11513 MonoReflectionType *gtd = rgi->generic_type;
11515 if (is_sre_type_builder (mono_object_class (gtd))) {
11516 tb = (MonoReflectionTypeBuilder *)gtd;
11521 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11522 if (tb && tb->generic_container)
11523 mono_reflection_create_generic_class (tb);
11525 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11526 if (!klass->generic_container) {
11527 mono_loader_unlock ();
11531 if (klass->wastypebuilder) {
11532 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11537 mono_loader_unlock ();
11539 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11541 return &geninst->byval_arg;
11545 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11547 MonoGenericClass *gclass;
11548 MonoGenericInst *inst;
11550 g_assert (klass->generic_container);
11552 inst = mono_metadata_get_generic_inst (type_argc, types);
11553 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11555 return mono_generic_class_get_class (gclass);
11558 MonoReflectionMethod*
11559 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11563 MonoMethod *method, *inflated;
11564 MonoMethodInflated *imethod;
11565 MonoGenericContext tmp_context;
11566 MonoGenericInst *ginst;
11567 MonoType **type_argv;
11570 /*FIXME but this no longer should happen*/
11571 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11572 #ifndef DISABLE_REFLECTION_EMIT
11573 MonoReflectionMethodBuilder *mb = NULL;
11574 MonoReflectionTypeBuilder *tb;
11577 mb = (MonoReflectionMethodBuilder *) rmethod;
11578 tb = (MonoReflectionTypeBuilder *) mb->type;
11579 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11581 method = methodbuilder_to_mono_method (klass, mb, &error);
11583 mono_error_raise_exception (&error); /* FIXME don't raise here */
11585 g_assert_not_reached ();
11589 method = rmethod->method;
11592 klass = method->klass;
11594 if (method->is_inflated)
11595 method = ((MonoMethodInflated *) method)->declaring;
11597 count = mono_method_signature (method)->generic_param_count;
11598 if (count != mono_array_length (types))
11601 type_argv = g_new0 (MonoType *, count);
11602 for (i = 0; i < count; i++) {
11603 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11604 type_argv [i] = mono_reflection_type_get_handle (garg);
11606 ginst = mono_metadata_get_generic_inst (count, type_argv);
11607 g_free (type_argv);
11609 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11610 tmp_context.method_inst = ginst;
11612 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11613 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11614 imethod = (MonoMethodInflated *) inflated;
11616 /*FIXME but I think this is no longer necessary*/
11617 if (image_is_dynamic (method->klass->image)) {
11618 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11620 * This table maps metadata structures representing inflated methods/fields
11621 * to the reflection objects representing their generic definitions.
11623 mono_image_lock ((MonoImage*)image);
11624 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11625 mono_image_unlock ((MonoImage*)image);
11628 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11629 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11631 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11632 mono_error_raise_exception (&error); /* FIXME don't raise here */
11636 #ifndef DISABLE_REFLECTION_EMIT
11638 static MonoMethod *
11639 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11641 MonoMethodInflated *imethod;
11642 MonoGenericContext *context;
11646 * With generic code sharing the klass might not be inflated.
11647 * This can happen because classes inflated with their own
11648 * type arguments are "normalized" to the uninflated class.
11650 if (!klass->generic_class)
11653 context = mono_class_get_context (klass);
11655 if (klass->method.count && klass->methods) {
11656 /* Find the already created inflated method */
11657 for (i = 0; i < klass->method.count; ++i) {
11658 g_assert (klass->methods [i]->is_inflated);
11659 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11662 g_assert (i < klass->method.count);
11663 imethod = (MonoMethodInflated*)klass->methods [i];
11666 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11667 mono_error_assert_ok (&error);
11670 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11671 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11673 mono_image_lock ((MonoImage*)image);
11674 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11675 mono_image_unlock ((MonoImage*)image);
11677 return (MonoMethod *) imethod;
11680 static MonoMethod *
11681 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11683 MonoMethod *method;
11686 mono_error_init (error);
11688 MonoClass *type_class = mono_object_class (type);
11690 if (is_sre_generic_instance (type_class)) {
11691 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11692 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11693 } else if (is_sre_type_builder (type_class)) {
11694 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11695 } else if (type->type) {
11696 gklass = mono_class_from_mono_type (type->type);
11697 gklass = mono_class_get_generic_type_definition (gklass);
11699 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11702 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11703 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11704 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11706 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11710 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11711 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11714 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11715 method = ((MonoReflectionMethod *) obj)->method;
11717 method = NULL; /* prevent compiler warning */
11718 g_error ("can't handle type %s", obj->vtable->klass->name);
11721 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11724 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11726 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11728 MonoGenericClass *gclass;
11729 MonoDynamicGenericClass *dgclass;
11730 MonoClass *klass, *gklass;
11734 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11735 klass = mono_class_from_mono_type (gtype);
11736 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11737 gclass = gtype->data.generic_class;
11739 if (!gclass->is_dynamic)
11742 dgclass = (MonoDynamicGenericClass *) gclass;
11744 if (dgclass->initialized)
11747 gklass = gclass->container_class;
11748 mono_class_init (gklass);
11750 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11752 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11753 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11754 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11756 for (i = 0; i < dgclass->count_fields; i++) {
11757 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11758 MonoClassField *field, *inflated_field = NULL;
11760 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11761 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11762 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11763 field = ((MonoReflectionField *) obj)->field;
11765 field = NULL; /* prevent compiler warning */
11766 g_assert_not_reached ();
11769 dgclass->fields [i] = *field;
11770 dgclass->fields [i].parent = klass;
11771 dgclass->fields [i].type = mono_class_inflate_generic_type (
11772 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11773 dgclass->field_generic_types [i] = field->type;
11774 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11775 dgclass->field_objects [i] = obj;
11777 if (inflated_field) {
11778 g_free (inflated_field);
11780 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11784 dgclass->initialized = TRUE;
11788 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11790 MonoDynamicGenericClass *dgclass;
11793 g_assert (gclass->is_dynamic);
11795 dgclass = (MonoDynamicGenericClass *)gclass;
11797 for (i = 0; i < dgclass->count_fields; ++i) {
11798 MonoClassField *field = dgclass->fields + i;
11799 mono_metadata_free_type (field->type);
11800 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11805 fix_partial_generic_class (MonoClass *klass)
11807 MonoClass *gklass = klass->generic_class->container_class;
11808 MonoDynamicGenericClass *dgclass;
11811 if (klass->wastypebuilder)
11814 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11815 if (klass->parent != gklass->parent) {
11817 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11818 if (mono_error_ok (&error)) {
11819 MonoClass *parent = mono_class_from_mono_type (parent_type);
11820 mono_metadata_free_type (parent_type);
11821 if (parent != klass->parent) {
11822 /*fool mono_class_setup_parent*/
11823 klass->supertypes = NULL;
11824 mono_class_setup_parent (klass, parent);
11827 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11828 mono_error_cleanup (&error);
11829 if (gklass->wastypebuilder)
11830 klass->wastypebuilder = TRUE;
11835 if (!dgclass->initialized)
11838 if (klass->method.count != gklass->method.count) {
11839 klass->method.count = gklass->method.count;
11840 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11842 for (i = 0; i < klass->method.count; i++) {
11844 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11845 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11846 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11850 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11851 klass->interface_count = gklass->interface_count;
11852 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11853 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11855 for (i = 0; i < gklass->interface_count; ++i) {
11857 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11858 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11859 mono_metadata_free_type (iface_type);
11861 ensure_runtime_vtable (klass->interfaces [i], &error);
11862 mono_error_raise_exception (&error); /* FIXME don't raise here */
11864 klass->interfaces_inited = 1;
11867 if (klass->field.count != gklass->field.count) {
11868 klass->field.count = gklass->field.count;
11869 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11871 for (i = 0; i < klass->field.count; i++) {
11872 klass->fields [i] = gklass->fields [i];
11873 klass->fields [i].parent = klass;
11874 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11878 /*We can only finish with this klass once it's parent has as well*/
11879 if (gklass->wastypebuilder)
11880 klass->wastypebuilder = TRUE;
11885 * ensure_generic_class_runtime_vtable:
11886 * @klass a generic class
11887 * @error set on error
11889 * Ensures that the generic container of @klass has a vtable and
11890 * returns TRUE on success. On error returns FALSE and sets @error.
11893 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
11895 MonoClass *gklass = klass->generic_class->container_class;
11897 mono_error_init (error);
11899 if (!ensure_runtime_vtable (gklass, error))
11902 fix_partial_generic_class (klass);
11908 * ensure_runtime_vtable:
11910 * @error set on error
11912 * Ensures that @klass has a vtable and returns TRUE on success. On
11913 * error returns FALSE and sets @error.
11916 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
11918 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11921 mono_error_init (error);
11923 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11926 if (!ensure_runtime_vtable (klass->parent, error))
11930 num = tb->ctors? mono_array_length (tb->ctors): 0;
11931 num += tb->num_methods;
11932 klass->method.count = num;
11933 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11934 num = tb->ctors? mono_array_length (tb->ctors): 0;
11935 for (i = 0; i < num; ++i) {
11936 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
11939 klass->methods [i] = ctor;
11941 num = tb->num_methods;
11943 for (i = 0; i < num; ++i) {
11944 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
11947 klass->methods [j++] = meth;
11950 if (tb->interfaces) {
11951 klass->interface_count = mono_array_length (tb->interfaces);
11952 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11953 for (i = 0; i < klass->interface_count; ++i) {
11954 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11955 klass->interfaces [i] = mono_class_from_mono_type (iface);
11956 if (!ensure_runtime_vtable (klass->interfaces [i], error))
11959 klass->interfaces_inited = 1;
11961 } else if (klass->generic_class){
11962 if (!ensure_generic_class_runtime_vtable (klass, error))
11966 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11968 for (i = 0; i < klass->method.count; ++i) {
11969 MonoMethod *im = klass->methods [i];
11970 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11971 im->slot = slot_num++;
11974 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11975 mono_class_setup_interface_offsets (klass);
11976 mono_class_setup_interface_id (klass);
11980 * The generic vtable is needed even if image->run is not set since some
11981 * runtime code like ves_icall_Type_GetMethodsByName depends on
11982 * method->slot being defined.
11986 * tb->methods could not be freed since it is used for determining
11987 * overrides during dynamic vtable construction.
11994 mono_reflection_method_get_handle (MonoObject *method)
11997 MonoClass *klass = mono_object_class (method);
11998 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11999 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12000 return sr_method->method;
12002 if (is_sre_method_builder (klass)) {
12003 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12004 return mb->mhandle;
12006 if (is_sre_method_on_tb_inst (klass)) {
12007 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12008 MonoMethod *result;
12009 /*FIXME move this to a proper method and unify with resolve_object*/
12010 if (m->method_args) {
12011 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12012 mono_error_raise_exception (&error); /* FIXME don't raise here */
12014 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12015 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12016 MonoMethod *mono_method;
12018 if (is_sre_method_builder (mono_object_class (m->mb)))
12019 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12020 else if (is_sr_mono_method (mono_object_class (m->mb)))
12021 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12023 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)));
12025 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12030 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12035 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12037 MonoReflectionTypeBuilder *tb;
12039 MonoReflectionMethod *m;
12042 *num_overrides = 0;
12044 g_assert (image_is_dynamic (klass->image));
12046 if (!mono_class_get_ref_info (klass))
12049 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12051 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12055 for (i = 0; i < tb->num_methods; ++i) {
12056 MonoReflectionMethodBuilder *mb =
12057 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12058 if (mb->override_methods)
12059 onum += mono_array_length (mb->override_methods);
12064 *overrides = g_new0 (MonoMethod*, onum * 2);
12067 for (i = 0; i < tb->num_methods; ++i) {
12068 MonoReflectionMethodBuilder *mb =
12069 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12070 if (mb->override_methods) {
12071 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12072 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12074 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12075 (*overrides) [onum * 2 + 1] = mb->mhandle;
12077 g_assert (mb->mhandle);
12085 *num_overrides = onum;
12089 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12091 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12092 MonoReflectionFieldBuilder *fb;
12093 MonoClassField *field;
12094 MonoImage *image = klass->image;
12095 const char *p, *p2;
12097 guint32 len, idx, real_size = 0;
12099 klass->field.count = tb->num_fields;
12100 klass->field.first = 0;
12102 mono_error_init (error);
12104 if (tb->class_size) {
12105 if ((tb->packing_size & 0xffffff00) != 0) {
12106 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12107 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12110 klass->packing_size = tb->packing_size;
12111 real_size = klass->instance_size + tb->class_size;
12114 if (!klass->field.count) {
12115 klass->instance_size = MAX (klass->instance_size, real_size);
12119 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12120 mono_class_alloc_ext (klass);
12121 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12123 This is, guess what, a hack.
12124 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12125 On the static path no field class is resolved, only types are built. This is the right thing to do
12127 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12129 klass->size_inited = 1;
12131 for (i = 0; i < klass->field.count; ++i) {
12132 MonoArray *rva_data;
12133 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12134 field = &klass->fields [i];
12135 field->name = mono_string_to_utf8_image (image, fb->name, error);
12136 if (!mono_error_ok (error))
12139 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12140 field->type->attrs = fb->attrs;
12142 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12145 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12146 char *base = mono_array_addr (rva_data, char, 0);
12147 size_t size = mono_array_length (rva_data);
12148 char *data = (char *)mono_image_alloc (klass->image, size);
12149 memcpy (data, base, size);
12150 klass->ext->field_def_values [i].data = data;
12152 if (fb->offset != -1)
12153 field->offset = fb->offset;
12154 field->parent = klass;
12155 fb->handle = field;
12156 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12158 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12159 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12161 if (fb->def_value) {
12162 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12163 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12164 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12165 /* Copy the data from the blob since it might get realloc-ed */
12166 p = assembly->blob.data + idx;
12167 len = mono_metadata_decode_blob_size (p, &p2);
12169 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12170 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12174 klass->instance_size = MAX (klass->instance_size, real_size);
12175 mono_class_layout_fields (klass);
12179 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12182 MonoReflectionPropertyBuilder *pb;
12183 MonoImage *image = klass->image;
12184 MonoProperty *properties;
12187 mono_error_init (error);
12190 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12192 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12193 klass->ext->property.first = 0;
12195 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12196 klass->ext->properties = properties;
12197 for (i = 0; i < klass->ext->property.count; ++i) {
12198 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12199 properties [i].parent = klass;
12200 properties [i].attrs = pb->attrs;
12201 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12202 if (!mono_error_ok (error))
12204 if (pb->get_method)
12205 properties [i].get = pb->get_method->mhandle;
12206 if (pb->set_method)
12207 properties [i].set = pb->set_method->mhandle;
12209 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12210 if (pb->def_value) {
12212 const char *p, *p2;
12213 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12214 if (!klass->ext->prop_def_values)
12215 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12216 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12217 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12218 /* Copy the data from the blob since it might get realloc-ed */
12219 p = assembly->blob.data + idx;
12220 len = mono_metadata_decode_blob_size (p, &p2);
12222 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12223 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12228 MonoReflectionEvent *
12229 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12232 MonoEvent *event = g_new0 (MonoEvent, 1);
12235 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12237 event->parent = klass;
12238 event->attrs = eb->attrs;
12239 event->name = mono_string_to_utf8 (eb->name);
12240 if (eb->add_method)
12241 event->add = eb->add_method->mhandle;
12242 if (eb->remove_method)
12243 event->remove = eb->remove_method->mhandle;
12244 if (eb->raise_method)
12245 event->raise = eb->raise_method->mhandle;
12247 #ifndef MONO_SMALL_CONFIG
12248 if (eb->other_methods) {
12250 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12251 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12252 MonoReflectionMethodBuilder *mb =
12253 mono_array_get (eb->other_methods,
12254 MonoReflectionMethodBuilder*, j);
12255 event->other [j] = mb->mhandle;
12260 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12261 mono_error_raise_exception (&error); /* FIXME don't raise here */
12266 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12268 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12269 MonoReflectionEventBuilder *eb;
12270 MonoImage *image = klass->image;
12274 mono_error_init (error);
12277 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12279 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12280 klass->ext->event.first = 0;
12282 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12283 klass->ext->events = events;
12284 for (i = 0; i < klass->ext->event.count; ++i) {
12285 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12286 events [i].parent = klass;
12287 events [i].attrs = eb->attrs;
12288 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12289 if (!mono_error_ok (error))
12291 if (eb->add_method)
12292 events [i].add = eb->add_method->mhandle;
12293 if (eb->remove_method)
12294 events [i].remove = eb->remove_method->mhandle;
12295 if (eb->raise_method)
12296 events [i].raise = eb->raise_method->mhandle;
12298 #ifndef MONO_SMALL_CONFIG
12299 if (eb->other_methods) {
12301 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12302 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12303 MonoReflectionMethodBuilder *mb =
12304 mono_array_get (eb->other_methods,
12305 MonoReflectionMethodBuilder*, j);
12306 events [i].other [j] = mb->mhandle;
12310 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12315 remove_instantiations_of_and_ensure_contents (gpointer key,
12317 gpointer user_data)
12319 MonoType *type = (MonoType*)key;
12320 MonoClass *klass = (MonoClass*)user_data;
12322 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12323 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12330 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12332 mono_error_init (error);
12338 for (i = 0; i < mono_array_length (arr); ++i) {
12339 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12340 if (!mono_error_ok (error))
12345 MonoReflectionType*
12346 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12350 MonoDomain* domain;
12351 MonoReflectionType* res;
12354 domain = mono_object_domain (tb);
12355 klass = mono_class_from_mono_type (tb->type.type);
12358 * Check for user defined Type subclasses.
12360 RESOLVE_TYPE (tb->parent, &error);
12361 mono_error_raise_exception (&error); /* FIXME don't raise here */
12362 check_array_for_usertypes (tb->interfaces, &error);
12363 mono_error_raise_exception (&error); /*FIXME don't raise here */
12365 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12366 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12368 RESOLVE_TYPE (fb->type, &error);
12369 mono_error_raise_exception (&error); /* FIXME don't raise here */
12370 check_array_for_usertypes (fb->modreq, &error);
12371 mono_error_raise_exception (&error); /*FIXME don't raise here */
12372 check_array_for_usertypes (fb->modopt, &error);
12373 mono_error_raise_exception (&error); /*FIXME don't raise here */
12374 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12375 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12376 mono_error_raise_exception (&error); /* FIXME don't raise here */
12382 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12383 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12385 RESOLVE_TYPE (mb->rtype, &error);
12386 mono_error_raise_exception (&error); /* FIXME don't raise here */
12387 check_array_for_usertypes (mb->return_modreq, &error);
12388 mono_error_raise_exception (&error); /*FIXME don't raise here */
12389 check_array_for_usertypes (mb->return_modopt, &error);
12390 mono_error_raise_exception (&error); /*FIXME don't raise here */
12391 check_array_for_usertypes (mb->parameters, &error);
12392 mono_error_raise_exception (&error); /*FIXME don't raise here */
12393 if (mb->param_modreq)
12394 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12395 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12396 mono_error_raise_exception (&error); /*FIXME don't raise here */
12398 if (mb->param_modopt)
12399 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12400 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12401 mono_error_raise_exception (&error); /*FIXME don't raise here */
12407 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12408 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12410 check_array_for_usertypes (mb->parameters, &error);
12411 mono_error_raise_exception (&error); /*FIXME don't raise here */
12412 if (mb->param_modreq)
12413 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12414 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12415 mono_error_raise_exception (&error); /*FIXME don't raise here */
12417 if (mb->param_modopt)
12418 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12419 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12420 mono_error_raise_exception (&error); /*FIXME don't raise here */
12426 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12429 * we need to lock the domain because the lock will be taken inside
12430 * So, we need to keep the locking order correct.
12432 mono_loader_lock ();
12433 mono_domain_lock (domain);
12434 if (klass->wastypebuilder) {
12435 mono_domain_unlock (domain);
12436 mono_loader_unlock ();
12438 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12439 mono_error_raise_exception (&error); /* FIXME don't raise here */
12444 * Fields to set in klass:
12445 * the various flags: delegate/unicode/contextbound etc.
12447 klass->flags = tb->attrs;
12448 klass->has_cctor = 1;
12449 klass->has_finalize = 1;
12450 klass->has_finalize_inited = 1;
12452 mono_class_setup_parent (klass, klass->parent);
12453 /* fool mono_class_setup_supertypes */
12454 klass->supertypes = NULL;
12455 mono_class_setup_supertypes (klass);
12456 mono_class_setup_mono_type (klass);
12459 if (!((MonoDynamicImage*)klass->image)->run) {
12460 if (klass->generic_container) {
12461 /* FIXME: The code below can't handle generic classes */
12462 klass->wastypebuilder = TRUE;
12463 mono_loader_unlock ();
12464 mono_domain_unlock (domain);
12466 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12467 mono_error_raise_exception (&error); /* FIXME don't raise here */
12474 /* enums are done right away */
12475 if (!klass->enumtype)
12476 if (!ensure_runtime_vtable (klass, &error))
12479 if (tb->subtypes) {
12480 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12481 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12482 mono_class_alloc_ext (klass);
12483 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)));
12487 klass->nested_classes_inited = TRUE;
12489 /* fields and object layout */
12490 if (klass->parent) {
12491 if (!klass->parent->size_inited)
12492 mono_class_init (klass->parent);
12493 klass->instance_size = klass->parent->instance_size;
12494 klass->sizes.class_size = 0;
12495 klass->min_align = klass->parent->min_align;
12496 /* if the type has no fields we won't call the field_setup
12497 * routine which sets up klass->has_references.
12499 klass->has_references |= klass->parent->has_references;
12501 klass->instance_size = sizeof (MonoObject);
12502 klass->min_align = 1;
12505 /* FIXME: handle packing_size and instance_size */
12506 typebuilder_setup_fields (klass, &error);
12507 if (!mono_error_ok (&error))
12509 typebuilder_setup_properties (klass, &error);
12510 if (!mono_error_ok (&error))
12513 typebuilder_setup_events (klass, &error);
12514 if (!mono_error_ok (&error))
12517 klass->wastypebuilder = TRUE;
12520 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12521 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12522 * we want to return normal System.MonoType objects, so clear these out from the cache.
12524 * Together with this we must ensure the contents of all instances to match the created type.
12526 if (domain->type_hash && klass->generic_container)
12527 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12529 mono_domain_unlock (domain);
12530 mono_loader_unlock ();
12532 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12533 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12534 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12537 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12538 mono_error_raise_exception (&error); /* FIXME don't raise here */
12540 g_assert (res != (MonoReflectionType*)tb);
12545 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12546 klass->wastypebuilder = TRUE;
12547 mono_domain_unlock (domain);
12548 mono_loader_unlock ();
12549 mono_error_raise_exception (&error);
12554 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12556 MonoGenericParamFull *param;
12561 image = &gparam->tbuilder->module->dynamic_image->image;
12563 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12565 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12566 g_assert (mono_error_ok (&error));
12567 param->param.num = gparam->index;
12569 if (gparam->mbuilder) {
12570 if (!gparam->mbuilder->generic_container) {
12571 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12572 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12573 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12574 gparam->mbuilder->generic_container->is_method = TRUE;
12576 * Cannot set owner.method, since the MonoMethod is not created yet.
12577 * Set the image field instead, so type_in_image () works.
12579 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12580 gparam->mbuilder->generic_container->owner.image = klass->image;
12582 param->param.owner = gparam->mbuilder->generic_container;
12583 } else if (gparam->tbuilder) {
12584 if (!gparam->tbuilder->generic_container) {
12585 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12586 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12587 gparam->tbuilder->generic_container->owner.klass = klass;
12589 param->param.owner = gparam->tbuilder->generic_container;
12592 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12594 gparam->type.type = &pklass->byval_arg;
12596 mono_class_set_ref_info (pklass, gparam);
12597 mono_image_append_class_to_reflection_info_set (pklass);
12601 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12604 MonoReflectionModuleBuilder *module = sig->module;
12605 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12606 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12611 check_array_for_usertypes (sig->arguments, &error);
12612 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12614 sigbuffer_init (&buf, 32);
12616 sigbuffer_add_value (&buf, 0x07);
12617 sigbuffer_add_value (&buf, na);
12618 if (assembly != NULL){
12619 for (i = 0; i < na; ++i) {
12620 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12621 encode_reflection_type (assembly, type, &buf);
12625 buflen = buf.p - buf.buf;
12626 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12627 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12628 sigbuffer_free (&buf);
12634 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12637 MonoDynamicImage *assembly = sig->module->dynamic_image;
12638 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12643 check_array_for_usertypes (sig->arguments, &error);
12644 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12646 sigbuffer_init (&buf, 32);
12648 sigbuffer_add_value (&buf, 0x06);
12649 for (i = 0; i < na; ++i) {
12650 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12651 encode_reflection_type (assembly, type, &buf);
12654 buflen = buf.p - buf.buf;
12655 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12656 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12657 sigbuffer_free (&buf);
12663 MonoMethod *handle;
12664 MonoDomain *domain;
12665 } DynamicMethodReleaseData;
12668 * The runtime automatically clean up those after finalization.
12670 static MonoReferenceQueue *dynamic_method_queue;
12673 free_dynamic_method (void *dynamic_method)
12675 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12676 MonoDomain *domain = data->domain;
12677 MonoMethod *method = data->handle;
12680 mono_domain_lock (domain);
12681 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12682 g_hash_table_remove (domain->method_to_dyn_method, method);
12683 mono_domain_unlock (domain);
12684 g_assert (dis_link);
12685 mono_gchandle_free (dis_link);
12687 mono_runtime_free_method (domain, method);
12692 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12694 MonoReferenceQueue *queue;
12695 MonoMethod *handle;
12696 DynamicMethodReleaseData *release_data;
12697 ReflectionMethodBuilder rmb;
12698 MonoMethodSignature *sig;
12700 MonoDomain *domain;
12704 if (mono_runtime_is_shutting_down ())
12705 mono_raise_exception (mono_get_exception_invalid_operation (""));
12707 if (!(queue = dynamic_method_queue)) {
12708 mono_loader_lock ();
12709 if (!(queue = dynamic_method_queue))
12710 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12711 mono_loader_unlock ();
12714 sig = dynamic_method_to_signature (mb);
12716 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12719 * Resolve references.
12722 * Every second entry in the refs array is reserved for storing handle_class,
12723 * which is needed by the ldtoken implementation in the JIT.
12725 rmb.nrefs = mb->nrefs;
12726 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12727 for (i = 0; i < mb->nrefs; i += 2) {
12728 MonoClass *handle_class;
12730 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12732 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12733 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12735 * The referenced DynamicMethod should already be created by the managed
12736 * code, except in the case of circular references. In that case, we store
12737 * method in the refs array, and fix it up later when the referenced
12738 * DynamicMethod is created.
12740 if (method->mhandle) {
12741 ref = method->mhandle;
12743 /* FIXME: GC object stored in unmanaged memory */
12746 /* FIXME: GC object stored in unmanaged memory */
12747 method->referenced_by = g_slist_append (method->referenced_by, mb);
12749 handle_class = mono_defaults.methodhandle_class;
12751 MonoException *ex = NULL;
12752 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12754 ex = mono_get_exception_type_load (NULL, NULL);
12755 else if (mono_security_core_clr_enabled ())
12756 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12760 mono_raise_exception (ex);
12765 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12766 rmb.refs [i + 1] = handle_class;
12769 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12771 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12772 release_data = g_new (DynamicMethodReleaseData, 1);
12773 release_data->handle = handle;
12774 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12775 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12776 g_free (release_data);
12778 /* Fix up refs entries pointing at us */
12779 for (l = mb->referenced_by; l; l = l->next) {
12780 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12781 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12784 g_assert (method->mhandle);
12786 data = (gpointer*)wrapper->method_data;
12787 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12788 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12789 data [i + 1] = mb->mhandle;
12792 g_slist_free (mb->referenced_by);
12796 /* ilgen is no longer needed */
12799 domain = mono_domain_get ();
12800 mono_domain_lock (domain);
12801 if (!domain->method_to_dyn_method)
12802 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12803 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12804 mono_domain_unlock (domain);
12807 #endif /* DISABLE_REFLECTION_EMIT */
12811 * mono_reflection_is_valid_dynamic_token:
12813 * Returns TRUE if token is valid.
12817 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12819 return lookup_dyn_token (image, token) != NULL;
12822 MonoMethodSignature *
12823 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12825 MonoMethodSignature *sig;
12826 g_assert (image_is_dynamic (image));
12828 mono_error_init (error);
12830 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12834 return mono_method_signature_checked (method, error);
12837 #ifndef DISABLE_REFLECTION_EMIT
12840 * mono_reflection_lookup_dynamic_token:
12842 * Finish the Builder object pointed to by TOKEN and return the corresponding
12843 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12844 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12847 * LOCKING: Take the loader lock
12850 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12852 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12856 obj = lookup_dyn_token (assembly, token);
12859 g_error ("Could not find required dynamic token 0x%08x", token);
12865 handle_class = &klass;
12866 return resolve_object (image, obj, handle_class, context);
12870 * ensure_complete_type:
12872 * Ensure that KLASS is completed if it is a dynamic type, or references
12876 ensure_complete_type (MonoClass *klass)
12880 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12881 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12883 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12884 mono_error_raise_exception (&error); /* FIXME don't raise here */
12886 // Asserting here could break a lot of code
12887 //g_assert (klass->wastypebuilder);
12890 if (klass->generic_class) {
12891 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12894 for (i = 0; i < inst->type_argc; ++i) {
12895 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12901 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12904 gpointer result = NULL;
12906 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12907 result = mono_string_intern_checked ((MonoString*)obj, &error);
12908 mono_error_raise_exception (&error); /* FIXME don't raise here */
12909 *handle_class = mono_defaults.string_class;
12911 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12912 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12913 MonoClass *mc = mono_class_from_mono_type (type);
12914 if (!mono_class_init (mc))
12915 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12918 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12919 result = mono_class_from_mono_type (inflated);
12920 mono_metadata_free_type (inflated);
12922 result = mono_class_from_mono_type (type);
12924 *handle_class = mono_defaults.typehandle_class;
12926 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12927 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12928 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12929 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12930 result = ((MonoReflectionMethod*)obj)->method;
12933 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12934 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12936 *handle_class = mono_defaults.methodhandle_class;
12938 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12939 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12940 result = mb->mhandle;
12942 /* Type is not yet created */
12943 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12945 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12946 mono_error_raise_exception (&error); /* FIXME don't raise here */
12949 * Hopefully this has been filled in by calling CreateType() on the
12953 * TODO: This won't work if the application finishes another
12954 * TypeBuilder instance instead of this one.
12956 result = mb->mhandle;
12960 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12961 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12963 *handle_class = mono_defaults.methodhandle_class;
12964 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12965 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12967 result = cb->mhandle;
12969 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12971 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12972 mono_error_raise_exception (&error); /* FIXME don't raise here */
12973 result = cb->mhandle;
12977 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12978 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12980 *handle_class = mono_defaults.methodhandle_class;
12981 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12982 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12984 ensure_complete_type (field->parent);
12986 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12987 MonoClass *klass = mono_class_from_mono_type (inflated);
12988 MonoClassField *inflated_field;
12989 gpointer iter = NULL;
12990 mono_metadata_free_type (inflated);
12991 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12992 if (!strcmp (field->name, inflated_field->name))
12995 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12996 result = inflated_field;
13000 *handle_class = mono_defaults.fieldhandle_class;
13002 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13003 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13004 result = fb->handle;
13007 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13009 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13010 mono_error_raise_exception (&error); /* FIXME don't raise here */
13011 result = fb->handle;
13014 if (fb->handle && fb->handle->parent->generic_container) {
13015 MonoClass *klass = fb->handle->parent;
13016 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
13017 MonoClass *inflated = mono_class_from_mono_type (type);
13019 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13021 mono_metadata_free_type (type);
13023 *handle_class = mono_defaults.fieldhandle_class;
13024 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13025 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13026 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
13029 klass = type->data.klass;
13030 if (klass->wastypebuilder) {
13031 /* Already created */
13035 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13036 mono_error_raise_exception (&error); /* FIXME don't raise here */
13037 result = type->data.klass;
13040 *handle_class = mono_defaults.typehandle_class;
13041 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13042 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13043 MonoMethodSignature *sig;
13046 if (helper->arguments)
13047 nargs = mono_array_length (helper->arguments);
13051 sig = mono_metadata_signature_alloc (image, nargs);
13052 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13053 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13055 if (helper->unmanaged_call_conv) { /* unmanaged */
13056 sig->call_convention = helper->unmanaged_call_conv - 1;
13057 sig->pinvoke = TRUE;
13058 } else if (helper->call_conv & 0x02) {
13059 sig->call_convention = MONO_CALL_VARARG;
13061 sig->call_convention = MONO_CALL_DEFAULT;
13064 sig->param_count = nargs;
13065 /* TODO: Copy type ? */
13066 sig->ret = helper->return_type->type;
13067 for (i = 0; i < nargs; ++i)
13068 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13071 *handle_class = NULL;
13072 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13073 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13074 /* Already created by the managed code */
13075 g_assert (method->mhandle);
13076 result = method->mhandle;
13077 *handle_class = mono_defaults.methodhandle_class;
13078 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13079 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13080 type = mono_class_inflate_generic_type (type, context);
13081 result = mono_class_from_mono_type (type);
13082 *handle_class = mono_defaults.typehandle_class;
13084 mono_metadata_free_type (type);
13085 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13086 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13087 type = mono_class_inflate_generic_type (type, context);
13088 result = mono_class_from_mono_type (type);
13089 *handle_class = mono_defaults.typehandle_class;
13091 mono_metadata_free_type (type);
13092 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13093 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13094 MonoClass *inflated;
13096 MonoClassField *field;
13098 if (is_sre_field_builder (mono_object_class (f->fb)))
13099 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13100 else if (is_sr_mono_field (mono_object_class (f->fb)))
13101 field = ((MonoReflectionField*)f->fb)->field;
13103 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)));
13105 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13106 inflated = mono_class_from_mono_type (type);
13108 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13109 ensure_complete_type (field->parent);
13111 mono_metadata_free_type (type);
13112 *handle_class = mono_defaults.fieldhandle_class;
13113 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13114 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13115 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13116 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13117 MonoMethod *method;
13119 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13120 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13121 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13122 method = ((MonoReflectionMethod *)c->cb)->method;
13124 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)));
13126 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13127 *handle_class = mono_defaults.methodhandle_class;
13128 mono_metadata_free_type (type);
13129 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13130 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13131 if (m->method_args) {
13132 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13133 mono_error_raise_exception (&error); /* FIXME don't raise here */
13135 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13136 mono_error_assert_ok (&error);
13139 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13140 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13141 MonoMethod *method;
13143 if (is_sre_method_builder (mono_object_class (m->mb)))
13144 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13145 else if (is_sr_mono_method (mono_object_class (m->mb)))
13146 method = ((MonoReflectionMethod *)m->mb)->method;
13148 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)));
13150 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13151 mono_metadata_free_type (type);
13153 *handle_class = mono_defaults.methodhandle_class;
13154 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13155 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13158 MonoMethod *method;
13162 mtype = mono_reflection_type_get_handle (m->parent);
13163 klass = mono_class_from_mono_type (mtype);
13165 /* Find the method */
13167 name = mono_string_to_utf8 (m->name);
13169 while ((method = mono_class_get_methods (klass, &iter))) {
13170 if (!strcmp (method->name, name))
13177 // FIXME: Check parameters/return value etc. match
13180 *handle_class = mono_defaults.methodhandle_class;
13181 } else if (is_sre_array (mono_object_get_class(obj)) ||
13182 is_sre_byref (mono_object_get_class(obj)) ||
13183 is_sre_pointer (mono_object_get_class(obj))) {
13184 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13185 MonoType *type = mono_reflection_type_get_handle (ref_type);
13188 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13189 result = mono_class_from_mono_type (inflated);
13190 mono_metadata_free_type (inflated);
13192 result = mono_class_from_mono_type (type);
13194 *handle_class = mono_defaults.typehandle_class;
13196 g_print ("%s\n", obj->vtable->klass->name);
13197 g_assert_not_reached ();
13202 #else /* DISABLE_REFLECTION_EMIT */
13205 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13207 g_assert_not_reached ();
13212 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13214 g_assert_not_reached ();
13218 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13220 g_assert_not_reached ();
13224 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13226 g_assert_not_reached ();
13230 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13232 g_assert_not_reached ();
13236 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13238 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13242 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13244 g_assert_not_reached ();
13248 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13250 g_assert_not_reached ();
13253 MonoReflectionModule *
13254 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13256 g_assert_not_reached ();
13261 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13263 g_assert_not_reached ();
13268 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13270 g_assert_not_reached ();
13275 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13276 gboolean create_open_instance, gboolean register_token, MonoError *error)
13278 g_assert_not_reached ();
13283 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13288 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13290 g_assert_not_reached ();
13294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13297 *num_overrides = 0;
13300 MonoReflectionEvent *
13301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13303 g_assert_not_reached ();
13307 MonoReflectionType*
13308 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13310 g_assert_not_reached ();
13315 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13317 g_assert_not_reached ();
13321 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13323 g_assert_not_reached ();
13328 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13330 g_assert_not_reached ();
13335 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13340 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13346 mono_reflection_type_get_handle (MonoReflectionType* ref)
13354 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13356 g_assert_not_reached ();
13359 #endif /* DISABLE_REFLECTION_EMIT */
13361 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13362 const static guint32 declsec_flags_map[] = {
13363 0x00000000, /* empty */
13364 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13365 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13366 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13367 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13368 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13369 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13370 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13371 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13372 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13373 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13374 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13375 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13376 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13377 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13378 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13379 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13380 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13381 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13385 * Returns flags that includes all available security action associated to the handle.
13386 * @token: metadata token (either for a class or a method)
13387 * @image: image where resides the metadata.
13390 mono_declsec_get_flags (MonoImage *image, guint32 token)
13392 int index = mono_metadata_declsec_from_index (image, token);
13393 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13394 guint32 result = 0;
13398 /* HasSecurity can be present for other, not specially encoded, attributes,
13399 e.g. SuppressUnmanagedCodeSecurityAttribute */
13403 for (i = index; i < t->rows; i++) {
13404 guint32 cols [MONO_DECL_SECURITY_SIZE];
13406 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13407 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13410 action = cols [MONO_DECL_SECURITY_ACTION];
13411 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13412 result |= declsec_flags_map [action];
13414 g_assert_not_reached ();
13421 * Get the security actions (in the form of flags) associated with the specified method.
13423 * @method: The method for which we want the declarative security flags.
13424 * Return the declarative security flags for the method (only).
13426 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13427 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13430 mono_declsec_flags_from_method (MonoMethod *method)
13432 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13433 /* FIXME: No cache (for the moment) */
13434 guint32 idx = mono_method_get_index (method);
13435 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13436 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13437 return mono_declsec_get_flags (method->klass->image, idx);
13443 * Get the security actions (in the form of flags) associated with the specified class.
13445 * @klass: The class for which we want the declarative security flags.
13446 * Return the declarative security flags for the class.
13448 * Note: We cache the flags inside the MonoClass structure as this will get
13449 * called very often (at least for each method).
13452 mono_declsec_flags_from_class (MonoClass *klass)
13454 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13455 if (!klass->ext || !klass->ext->declsec_flags) {
13458 idx = mono_metadata_token_index (klass->type_token);
13459 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13460 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13461 mono_loader_lock ();
13462 mono_class_alloc_ext (klass);
13463 mono_loader_unlock ();
13464 /* we cache the flags on classes */
13465 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13467 return klass->ext->declsec_flags;
13473 * Get the security actions (in the form of flags) associated with the specified assembly.
13475 * @assembly: The assembly for which we want the declarative security flags.
13476 * Return the declarative security flags for the assembly.
13479 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13481 guint32 idx = 1; /* there is only one assembly */
13482 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13483 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13484 return mono_declsec_get_flags (assembly->image, idx);
13489 * Fill actions for the specific index (which may either be an encoded class token or
13490 * an encoded method token) from the metadata image.
13491 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13494 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13495 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13497 MonoBoolean result = FALSE;
13499 guint32 cols [MONO_DECL_SECURITY_SIZE];
13500 int index = mono_metadata_declsec_from_index (image, token);
13503 t = &image->tables [MONO_TABLE_DECLSECURITY];
13504 for (i = index; i < t->rows; i++) {
13505 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13507 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13510 /* if present only replace (class) permissions with method permissions */
13511 /* if empty accept either class or method permissions */
13512 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13513 if (!actions->demand.blob) {
13514 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13515 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13516 actions->demand.blob = (char*) (blob + 2);
13517 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13520 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13521 if (!actions->noncasdemand.blob) {
13522 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13523 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13524 actions->noncasdemand.blob = (char*) (blob + 2);
13525 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13528 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13529 if (!actions->demandchoice.blob) {
13530 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13531 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13532 actions->demandchoice.blob = (char*) (blob + 2);
13533 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13543 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13544 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13546 guint32 idx = mono_metadata_token_index (klass->type_token);
13547 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13548 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13549 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13553 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13554 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13556 guint32 idx = mono_method_get_index (method);
13557 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13558 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13559 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13563 * Collect all actions (that requires to generate code in mini) assigned for
13564 * the specified method.
13565 * Note: Don't use the content of actions if the function return FALSE.
13568 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13570 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13571 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13572 MonoBoolean result = FALSE;
13575 /* quick exit if no declarative security is present in the metadata */
13576 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13579 /* we want the original as the wrapper is "free" of the security informations */
13580 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13581 method = mono_marshal_method_from_wrapper (method);
13586 /* First we look for method-level attributes */
13587 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13588 mono_class_init (method->klass);
13589 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13591 result = mono_declsec_get_method_demands_params (method, demands,
13592 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13595 /* Here we use (or create) the class declarative cache to look for demands */
13596 flags = mono_declsec_flags_from_class (method->klass);
13597 if (flags & mask) {
13599 mono_class_init (method->klass);
13600 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13602 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13603 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13606 /* The boolean return value is used as a shortcut in case nothing needs to
13607 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13613 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13615 * Note: Don't use the content of actions if the function return FALSE.
13618 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13620 MonoBoolean result = FALSE;
13623 /* quick exit if no declarative security is present in the metadata */
13624 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13627 /* we want the original as the wrapper is "free" of the security informations */
13628 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13629 method = mono_marshal_method_from_wrapper (method);
13634 /* results are independant - zeroize both */
13635 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13636 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13638 /* First we look for method-level attributes */
13639 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13640 mono_class_init (method->klass);
13642 result = mono_declsec_get_method_demands_params (method, cmethod,
13643 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13646 /* Here we use (or create) the class declarative cache to look for demands */
13647 flags = mono_declsec_flags_from_class (method->klass);
13648 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13649 mono_class_init (method->klass);
13651 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13652 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13659 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13661 * @klass The inherited class - this is the class that provides the security check (attributes)
13663 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13665 * Note: Don't use the content of actions if the function return FALSE.
13668 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13670 MonoBoolean result = FALSE;
13673 /* quick exit if no declarative security is present in the metadata */
13674 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13677 /* Here we use (or create) the class declarative cache to look for demands */
13678 flags = mono_declsec_flags_from_class (klass);
13679 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13680 mono_class_init (klass);
13681 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13683 result |= mono_declsec_get_class_demands_params (klass, demands,
13684 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13691 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13693 * Note: Don't use the content of actions if the function return FALSE.
13696 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13698 /* quick exit if no declarative security is present in the metadata */
13699 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13702 /* we want the original as the wrapper is "free" of the security informations */
13703 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13704 method = mono_marshal_method_from_wrapper (method);
13709 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13710 mono_class_init (method->klass);
13711 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13713 return mono_declsec_get_method_demands_params (method, demands,
13714 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13721 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13723 guint32 cols [MONO_DECL_SECURITY_SIZE];
13727 int index = mono_metadata_declsec_from_index (image, token);
13731 t = &image->tables [MONO_TABLE_DECLSECURITY];
13732 for (i = index; i < t->rows; i++) {
13733 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13735 /* shortcut - index are ordered */
13736 if (token != cols [MONO_DECL_SECURITY_PARENT])
13739 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13740 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13741 entry->blob = (char*) (metadata + 2);
13742 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13751 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13753 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13754 guint32 idx = mono_method_get_index (method);
13755 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13756 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13757 return get_declsec_action (method->klass->image, idx, action, entry);
13763 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13766 guint32 flags = mono_declsec_flags_from_class (klass);
13767 if (declsec_flags_map [action] & flags) {
13768 guint32 idx = mono_metadata_token_index (klass->type_token);
13769 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13770 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13771 return get_declsec_action (klass->image, idx, action, entry);
13777 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13779 guint32 idx = 1; /* there is only one assembly */
13780 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13781 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13783 return get_declsec_action (assembly->image, idx, action, entry);
13787 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13790 MonoObject *res, *exc;
13792 static MonoMethod *method = NULL;
13794 if (method == NULL) {
13795 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13800 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13801 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13803 g_assert (mono_class_get_ref_info (klass));
13804 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13806 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13807 mono_error_raise_exception (&error); /* FIXME don't raise here */
13809 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13811 if (exc || !mono_error_ok (&error)) {
13812 mono_error_cleanup (&error);
13815 return *(MonoBoolean*)mono_object_unbox (res);
13819 * mono_reflection_type_get_type:
13820 * @reftype: the System.Type object
13822 * Returns the MonoType* associated with the C# System.Type object @reftype.
13825 mono_reflection_type_get_type (MonoReflectionType *reftype)
13827 g_assert (reftype);
13829 return mono_reflection_type_get_handle (reftype);
13833 * mono_reflection_assembly_get_assembly:
13834 * @refassembly: the System.Reflection.Assembly object
13836 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13839 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13841 g_assert (refassembly);
13843 return refassembly->assembly;