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, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
247 dynamic_images_lock (void)
249 mono_os_mutex_lock (&dynamic_images_mutex);
253 dynamic_images_unlock (void)
255 mono_os_mutex_unlock (&dynamic_images_mutex);
259 * mono_find_dynamic_image_owner:
261 * Find the dynamic image, if any, which a given pointer is located in the memory of.
264 mono_find_dynamic_image_owner (void *ptr)
266 MonoImage *owner = NULL;
269 dynamic_images_lock ();
273 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275 if (mono_mempool_contains_addr (image->mempool, ptr))
280 dynamic_images_unlock ();
286 mono_reflection_init (void)
288 mono_os_mutex_init (&dynamic_images_mutex);
292 dynamic_image_lock (MonoDynamicImage *image)
294 MONO_PREPARE_BLOCKING;
295 mono_image_lock ((MonoImage*)image);
296 MONO_FINISH_BLOCKING;
300 dynamic_image_unlock (MonoDynamicImage *image)
302 mono_image_unlock ((MonoImage*)image);
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
308 MONO_REQ_GC_UNSAFE_MODE;
310 dynamic_image_lock (assembly);
311 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312 dynamic_image_unlock (assembly);
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
318 MONO_REQ_GC_UNSAFE_MODE;
322 dynamic_image_lock (assembly);
323 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324 dynamic_image_unlock (assembly);
330 sigbuffer_init (SigBuffer *buf, int size)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 buf->buf = (char *)g_malloc (size);
336 buf->end = buf->buf + size;
340 sigbuffer_make_room (SigBuffer *buf, int size)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 if (buf->end - buf->p < size) {
345 int new_size = buf->end - buf->buf + size + 32;
346 char *p = (char *)g_realloc (buf->buf, new_size);
347 size = buf->p - buf->buf;
350 buf->end = buf->buf + new_size;
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
357 MONO_REQ_GC_NEUTRAL_MODE;
359 sigbuffer_make_room (buf, 6);
360 mono_metadata_encode_value (val, buf->p, &buf->p);
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
366 MONO_REQ_GC_NEUTRAL_MODE;
368 sigbuffer_make_room (buf, 1);
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
376 MONO_REQ_GC_NEUTRAL_MODE;
378 sigbuffer_make_room (buf, size);
379 memcpy (buf->p, p, size);
384 sigbuffer_free (SigBuffer *buf)
386 MONO_REQ_GC_NEUTRAL_MODE;
391 #ifndef DISABLE_REFLECTION_EMIT
395 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399 image_g_malloc (MonoImage *image, guint size)
401 MONO_REQ_GC_NEUTRAL_MODE;
404 return mono_image_alloc (image, size);
406 return g_malloc (size);
408 #endif /* !DISABLE_REFLECTION_EMIT */
413 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417 image_g_malloc0 (MonoImage *image, guint size)
419 MONO_REQ_GC_NEUTRAL_MODE;
422 return mono_image_alloc0 (image, size);
424 return g_malloc0 (size);
427 #ifndef DISABLE_REFLECTION_EMIT
429 image_strdup (MonoImage *image, const char *s)
431 MONO_REQ_GC_NEUTRAL_MODE;
434 return mono_image_strdup (image, s);
440 #define image_g_new(image,struct_type, n_structs) \
441 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
443 #define image_g_new0(image,struct_type, n_structs) \
444 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
448 alloc_table (MonoDynamicTable *table, guint nrows)
450 MONO_REQ_GC_NEUTRAL_MODE;
453 g_assert (table->columns);
454 if (nrows + 1 >= table->alloc_rows) {
455 while (nrows + 1 >= table->alloc_rows) {
456 if (table->alloc_rows == 0)
457 table->alloc_rows = 16;
459 table->alloc_rows *= 2;
462 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
467 make_room_in_stream (MonoDynamicStream *stream, int size)
469 MONO_REQ_GC_NEUTRAL_MODE;
471 if (size <= stream->alloc_size)
474 while (stream->alloc_size <= size) {
475 if (stream->alloc_size < 4096)
476 stream->alloc_size = 4096;
478 stream->alloc_size *= 2;
481 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
487 MONO_REQ_GC_NEUTRAL_MODE;
491 gpointer oldkey, oldval;
493 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494 return GPOINTER_TO_UINT (oldval);
496 len = strlen (str) + 1;
499 make_room_in_stream (sh, idx + len);
502 * We strdup the string even if we already copy them in sh->data
503 * so that the string pointers in the hash remain valid even if
504 * we need to realloc sh->data. We may want to avoid that later.
506 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507 memcpy (sh->data + idx, str, len);
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
515 MONO_REQ_GC_UNSAFE_MODE;
517 char *name = mono_string_to_utf8 (str);
519 idx = string_heap_insert (sh, name);
524 #ifndef DISABLE_REFLECTION_EMIT
526 string_heap_init (MonoDynamicStream *sh)
528 MONO_REQ_GC_NEUTRAL_MODE;
531 sh->alloc_size = 4096;
532 sh->data = (char *)g_malloc (4096);
533 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534 string_heap_insert (sh, "");
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
541 MONO_REQ_GC_NEUTRAL_MODE;
545 make_room_in_stream (stream, stream->index + len);
546 memcpy (stream->data + stream->index, data, len);
548 stream->index += len;
550 * align index? Not without adding an additional param that controls it since
551 * we may store a blob value in pieces.
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
559 MONO_REQ_GC_NEUTRAL_MODE;
563 make_room_in_stream (stream, stream->index + len);
564 memset (stream->data + stream->index, 0, len);
566 stream->index += len;
571 stream_data_align (MonoDynamicStream *stream)
573 MONO_REQ_GC_NEUTRAL_MODE;
576 guint32 count = stream->index % 4;
578 /* we assume the stream data will be aligned */
580 mono_image_add_stream_data (stream, buf, 4 - count);
583 #ifndef DISABLE_REFLECTION_EMIT
585 mono_blob_entry_hash (const char* str)
587 MONO_REQ_GC_NEUTRAL_MODE;
591 len = mono_metadata_decode_blob_size (str, &str);
595 for (str += 1; str < end; str++)
596 h = (h << 5) - h + *str;
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605 MONO_REQ_GC_NEUTRAL_MODE;
610 len = mono_metadata_decode_blob_size (str1, &end1);
611 len2 = mono_metadata_decode_blob_size (str2, &end2);
614 return memcmp (end1, end2, len) == 0;
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
620 MONO_REQ_GC_NEUTRAL_MODE;
624 gpointer oldkey, oldval;
626 copy = (char *)g_malloc (s1+s2);
627 memcpy (copy, b1, s1);
628 memcpy (copy + s1, b2, s2);
629 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
631 idx = GPOINTER_TO_UINT (oldval);
633 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634 mono_image_add_stream_data (&assembly->blob, b2, s2);
635 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
643 MONO_REQ_GC_NEUTRAL_MODE;
647 guint32 size = buf->p - buf->buf;
649 g_assert (size <= (buf->end - buf->buf));
650 mono_metadata_encode_value (size, b, &b);
651 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
655 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656 * dest may be misaligned.
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660 MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
664 for (elem = 0; elem < nelem; ++elem) {
690 g_assert_not_reached ();
696 memcpy (dest, val, len * nelem);
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
703 MONO_REQ_GC_UNSAFE_MODE;
707 guint32 idx = 0, len;
709 len = str->length * 2;
710 mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
713 char *swapped = g_malloc (2 * mono_string_length (str));
714 const char *p = (const char*)mono_string_chars (str);
716 swap_with_size (swapped, p, 2, mono_string_length (str));
717 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
726 #ifndef DISABLE_REFLECTION_EMIT
728 default_class_from_mono_type (MonoType *type)
730 MONO_REQ_GC_NEUTRAL_MODE;
732 switch (type->type) {
733 case MONO_TYPE_OBJECT:
734 return mono_defaults.object_class;
736 return mono_defaults.void_class;
737 case MONO_TYPE_BOOLEAN:
738 return mono_defaults.boolean_class;
740 return mono_defaults.char_class;
742 return mono_defaults.sbyte_class;
744 return mono_defaults.byte_class;
746 return mono_defaults.int16_class;
748 return mono_defaults.uint16_class;
750 return mono_defaults.int32_class;
752 return mono_defaults.uint32_class;
754 return mono_defaults.int_class;
756 return mono_defaults.uint_class;
758 return mono_defaults.int64_class;
760 return mono_defaults.uint64_class;
762 return mono_defaults.single_class;
764 return mono_defaults.double_class;
765 case MONO_TYPE_STRING:
766 return mono_defaults.string_class;
768 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769 g_assert_not_reached ();
777 * mono_class_get_ref_info:
779 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
782 mono_class_get_ref_info (MonoClass *klass)
784 MONO_REQ_GC_UNSAFE_MODE;
786 if (klass->ref_info_handle == 0)
789 return mono_gchandle_get_target (klass->ref_info_handle);
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
795 MONO_REQ_GC_UNSAFE_MODE;
797 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798 g_assert (klass->ref_info_handle != 0);
802 mono_class_free_ref_info (MonoClass *klass)
804 MONO_REQ_GC_NEUTRAL_MODE;
806 if (klass->ref_info_handle) {
807 mono_gchandle_free (klass->ref_info_handle);
808 klass->ref_info_handle = 0;
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
815 MONO_REQ_GC_NEUTRAL_MODE;
818 MonoGenericInst *class_inst;
823 class_inst = gclass->context.class_inst;
825 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826 klass = gclass->container_class;
827 sigbuffer_add_value (buf, klass->byval_arg.type);
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
830 sigbuffer_add_value (buf, class_inst->type_argc);
831 for (i = 0; i < class_inst->type_argc; ++i)
832 encode_type (assembly, class_inst->type_argv [i], buf);
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
839 MONO_REQ_GC_NEUTRAL_MODE;
842 g_assert_not_reached ();
847 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
851 case MONO_TYPE_BOOLEAN:
865 case MONO_TYPE_STRING:
866 case MONO_TYPE_OBJECT:
867 case MONO_TYPE_TYPEDBYREF:
868 sigbuffer_add_value (buf, type->type);
871 sigbuffer_add_value (buf, type->type);
872 encode_type (assembly, type->data.type, buf);
874 case MONO_TYPE_SZARRAY:
875 sigbuffer_add_value (buf, type->type);
876 encode_type (assembly, &type->data.klass->byval_arg, buf);
878 case MONO_TYPE_VALUETYPE:
879 case MONO_TYPE_CLASS: {
880 MonoClass *k = mono_class_from_mono_type (type);
882 if (k->generic_container) {
883 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884 encode_generic_class (assembly, gclass, buf);
887 * Make sure we use the correct type.
889 sigbuffer_add_value (buf, k->byval_arg.type);
891 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892 * otherwise two typerefs could point to the same type, leading to
893 * verification errors.
895 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
899 case MONO_TYPE_ARRAY:
900 sigbuffer_add_value (buf, type->type);
901 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902 sigbuffer_add_value (buf, type->data.array->rank);
903 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904 sigbuffer_add_value (buf, 0);
906 case MONO_TYPE_GENERICINST:
907 encode_generic_class (assembly, type->data.generic_class, buf);
911 sigbuffer_add_value (buf, type->type);
912 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
915 g_error ("need to encode type %x", type->type);
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
922 MONO_REQ_GC_UNSAFE_MODE;
924 mono_error_init (error);
927 sigbuffer_add_value (buf, MONO_TYPE_VOID);
931 MonoType *t = mono_reflection_type_get_handle (type, error);
932 return_if_nok (error);
933 encode_type (assembly, t, buf);
937 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
939 MONO_REQ_GC_UNSAFE_MODE;
943 mono_error_init (error);
946 for (i = 0; i < mono_array_length (modreq); ++i) {
947 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
948 return_if_nok (error);
949 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
950 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
954 for (i = 0; i < mono_array_length (modopt); ++i) {
955 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
956 return_if_nok (error);
957 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
958 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
963 #ifndef DISABLE_REFLECTION_EMIT
965 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
967 MONO_REQ_GC_UNSAFE_MODE;
971 guint32 nparams = sig->param_count;
977 sigbuffer_init (&buf, 32);
979 * FIXME: vararg, explicit_this, differenc call_conv values...
981 idx = sig->call_convention;
983 idx |= 0x20; /* hasthis */
984 if (sig->generic_param_count)
985 idx |= 0x10; /* generic */
986 sigbuffer_add_byte (&buf, idx);
987 if (sig->generic_param_count)
988 sigbuffer_add_value (&buf, sig->generic_param_count);
989 sigbuffer_add_value (&buf, nparams);
990 encode_type (assembly, sig->ret, &buf);
991 for (i = 0; i < nparams; ++i) {
992 if (i == sig->sentinelpos)
993 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
994 encode_type (assembly, sig->params [i], &buf);
996 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
997 sigbuffer_free (&buf);
1003 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1005 MONO_REQ_GC_UNSAFE_MODE;
1007 mono_error_init (error);
1010 * FIXME: reuse code from method_encode_signature().
1014 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1015 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1016 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1019 sigbuffer_init (&buf, 32);
1020 /* LAMESPEC: all the call conv spec is foobared */
1021 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1022 if (mb->call_conv & 2)
1023 idx |= 0x5; /* vararg */
1024 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1025 idx |= 0x20; /* hasthis */
1027 idx |= 0x10; /* generic */
1028 sigbuffer_add_byte (&buf, idx);
1030 sigbuffer_add_value (&buf, ngparams);
1031 sigbuffer_add_value (&buf, nparams + notypes);
1032 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1035 encode_reflection_type (assembly, mb->rtype, &buf, error);
1038 for (i = 0; i < nparams; ++i) {
1039 MonoArray *modreq = NULL;
1040 MonoArray *modopt = NULL;
1041 MonoReflectionType *pt;
1043 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1044 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1045 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1046 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1047 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1050 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1051 encode_reflection_type (assembly, pt, &buf, error);
1056 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1057 for (i = 0; i < notypes; ++i) {
1058 MonoReflectionType *pt;
1060 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1061 encode_reflection_type (assembly, pt, &buf, error);
1066 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1068 sigbuffer_free (&buf);
1073 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1075 MONO_REQ_GC_UNSAFE_MODE;
1077 mono_error_init (error);
1079 MonoDynamicTable *table;
1081 guint32 idx, sig_idx;
1082 guint nl = mono_array_length (ilgen->locals);
1086 sigbuffer_init (&buf, 32);
1087 sigbuffer_add_value (&buf, 0x07);
1088 sigbuffer_add_value (&buf, nl);
1089 for (i = 0; i < nl; ++i) {
1090 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1093 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1095 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1096 if (!is_ok (error)) {
1097 sigbuffer_free (&buf);
1101 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1102 sigbuffer_free (&buf);
1104 if (assembly->standalonesig_cache == NULL)
1105 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1106 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1110 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1111 idx = table->next_idx ++;
1113 alloc_table (table, table->rows);
1114 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1116 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1118 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1124 method_count_clauses (MonoReflectionILGen *ilgen)
1126 MONO_REQ_GC_UNSAFE_MODE;
1128 guint32 num_clauses = 0;
1131 MonoILExceptionInfo *ex_info;
1132 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1133 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134 if (ex_info->handlers)
1135 num_clauses += mono_array_length (ex_info->handlers);
1143 #ifndef DISABLE_REFLECTION_EMIT
1144 static MonoExceptionClause*
1145 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1147 MONO_REQ_GC_UNSAFE_MODE;
1150 MonoExceptionClause *clauses;
1151 MonoExceptionClause *clause;
1152 MonoILExceptionInfo *ex_info;
1153 MonoILExceptionBlock *ex_block;
1154 guint32 finally_start;
1155 int i, j, clause_index;;
1157 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1160 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1161 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1162 finally_start = ex_info->start + ex_info->len;
1163 if (!ex_info->handlers)
1165 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1166 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1167 clause = &(clauses [clause_index]);
1169 clause->flags = ex_block->type;
1170 clause->try_offset = ex_info->start;
1172 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1173 clause->try_len = finally_start - ex_info->start;
1175 clause->try_len = ex_info->len;
1176 clause->handler_offset = ex_block->start;
1177 clause->handler_len = ex_block->len;
1178 if (ex_block->extype) {
1179 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, &error);
1180 mono_error_raise_exception (&error); /* FIXME don't raise here */
1181 clause->data.catch_class = mono_class_from_mono_type (extype);
1183 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1184 clause->data.filter_offset = ex_block->filter_offset;
1186 clause->data.filter_offset = 0;
1188 finally_start = ex_block->start + ex_block->len;
1196 #endif /* !DISABLE_REFLECTION_EMIT */
1199 * method_encode_code:
1201 * @assembly the assembly
1202 * @mb the managed MethodBuilder
1203 * @error set on error
1205 * Note that the return value is not sensible if @error is set.
1208 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1210 MONO_REQ_GC_UNSAFE_MODE;
1215 gint32 max_stack, i;
1216 gint32 num_locals = 0;
1217 gint32 num_exception = 0;
1220 char fat_header [12];
1222 guint16 short_value;
1223 guint32 local_sig = 0;
1224 guint32 header_size = 12;
1227 mono_error_init (error);
1229 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1230 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1234 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1236 code = mb->ilgen->code;
1237 code_size = mb->ilgen->code_len;
1238 max_stack = mb->ilgen->max_stack;
1239 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1240 if (mb->ilgen->ex_handlers)
1241 num_exception = method_count_clauses (mb->ilgen);
1245 char *name = mono_string_to_utf8 (mb->name);
1246 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1247 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1253 code_size = mono_array_length (code);
1254 max_stack = 8; /* we probably need to run a verifier on the code... */
1257 stream_data_align (&assembly->code);
1259 /* check for exceptions, maxstack, locals */
1260 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1262 if (code_size < 64 && !(code_size & 1)) {
1263 flags = (code_size << 2) | 0x2;
1264 } else if (code_size < 32 && (code_size & 1)) {
1265 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1269 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1270 /* add to the fixup todo list */
1271 if (mb->ilgen && mb->ilgen->num_token_fixups)
1272 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1273 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1274 return assembly->text_rva + idx;
1278 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1279 return_val_if_nok (error, 0);
1282 * FIXME: need to set also the header size in fat_flags.
1283 * (and more sects and init locals flags)
1287 fat_flags |= METHOD_HEADER_MORE_SECTS;
1288 if (mb->init_locals)
1289 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1290 fat_header [0] = fat_flags;
1291 fat_header [1] = (header_size / 4 ) << 4;
1292 short_value = GUINT16_TO_LE (max_stack);
1293 memcpy (fat_header + 2, &short_value, 2);
1294 int_value = GUINT32_TO_LE (code_size);
1295 memcpy (fat_header + 4, &int_value, 4);
1296 int_value = GUINT32_TO_LE (local_sig);
1297 memcpy (fat_header + 8, &int_value, 4);
1298 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1299 /* add to the fixup todo list */
1300 if (mb->ilgen && mb->ilgen->num_token_fixups)
1301 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1303 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1304 if (num_exception) {
1305 unsigned char sheader [4];
1306 MonoILExceptionInfo * ex_info;
1307 MonoILExceptionBlock * ex_block;
1310 stream_data_align (&assembly->code);
1311 /* always use fat format for now */
1312 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1313 num_exception *= 6 * sizeof (guint32);
1314 num_exception += 4; /* include the size of the header */
1315 sheader [1] = num_exception & 0xff;
1316 sheader [2] = (num_exception >> 8) & 0xff;
1317 sheader [3] = (num_exception >> 16) & 0xff;
1318 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1319 /* fat header, so we are already aligned */
1321 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1322 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1323 if (ex_info->handlers) {
1324 int finally_start = ex_info->start + ex_info->len;
1325 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1327 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1329 val = GUINT32_TO_LE (ex_block->type);
1330 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1332 val = GUINT32_TO_LE (ex_info->start);
1333 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1334 /* need fault, too, probably */
1335 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1336 val = GUINT32_TO_LE (finally_start - ex_info->start);
1338 val = GUINT32_TO_LE (ex_info->len);
1339 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1340 /* handler offset */
1341 val = GUINT32_TO_LE (ex_block->start);
1342 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1344 val = GUINT32_TO_LE (ex_block->len);
1345 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1346 finally_start = ex_block->start + ex_block->len;
1347 if (ex_block->extype) {
1348 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1349 return_val_if_nok (error, 0);
1351 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1353 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1354 val = ex_block->filter_offset;
1358 val = GUINT32_TO_LE (val);
1359 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1360 /*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",
1361 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);*/
1364 g_error ("No clauses for ex info block %d", i);
1368 return assembly->text_rva + idx;
1372 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1374 MONO_REQ_GC_NEUTRAL_MODE;
1377 MonoDynamicTable *table;
1380 table = &assembly->tables [table_idx];
1382 g_assert (col < table->columns);
1384 values = table->values + table->columns;
1385 for (i = 1; i <= table->rows; ++i) {
1386 if (values [col] == token)
1388 values += table->columns;
1394 * LOCKING: Acquires the loader lock.
1396 static MonoCustomAttrInfo*
1397 lookup_custom_attr (MonoImage *image, gpointer member)
1399 MONO_REQ_GC_NEUTRAL_MODE;
1401 MonoCustomAttrInfo* res;
1403 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1408 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1414 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1416 MONO_REQ_GC_UNSAFE_MODE;
1418 /* FIXME: Need to do more checks */
1419 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1420 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1422 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1429 static MonoCustomAttrInfo*
1430 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1432 MONO_REQ_GC_UNSAFE_MODE;
1434 int i, index, count, not_visible;
1435 MonoCustomAttrInfo *ainfo;
1436 MonoReflectionCustomAttr *cattr;
1440 /* FIXME: check in assembly the Run flag is set */
1442 count = mono_array_length (cattrs);
1444 /* Skip nonpublic attributes since MS.NET seems to do the same */
1445 /* FIXME: This needs to be done more globally */
1447 for (i = 0; i < count; ++i) {
1448 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1449 if (!custom_attr_visible (image, cattr))
1452 count -= not_visible;
1454 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1456 ainfo->image = image;
1457 ainfo->num_attrs = count;
1458 ainfo->cached = alloc_img != NULL;
1460 for (i = 0; i < count; ++i) {
1461 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1462 if (custom_attr_visible (image, cattr)) {
1463 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1464 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1465 ainfo->attrs [index].ctor = cattr->ctor->method;
1466 ainfo->attrs [index].data = saved;
1467 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1475 #ifndef DISABLE_REFLECTION_EMIT
1477 * LOCKING: Acquires the loader lock.
1480 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1482 MONO_REQ_GC_UNSAFE_MODE;
1484 MonoCustomAttrInfo *ainfo, *tmp;
1486 if (!cattrs || !mono_array_length (cattrs))
1489 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1491 mono_loader_lock ();
1492 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1494 mono_custom_attrs_free (tmp);
1495 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1496 mono_loader_unlock ();
1502 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1504 MONO_REQ_GC_NEUTRAL_MODE;
1506 if (ainfo && !ainfo->cached)
1511 * idx is the table index of the object
1512 * type is one of MONO_CUSTOM_ATTR_*
1515 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1517 MONO_REQ_GC_UNSAFE_MODE;
1519 MonoDynamicTable *table;
1520 MonoReflectionCustomAttr *cattr;
1522 guint32 count, i, token;
1524 char *p = blob_size;
1526 mono_error_init (error);
1528 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1531 count = mono_array_length (cattrs);
1532 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1533 table->rows += count;
1534 alloc_table (table, table->rows);
1535 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1536 idx <<= MONO_CUSTOM_ATTR_BITS;
1538 for (i = 0; i < count; ++i) {
1539 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1540 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1541 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1542 if (!mono_error_ok (error)) goto fail;
1543 type = mono_metadata_token_index (token);
1544 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1545 switch (mono_metadata_token_table (token)) {
1546 case MONO_TABLE_METHOD:
1547 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1549 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1550 * method, not the one returned by mono_image_create_token ().
1552 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1554 case MONO_TABLE_MEMBERREF:
1555 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1558 g_warning ("got wrong token in custom attr");
1561 values [MONO_CUSTOM_ATTR_TYPE] = type;
1563 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1564 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1565 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1566 values += MONO_CUSTOM_ATTR_SIZE;
1577 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1579 MONO_REQ_GC_UNSAFE_MODE;
1581 MonoDynamicTable *table;
1583 guint32 count, i, idx;
1584 MonoReflectionPermissionSet *perm;
1589 count = mono_array_length (permissions);
1590 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1591 table->rows += count;
1592 alloc_table (table, table->rows);
1594 for (i = 0; i < mono_array_length (permissions); ++i) {
1595 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1597 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1599 idx = mono_metadata_token_index (parent_token);
1600 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1601 switch (mono_metadata_token_table (parent_token)) {
1602 case MONO_TABLE_TYPEDEF:
1603 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1605 case MONO_TABLE_METHOD:
1606 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1608 case MONO_TABLE_ASSEMBLY:
1609 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1612 g_assert_not_reached ();
1615 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1616 values [MONO_DECL_SECURITY_PARENT] = idx;
1617 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1624 * Fill in the MethodDef and ParamDef tables for a method.
1625 * This is used for both normal methods and constructors.
1628 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1630 MONO_REQ_GC_UNSAFE_MODE;
1632 MonoDynamicTable *table;
1636 mono_error_init (error);
1638 /* room in this table is already allocated */
1639 table = &assembly->tables [MONO_TABLE_METHOD];
1640 *mb->table_idx = table->next_idx ++;
1641 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1642 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1643 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1644 values [MONO_METHOD_FLAGS] = mb->attrs;
1645 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1646 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1647 return_val_if_nok (error, FALSE);
1648 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1649 return_val_if_nok (error, FALSE);
1651 table = &assembly->tables [MONO_TABLE_PARAM];
1652 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1654 mono_image_add_decl_security (assembly,
1655 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1658 MonoDynamicTable *mtable;
1661 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1662 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1665 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1666 if (mono_array_get (mb->pinfo, gpointer, i))
1669 table->rows += count;
1670 alloc_table (table, table->rows);
1671 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1672 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1673 MonoReflectionParamBuilder *pb;
1674 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1675 values [MONO_PARAM_FLAGS] = pb->attrs;
1676 values [MONO_PARAM_SEQUENCE] = i;
1677 if (pb->name != NULL) {
1678 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1680 values [MONO_PARAM_NAME] = 0;
1682 values += MONO_PARAM_SIZE;
1683 if (pb->marshal_info) {
1685 alloc_table (mtable, mtable->rows);
1686 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1687 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1688 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1690 pb->table_idx = table->next_idx++;
1691 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1692 guint32 field_type = 0;
1693 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1695 alloc_table (mtable, mtable->rows);
1696 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1697 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1698 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1699 mvalues [MONO_CONSTANT_TYPE] = field_type;
1700 mvalues [MONO_CONSTANT_PADDING] = 0;
1709 #ifndef DISABLE_REFLECTION_EMIT
1711 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1713 MONO_REQ_GC_UNSAFE_MODE;
1715 mono_error_init (error);
1716 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1718 rmb->ilgen = mb->ilgen;
1719 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1720 return_val_if_nok (error, FALSE);
1721 rmb->parameters = mb->parameters;
1722 rmb->generic_params = mb->generic_params;
1723 rmb->generic_container = mb->generic_container;
1724 rmb->opt_types = NULL;
1725 rmb->pinfo = mb->pinfo;
1726 rmb->attrs = mb->attrs;
1727 rmb->iattrs = mb->iattrs;
1728 rmb->call_conv = mb->call_conv;
1729 rmb->code = mb->code;
1730 rmb->type = mb->type;
1731 rmb->name = mb->name;
1732 rmb->table_idx = &mb->table_idx;
1733 rmb->init_locals = mb->init_locals;
1734 rmb->skip_visibility = FALSE;
1735 rmb->return_modreq = mb->return_modreq;
1736 rmb->return_modopt = mb->return_modopt;
1737 rmb->param_modreq = mb->param_modreq;
1738 rmb->param_modopt = mb->param_modopt;
1739 rmb->permissions = mb->permissions;
1740 rmb->mhandle = mb->mhandle;
1745 rmb->charset = mb->charset;
1746 rmb->extra_flags = mb->extra_flags;
1747 rmb->native_cc = mb->native_cc;
1748 rmb->dllentry = mb->dllentry;
1756 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1758 MONO_REQ_GC_UNSAFE_MODE;
1760 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1762 mono_error_init (error);
1764 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1766 rmb->ilgen = mb->ilgen;
1767 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1768 return_val_if_nok (error, FALSE);
1769 rmb->parameters = mb->parameters;
1770 rmb->generic_params = NULL;
1771 rmb->generic_container = NULL;
1772 rmb->opt_types = NULL;
1773 rmb->pinfo = mb->pinfo;
1774 rmb->attrs = mb->attrs;
1775 rmb->iattrs = mb->iattrs;
1776 rmb->call_conv = mb->call_conv;
1778 rmb->type = mb->type;
1779 rmb->name = mono_string_new (mono_domain_get (), name);
1780 rmb->table_idx = &mb->table_idx;
1781 rmb->init_locals = mb->init_locals;
1782 rmb->skip_visibility = FALSE;
1783 rmb->return_modreq = NULL;
1784 rmb->return_modopt = NULL;
1785 rmb->param_modreq = mb->param_modreq;
1786 rmb->param_modopt = mb->param_modopt;
1787 rmb->permissions = mb->permissions;
1788 rmb->mhandle = mb->mhandle;
1796 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1798 MONO_REQ_GC_UNSAFE_MODE;
1800 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1802 rmb->ilgen = mb->ilgen;
1803 rmb->rtype = mb->rtype;
1804 rmb->parameters = mb->parameters;
1805 rmb->generic_params = NULL;
1806 rmb->generic_container = NULL;
1807 rmb->opt_types = NULL;
1809 rmb->attrs = mb->attrs;
1811 rmb->call_conv = mb->call_conv;
1813 rmb->type = (MonoObject *) mb->owner;
1814 rmb->name = mb->name;
1815 rmb->table_idx = NULL;
1816 rmb->init_locals = mb->init_locals;
1817 rmb->skip_visibility = mb->skip_visibility;
1818 rmb->return_modreq = NULL;
1819 rmb->return_modopt = NULL;
1820 rmb->param_modreq = NULL;
1821 rmb->param_modopt = NULL;
1822 rmb->permissions = NULL;
1823 rmb->mhandle = mb->mhandle;
1830 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1832 MONO_REQ_GC_UNSAFE_MODE;
1834 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1835 MonoDynamicTable *table;
1838 MonoReflectionMethod *m;
1841 mono_error_init (error);
1843 if (!mb->override_methods)
1846 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1847 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1849 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1851 alloc_table (table, table->rows);
1852 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1853 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1854 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1856 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1857 return_val_if_nok (error, FALSE);
1859 switch (mono_metadata_token_table (tok)) {
1860 case MONO_TABLE_MEMBERREF:
1861 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1863 case MONO_TABLE_METHOD:
1864 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1867 g_assert_not_reached ();
1869 values [MONO_METHODIMPL_DECLARATION] = tok;
1875 #ifndef DISABLE_REFLECTION_EMIT
1877 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1879 MONO_REQ_GC_UNSAFE_MODE;
1881 MonoDynamicTable *table;
1883 ReflectionMethodBuilder rmb;
1886 mono_error_init (error);
1888 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1889 !mono_image_basic_method (&rmb, assembly, error))
1892 mb->table_idx = *rmb.table_idx;
1894 if (mb->dll) { /* It's a P/Invoke method */
1896 /* map CharSet values to on-disk values */
1897 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1898 int extra_flags = mb->extra_flags;
1899 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1901 alloc_table (table, table->rows);
1902 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1904 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1905 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1907 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1909 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1910 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1911 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1912 table = &assembly->tables [MONO_TABLE_MODULEREF];
1914 alloc_table (table, table->rows);
1915 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1916 values [MONO_IMPLMAP_SCOPE] = table->rows;
1920 if (mb->generic_params) {
1921 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1922 table->rows += mono_array_length (mb->generic_params);
1923 alloc_table (table, table->rows);
1924 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1925 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1927 mono_image_get_generic_param_info (
1928 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1936 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1938 MONO_REQ_GC_UNSAFE_MODE;
1940 ReflectionMethodBuilder rmb;
1942 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1945 if (!mono_image_basic_method (&rmb, assembly, error))
1948 mb->table_idx = *rmb.table_idx;
1955 type_get_fully_qualified_name (MonoType *type)
1957 MONO_REQ_GC_NEUTRAL_MODE;
1959 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1963 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1965 MONO_REQ_GC_UNSAFE_MODE;
1970 klass = mono_class_from_mono_type (type);
1972 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1973 ta = klass->image->assembly;
1974 if (assembly_is_dynamic (ta) || (ta == ass)) {
1975 if (klass->generic_class || klass->generic_container)
1976 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1977 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1979 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1982 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1985 #ifndef DISABLE_REFLECTION_EMIT
1986 /*field_image is the image to which the eventual custom mods have been encoded against*/
1988 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1990 MONO_REQ_GC_NEUTRAL_MODE;
1993 guint32 idx, i, token;
1995 if (!assembly->save)
1998 sigbuffer_init (&buf, 32);
2000 sigbuffer_add_value (&buf, 0x06);
2001 /* encode custom attributes before the type */
2002 if (type->num_mods) {
2003 for (i = 0; i < type->num_mods; ++i) {
2006 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2007 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2009 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2011 token = type->modifiers [i].token;
2014 if (type->modifiers [i].required)
2015 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2017 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2019 sigbuffer_add_value (&buf, token);
2022 encode_type (assembly, type, &buf);
2023 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024 sigbuffer_free (&buf);
2030 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2032 MONO_REQ_GC_UNSAFE_MODE;
2037 guint32 typespec = 0;
2041 init_type_builder_generics (fb->type);
2043 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
2044 mono_error_raise_exception (&error); /* FIXME don't raise here */
2045 klass = mono_class_from_mono_type (type);
2047 sigbuffer_init (&buf, 32);
2049 sigbuffer_add_value (&buf, 0x06);
2050 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, &error);
2051 if (!is_ok (&error))
2053 /* encode custom attributes before the type */
2055 if (klass->generic_container)
2056 typespec = create_typespec (assembly, type);
2059 MonoGenericClass *gclass;
2060 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2061 encode_generic_class (assembly, gclass, &buf);
2063 encode_type (assembly, type, &buf);
2065 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2066 sigbuffer_free (&buf);
2069 sigbuffer_free (&buf);
2070 mono_error_raise_exception (&error); /* FIXME don't raise here */
2071 g_assert_not_reached ();
2075 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2077 MONO_REQ_GC_UNSAFE_MODE;
2079 char blob_size [64];
2080 char *b = blob_size;
2083 guint32 idx = 0, len = 0, dummy = 0;
2085 buf = (char *)g_malloc (64);
2087 *ret_type = MONO_TYPE_CLASS;
2089 box_val = (char*)&dummy;
2091 box_val = ((char*)val) + sizeof (MonoObject);
2092 *ret_type = val->vtable->klass->byval_arg.type;
2095 switch (*ret_type) {
2096 case MONO_TYPE_BOOLEAN:
2101 case MONO_TYPE_CHAR:
2118 case MONO_TYPE_VALUETYPE: {
2119 MonoClass *klass = val->vtable->klass;
2121 if (klass->enumtype) {
2122 *ret_type = mono_class_enum_basetype (klass)->type;
2124 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2127 g_error ("we can't encode valuetypes, we should have never reached this line");
2130 case MONO_TYPE_CLASS:
2132 case MONO_TYPE_STRING: {
2133 MonoString *str = (MonoString*)val;
2134 /* there is no signature */
2135 len = str->length * 2;
2136 mono_metadata_encode_value (len, b, &b);
2137 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2139 char *swapped = g_malloc (2 * mono_string_length (str));
2140 const char *p = (const char*)mono_string_chars (str);
2142 swap_with_size (swapped, p, 2, mono_string_length (str));
2143 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2147 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2153 case MONO_TYPE_GENERICINST:
2154 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2157 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2160 /* there is no signature */
2161 mono_metadata_encode_value (len, b, &b);
2162 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2163 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2164 swap_with_size (blob_size, box_val, len, 1);
2165 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2175 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2177 MONO_REQ_GC_UNSAFE_MODE;
2184 sigbuffer_init (&buf, 32);
2186 sigbuffer_add_value (&buf, minfo->type);
2188 switch (minfo->type) {
2189 case MONO_NATIVE_BYVALTSTR:
2190 case MONO_NATIVE_BYVALARRAY:
2191 sigbuffer_add_value (&buf, minfo->count);
2193 case MONO_NATIVE_LPARRAY:
2194 if (minfo->eltype || minfo->has_size) {
2195 sigbuffer_add_value (&buf, minfo->eltype);
2196 if (minfo->has_size) {
2197 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2198 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2200 /* LAMESPEC: ElemMult is undocumented */
2201 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2205 case MONO_NATIVE_SAFEARRAY:
2207 sigbuffer_add_value (&buf, minfo->eltype);
2209 case MONO_NATIVE_CUSTOM:
2211 str = mono_string_to_utf8 (minfo->guid);
2213 sigbuffer_add_value (&buf, len);
2214 sigbuffer_add_mem (&buf, str, len);
2217 sigbuffer_add_value (&buf, 0);
2219 /* native type name */
2220 sigbuffer_add_value (&buf, 0);
2221 /* custom marshaler type name */
2222 if (minfo->marshaltype || minfo->marshaltyperef) {
2223 if (minfo->marshaltyperef) {
2224 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
2225 mono_error_raise_exception (&error); /* FIXME don't raise here */
2226 str = type_get_fully_qualified_name (marshaltype);
2228 str = mono_string_to_utf8 (minfo->marshaltype);
2230 sigbuffer_add_value (&buf, len);
2231 sigbuffer_add_mem (&buf, str, len);
2234 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2235 sigbuffer_add_value (&buf, 0);
2237 if (minfo->mcookie) {
2238 str = mono_string_to_utf8 (minfo->mcookie);
2240 sigbuffer_add_value (&buf, len);
2241 sigbuffer_add_mem (&buf, str, len);
2244 sigbuffer_add_value (&buf, 0);
2250 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2251 sigbuffer_free (&buf);
2256 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2258 MONO_REQ_GC_UNSAFE_MODE;
2260 MonoDynamicTable *table;
2263 /* maybe this fixup should be done in the C# code */
2264 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2265 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2266 table = &assembly->tables [MONO_TABLE_FIELD];
2267 fb->table_idx = table->next_idx ++;
2268 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2269 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2270 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2271 values [MONO_FIELD_FLAGS] = fb->attrs;
2272 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2274 if (fb->offset != -1) {
2275 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2277 alloc_table (table, table->rows);
2278 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2279 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2280 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2282 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2283 MonoTypeEnum field_type = (MonoTypeEnum)0;
2284 table = &assembly->tables [MONO_TABLE_CONSTANT];
2286 alloc_table (table, table->rows);
2287 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2288 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2289 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2290 values [MONO_CONSTANT_TYPE] = field_type;
2291 values [MONO_CONSTANT_PADDING] = 0;
2293 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2295 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2297 alloc_table (table, table->rows);
2298 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2299 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2301 * We store it in the code section because it's simpler for now.
2304 if (mono_array_length (fb->rva_data) >= 10)
2305 stream_data_align (&assembly->code);
2306 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2308 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2309 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2311 if (fb->marshal_info) {
2312 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2314 alloc_table (table, table->rows);
2315 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2316 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2317 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2322 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2324 MONO_REQ_GC_UNSAFE_MODE;
2328 guint32 nparams = 0;
2329 MonoReflectionMethodBuilder *mb = fb->get_method;
2330 MonoReflectionMethodBuilder *smb = fb->set_method;
2333 if (mb && mb->parameters)
2334 nparams = mono_array_length (mb->parameters);
2335 if (!mb && smb && smb->parameters)
2336 nparams = mono_array_length (smb->parameters) - 1;
2337 sigbuffer_init (&buf, 32);
2338 if (fb->call_conv & 0x20)
2339 sigbuffer_add_byte (&buf, 0x28);
2341 sigbuffer_add_byte (&buf, 0x08);
2342 sigbuffer_add_value (&buf, nparams);
2344 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, &error);
2345 if (!is_ok (&error))
2347 for (i = 0; i < nparams; ++i) {
2348 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2349 encode_reflection_type (assembly, pt, &buf, &error);
2350 if (!is_ok (&error))
2353 } else if (smb && smb->parameters) {
2354 /* the property type is the last param */
2355 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, &error);
2356 if (!is_ok (&error))
2359 for (i = 0; i < nparams; ++i) {
2360 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2361 encode_reflection_type (assembly, pt, &buf, &error);
2362 if (!is_ok (&error))
2366 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, &error);
2367 if (!is_ok (&error))
2371 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2372 sigbuffer_free (&buf);
2375 sigbuffer_free (&buf);
2376 mono_error_raise_exception (&error); /* FIXME don't raise here */
2377 g_assert_not_reached ();
2381 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2383 MONO_REQ_GC_UNSAFE_MODE;
2385 MonoDynamicTable *table;
2387 guint num_methods = 0;
2391 * we need to set things in the following tables:
2392 * PROPERTYMAP (info already filled in _get_type_info ())
2393 * PROPERTY (rows already preallocated in _get_type_info ())
2394 * METHOD (method info already done with the generic method code)
2398 table = &assembly->tables [MONO_TABLE_PROPERTY];
2399 pb->table_idx = table->next_idx ++;
2400 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2401 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2402 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2403 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2405 /* FIXME: we still don't handle 'other' methods */
2406 if (pb->get_method) num_methods ++;
2407 if (pb->set_method) num_methods ++;
2409 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410 table->rows += num_methods;
2411 alloc_table (table, table->rows);
2413 if (pb->get_method) {
2414 semaidx = table->next_idx ++;
2415 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2417 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2418 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2420 if (pb->set_method) {
2421 semaidx = table->next_idx ++;
2422 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2424 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2425 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2427 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2428 MonoTypeEnum field_type = (MonoTypeEnum)0;
2429 table = &assembly->tables [MONO_TABLE_CONSTANT];
2431 alloc_table (table, table->rows);
2432 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2433 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2434 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2435 values [MONO_CONSTANT_TYPE] = field_type;
2436 values [MONO_CONSTANT_PADDING] = 0;
2441 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2443 MONO_REQ_GC_UNSAFE_MODE;
2446 MonoDynamicTable *table;
2448 guint num_methods = 0;
2452 * we need to set things in the following tables:
2453 * EVENTMAP (info already filled in _get_type_info ())
2454 * EVENT (rows already preallocated in _get_type_info ())
2455 * METHOD (method info already done with the generic method code)
2458 table = &assembly->tables [MONO_TABLE_EVENT];
2459 eb->table_idx = table->next_idx ++;
2460 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2461 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2462 values [MONO_EVENT_FLAGS] = eb->attrs;
2463 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2464 mono_error_raise_exception (&error); /* FIXME don't raise here */
2465 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2468 * FIXME: we still don't handle 'other' methods
2470 if (eb->add_method) num_methods ++;
2471 if (eb->remove_method) num_methods ++;
2472 if (eb->raise_method) num_methods ++;
2474 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2475 table->rows += num_methods;
2476 alloc_table (table, table->rows);
2478 if (eb->add_method) {
2479 semaidx = table->next_idx ++;
2480 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2481 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2482 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2483 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2485 if (eb->remove_method) {
2486 semaidx = table->next_idx ++;
2487 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2488 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2489 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2490 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2492 if (eb->raise_method) {
2493 semaidx = table->next_idx ++;
2494 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2495 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2496 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2497 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2502 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2504 MONO_REQ_GC_UNSAFE_MODE;
2507 MonoDynamicTable *table;
2508 guint32 num_constraints, i;
2512 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2513 num_constraints = gparam->iface_constraints ?
2514 mono_array_length (gparam->iface_constraints) : 0;
2515 table->rows += num_constraints;
2516 if (gparam->base_type)
2518 alloc_table (table, table->rows);
2520 if (gparam->base_type) {
2521 table_idx = table->next_idx ++;
2522 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2524 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, &error);
2525 mono_error_raise_exception (&error); /* FIXME don't raise here */
2526 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2527 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2530 for (i = 0; i < num_constraints; i++) {
2531 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2532 gparam->iface_constraints, gpointer, i);
2534 table_idx = table->next_idx ++;
2535 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2537 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, &error);
2538 mono_error_raise_exception (&error); /* FIXME don't raise here */
2540 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2541 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2546 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2548 MONO_REQ_GC_UNSAFE_MODE;
2550 GenericParamTableEntry *entry;
2553 * The GenericParam table must be sorted according to the `owner' field.
2554 * We need to do this sorting prior to writing the GenericParamConstraint
2555 * table, since we have to use the final GenericParam table indices there
2556 * and they must also be sorted.
2559 entry = g_new0 (GenericParamTableEntry, 1);
2560 entry->owner = owner;
2561 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2562 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2563 entry->gparam = gparam;
2565 g_ptr_array_add (assembly->gen_params, entry);
2569 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2571 MONO_REQ_GC_UNSAFE_MODE;
2573 MonoDynamicTable *table;
2574 MonoGenericParam *param;
2578 mono_error_init (error);
2580 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2581 table_idx = table->next_idx ++;
2582 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2584 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2585 return_val_if_nok (error, FALSE);
2587 param = gparam_type->data.generic_param;
2589 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2590 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2591 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2592 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2594 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2597 encode_constraints (entry->gparam, table_idx, assembly);
2603 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2605 MONO_REQ_GC_UNSAFE_MODE;
2607 MonoDynamicTable *table;
2610 guint32 cols [MONO_ASSEMBLY_SIZE];
2614 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2617 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2618 table = &assembly->tables [MONO_TABLE_MODULEREF];
2619 token = table->next_idx ++;
2621 alloc_table (table, table->rows);
2622 values = table->values + token * MONO_MODULEREF_SIZE;
2623 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2625 token <<= MONO_RESOLUTION_SCOPE_BITS;
2626 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2627 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2632 if (assembly_is_dynamic (image->assembly))
2634 memset (cols, 0, sizeof (cols));
2636 /* image->assembly->image is the manifest module */
2637 image = image->assembly->image;
2638 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2641 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2642 token = table->next_idx ++;
2644 alloc_table (table, table->rows);
2645 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2646 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2647 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2648 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2649 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2650 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2651 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2652 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2653 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2655 if (strcmp ("", image->assembly->aname.culture)) {
2656 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2657 image->assembly->aname.culture);
2660 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2661 guchar pubtoken [9];
2663 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2664 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2666 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2668 token <<= MONO_RESOLUTION_SCOPE_BITS;
2669 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2670 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2675 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2677 MONO_REQ_GC_NEUTRAL_MODE;
2679 MonoDynamicTable *table;
2684 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2687 sigbuffer_init (&buf, 32);
2688 switch (type->type) {
2689 case MONO_TYPE_FNPTR:
2691 case MONO_TYPE_SZARRAY:
2692 case MONO_TYPE_ARRAY:
2694 case MONO_TYPE_MVAR:
2695 case MONO_TYPE_GENERICINST:
2696 encode_type (assembly, type, &buf);
2698 case MONO_TYPE_CLASS:
2699 case MONO_TYPE_VALUETYPE: {
2700 MonoClass *k = mono_class_from_mono_type (type);
2701 if (!k || !k->generic_container) {
2702 sigbuffer_free (&buf);
2705 encode_type (assembly, type, &buf);
2709 sigbuffer_free (&buf);
2713 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2714 if (assembly->save) {
2715 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2716 alloc_table (table, table->rows + 1);
2717 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2718 values [MONO_TYPESPEC_SIGNATURE] = token;
2720 sigbuffer_free (&buf);
2722 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2723 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2729 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2731 MONO_REQ_GC_UNSAFE_MODE;
2733 MonoDynamicTable *table;
2735 guint32 token, scope, enclosing;
2738 /* if the type requires a typespec, we must try that first*/
2739 if (try_typespec && (token = create_typespec (assembly, type)))
2741 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2744 klass = mono_class_from_mono_type (type);
2746 klass = mono_class_from_mono_type (type);
2749 * If it's in the same module and not a generic type parameter:
2751 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2752 (type->type != MONO_TYPE_MVAR)) {
2753 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2754 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2755 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2759 if (klass->nested_in) {
2760 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2761 /* get the typeref idx of the enclosing type */
2762 enclosing >>= MONO_TYPEDEFORREF_BITS;
2763 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2765 scope = resolution_scope_from_image (assembly, klass->image);
2767 table = &assembly->tables [MONO_TABLE_TYPEREF];
2768 if (assembly->save) {
2769 alloc_table (table, table->rows + 1);
2770 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2771 values [MONO_TYPEREF_SCOPE] = scope;
2772 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2773 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2775 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2776 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2778 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2783 * Despite the name, we handle also TypeSpec (with the above helper).
2786 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2788 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2791 #ifndef DISABLE_REFLECTION_EMIT
2793 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2795 MONO_REQ_GC_NEUTRAL_MODE;
2797 MonoDynamicTable *table;
2799 guint32 token, pclass;
2801 switch (parent & MONO_TYPEDEFORREF_MASK) {
2802 case MONO_TYPEDEFORREF_TYPEREF:
2803 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2805 case MONO_TYPEDEFORREF_TYPESPEC:
2806 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2808 case MONO_TYPEDEFORREF_TYPEDEF:
2809 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2812 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2815 /* extract the index */
2816 parent >>= MONO_TYPEDEFORREF_BITS;
2818 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2820 if (assembly->save) {
2821 alloc_table (table, table->rows + 1);
2822 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2823 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2824 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2825 values [MONO_MEMBERREF_SIGNATURE] = sig;
2828 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2835 * Insert a memberef row into the metadata: the token that point to the memberref
2836 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2837 * mono_image_get_fieldref_token()).
2838 * The sig param is an index to an already built signature.
2841 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2843 MONO_REQ_GC_NEUTRAL_MODE;
2845 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2846 return mono_image_add_memberef_row (assembly, parent, name, sig);
2851 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2853 MONO_REQ_GC_NEUTRAL_MODE;
2856 MonoMethodSignature *sig;
2858 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2860 if (create_typespec) {
2861 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2866 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2867 if (token && !create_typespec)
2870 g_assert (!method->is_inflated);
2873 * A methodref signature can't contain an unmanaged calling convention.
2875 sig = mono_metadata_signature_dup (mono_method_signature (method));
2876 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2877 sig->call_convention = MONO_CALL_DEFAULT;
2878 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2879 method->name, method_encode_signature (assembly, sig));
2881 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2884 if (create_typespec) {
2885 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2886 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2887 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2889 if (assembly->save) {
2892 alloc_table (table, table->rows + 1);
2893 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2894 values [MONO_METHODSPEC_METHOD] = token;
2895 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2898 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2900 /*methodspec and memberef tokens are diferent, */
2901 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2908 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2910 guint32 token, parent, sig;
2911 ReflectionMethodBuilder rmb;
2912 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2914 mono_error_init (error);
2915 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2919 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2923 * A methodref signature can't contain an unmanaged calling convention.
2924 * Since some flags are encoded as part of call_conv, we need to check against it.
2926 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2927 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2929 sig = method_builder_encode_signature (assembly, &rmb, error);
2930 return_val_if_nok (error, 0);
2932 if (tb->generic_params)
2933 parent = create_generic_typespec (assembly, tb);
2935 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2936 return_val_if_nok (error, 0);
2938 parent = mono_image_typedef_or_ref (assembly, t);
2941 char *name = mono_string_to_utf8 (method->name);
2943 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2946 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2952 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2953 const gchar *name, guint32 sig)
2955 MonoDynamicTable *table;
2959 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2961 if (assembly->save) {
2962 alloc_table (table, table->rows + 1);
2963 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2964 values [MONO_MEMBERREF_CLASS] = original;
2965 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2966 values [MONO_MEMBERREF_SIGNATURE] = sig;
2969 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2976 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2980 guint32 nparams = mono_array_length (mb->generic_params);
2983 if (!assembly->save)
2986 sigbuffer_init (&buf, 32);
2988 sigbuffer_add_value (&buf, 0xa);
2989 sigbuffer_add_value (&buf, nparams);
2991 for (i = 0; i < nparams; i++) {
2992 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2993 sigbuffer_add_value (&buf, i);
2996 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2997 sigbuffer_free (&buf);
3002 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3004 MonoDynamicTable *table;
3006 guint32 token, mtoken = 0;
3008 mono_error_init (error);
3009 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3013 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3015 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3016 if (!mono_error_ok (error))
3019 switch (mono_metadata_token_table (mtoken)) {
3020 case MONO_TABLE_MEMBERREF:
3021 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3023 case MONO_TABLE_METHOD:
3024 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3027 g_assert_not_reached ();
3030 if (assembly->save) {
3031 alloc_table (table, table->rows + 1);
3032 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3033 values [MONO_METHODSPEC_METHOD] = mtoken;
3034 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3037 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3040 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3045 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3049 mono_error_init (error);
3051 if (mb->generic_params && create_methodspec)
3052 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3054 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3058 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3059 if (!mono_error_ok (error))
3061 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3066 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3068 guint32 token, parent, sig;
3069 ReflectionMethodBuilder rmb;
3071 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3073 mono_error_init (error);
3075 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3079 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3082 if (tb->generic_params)
3083 parent = create_generic_typespec (assembly, tb);
3085 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3086 return_val_if_nok (error, 0);
3087 parent = mono_image_typedef_or_ref (assembly, type);
3090 name = mono_string_to_utf8 (rmb.name);
3091 sig = method_builder_encode_signature (assembly, &rmb, error);
3092 return_val_if_nok (error, 0);
3094 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3097 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3103 is_field_on_inst (MonoClassField *field)
3105 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3109 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3112 get_field_on_inst_generic_type (MonoClassField *field)
3114 MonoClass *klass, *gtd;
3115 MonoDynamicGenericClass *dgclass;
3118 g_assert (is_field_on_inst (field));
3120 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3122 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3123 field_index = field - dgclass->fields;
3124 return dgclass->field_generic_types [field_index];
3127 klass = field->parent;
3128 gtd = klass->generic_class->container_class;
3130 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3131 field_index = field - klass->fields;
3132 return gtd->fields [field_index].type;
3135 g_assert_not_reached ();
3139 #ifndef DISABLE_REFLECTION_EMIT
3141 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3147 g_assert (field->parent);
3149 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3153 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3154 int index = field - field->parent->fields;
3155 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3157 if (is_field_on_inst (field))
3158 type = get_field_on_inst_generic_type (field);
3160 type = mono_field_get_type (field);
3162 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3163 mono_field_get_name (field),
3164 fieldref_encode_signature (assembly, field->parent->image, type));
3165 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3170 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3175 MonoGenericClass *gclass;
3179 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3182 if (is_sre_field_builder (mono_object_class (f->fb))) {
3183 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3184 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3185 mono_error_raise_exception (&error); /* FIXME don't raise here */
3186 klass = mono_class_from_mono_type (type);
3187 gclass = type->data.generic_class;
3188 g_assert (gclass->is_dynamic);
3190 name = mono_string_to_utf8 (fb->name);
3191 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3192 field_encode_signature (assembly, fb));
3194 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3196 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3198 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3199 mono_error_raise_exception (&error); /* FIXME don't raise here */
3200 klass = mono_class_from_mono_type (type);
3202 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3203 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3205 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3206 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3209 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3214 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3218 MonoGenericClass *gclass;
3221 mono_error_init (error);
3223 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3225 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3229 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3230 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3231 ReflectionMethodBuilder rmb;
3234 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3235 return_val_if_nok (error, 0);
3236 klass = mono_class_from_mono_type (type);
3238 gclass = type->data.generic_class;
3239 g_assert (gclass->is_dynamic);
3241 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3244 sig = method_builder_encode_signature (assembly, &rmb, error);
3245 return_val_if_nok (error, 0);
3247 name = mono_string_to_utf8 (rmb.name);
3249 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3251 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3252 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3254 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3255 return_val_if_nok (error, 0);
3256 klass = mono_class_from_mono_type (type);
3258 sig = method_encode_signature (assembly, mono_method_signature (mm));
3259 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3261 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3262 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3266 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3271 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3274 MonoGenericContext tmp_context;
3275 MonoType **type_argv;
3276 MonoGenericInst *ginst;
3277 MonoMethod *method, *inflated;
3280 mono_error_init (error);
3282 init_type_builder_generics ((MonoObject*)m->inst);
3284 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3285 return_val_if_nok (error, NULL);
3287 klass = method->klass;
3289 if (m->method_args == NULL)
3292 if (method->is_inflated)
3293 method = ((MonoMethodInflated *) method)->declaring;
3295 count = mono_array_length (m->method_args);
3297 type_argv = g_new0 (MonoType *, count);
3298 for (i = 0; i < count; i++) {
3299 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3300 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3301 return_val_if_nok (error, NULL);
3303 ginst = mono_metadata_get_generic_inst (count, type_argv);
3306 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3307 tmp_context.method_inst = ginst;
3309 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3310 mono_error_assert_ok (error);
3315 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3317 guint32 sig, token = 0;
3321 mono_error_init (error);
3323 if (m->method_args) {
3324 MonoMethod *inflated;
3326 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3327 return_val_if_nok (error, 0);
3329 if (create_methodspec)
3330 token = mono_image_get_methodspec_token (assembly, inflated);
3332 token = mono_image_get_inflated_method_token (assembly, inflated);
3336 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3340 if (is_sre_method_builder (mono_object_class (m->mb))) {
3341 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3342 MonoGenericClass *gclass;
3343 ReflectionMethodBuilder rmb;
3346 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3347 return_val_if_nok (error, 0);
3348 klass = mono_class_from_mono_type (type);
3349 gclass = type->data.generic_class;
3350 g_assert (gclass->is_dynamic);
3352 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3355 sig = method_builder_encode_signature (assembly, &rmb, error);
3356 return_val_if_nok (error, 0);
3358 name = mono_string_to_utf8 (rmb.name);
3360 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3362 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3363 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3365 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3366 return_val_if_nok (error, 0);
3367 klass = mono_class_from_mono_type (type);
3369 sig = method_encode_signature (assembly, mono_method_signature (mm));
3370 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3372 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3373 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3376 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3381 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3385 guint32 nparams = context->method_inst->type_argc;
3388 if (!assembly->save)
3391 sigbuffer_init (&buf, 32);
3393 * FIXME: vararg, explicit_this, differenc call_conv values...
3395 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3396 sigbuffer_add_value (&buf, nparams);
3398 for (i = 0; i < nparams; i++)
3399 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3401 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3402 sigbuffer_free (&buf);
3407 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3409 MonoDynamicTable *table;
3411 guint32 token, mtoken = 0, sig;
3412 MonoMethodInflated *imethod;
3413 MonoMethod *declaring;
3415 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3417 g_assert (method->is_inflated);
3418 imethod = (MonoMethodInflated *) method;
3419 declaring = imethod->declaring;
3421 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3422 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3424 if (!mono_method_signature (declaring)->generic_param_count)
3427 switch (mono_metadata_token_table (mtoken)) {
3428 case MONO_TABLE_MEMBERREF:
3429 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3431 case MONO_TABLE_METHOD:
3432 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3435 g_assert_not_reached ();
3438 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3440 if (assembly->save) {
3441 alloc_table (table, table->rows + 1);
3442 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3443 values [MONO_METHODSPEC_METHOD] = mtoken;
3444 values [MONO_METHODSPEC_SIGNATURE] = sig;
3447 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3454 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3456 MonoMethodInflated *imethod;
3459 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3463 g_assert (method->is_inflated);
3464 imethod = (MonoMethodInflated *) method;
3466 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3467 token = method_encode_methodspec (assembly, method);
3469 guint32 sig = method_encode_signature (
3470 assembly, mono_method_signature (imethod->declaring));
3471 token = mono_image_get_memberref_token (
3472 assembly, &method->klass->byval_arg, method->name, sig);
3475 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3480 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3482 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3485 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3486 token = mono_image_get_memberref_token (
3487 assembly, &m->klass->byval_arg, m->name, sig);
3493 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3496 MonoDynamicTable *table;
3505 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3506 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3507 * Because of this, we must not insert it into the `typeref' hash table.
3509 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3510 mono_error_raise_exception (&error); /* FIXME don't raise here */
3511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3515 sigbuffer_init (&buf, 32);
3517 g_assert (tb->generic_params);
3518 klass = mono_class_from_mono_type (type);
3520 if (tb->generic_container)
3521 mono_reflection_create_generic_class (tb);
3523 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3524 g_assert (klass->generic_container);
3525 sigbuffer_add_value (&buf, klass->byval_arg.type);
3526 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3528 count = mono_array_length (tb->generic_params);
3529 sigbuffer_add_value (&buf, count);
3530 for (i = 0; i < count; i++) {
3531 MonoReflectionGenericParam *gparam;
3533 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3534 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3535 mono_error_raise_exception (&error); /* FIXME don't raise here */
3537 encode_type (assembly, gparam_type, &buf);
3540 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3542 if (assembly->save) {
3543 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3544 alloc_table (table, table->rows + 1);
3545 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3546 values [MONO_TYPESPEC_SIGNATURE] = token;
3548 sigbuffer_free (&buf);
3550 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3551 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3557 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3560 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3563 int i, count, len, pos;
3568 count += mono_array_length (modreq);
3570 count += mono_array_length (modopt);
3573 return mono_metadata_type_dup (NULL, type);
3575 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3576 t = (MonoType *)g_malloc (len);
3577 memcpy (t, type, MONO_SIZEOF_TYPE);
3579 t->num_mods = count;
3582 for (i = 0; i < mono_array_length (modreq); ++i) {
3583 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3584 mono_error_raise_exception (&error); /* FIXME don't raise here */
3585 t->modifiers [pos].required = 1;
3586 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3591 for (i = 0; i < mono_array_length (modopt); ++i) {
3592 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3593 mono_error_raise_exception (&error); /* FIXME don't raise here */
3594 t->modifiers [pos].required = 0;
3595 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3604 init_type_builder_generics (MonoObject *type)
3606 MonoReflectionTypeBuilder *tb;
3608 if (!is_sre_type_builder(mono_object_class (type)))
3610 tb = (MonoReflectionTypeBuilder *)type;
3612 if (tb && tb->generic_container)
3613 mono_reflection_create_generic_class (tb);
3617 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3620 MonoDynamicTable *table;
3621 MonoType *custom = NULL, *type;
3623 guint32 token, pclass, parent, sig;
3626 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3630 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3631 mono_error_raise_exception (&error); /* FIXME don't raise here */
3632 /* FIXME: is this call necessary? */
3633 mono_class_from_mono_type (typeb);
3634 name = mono_string_to_utf8 (fb->name);
3636 /*FIXME this is one more layer of ugliness due how types are created.*/
3637 init_type_builder_generics (fb->type);
3639 /* fb->type does not include the custom modifiers */
3640 /* FIXME: We should do this in one place when a fieldbuilder is created */
3641 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3642 mono_error_raise_exception (&error); /* FIXME don't raise here */
3644 if (fb->modreq || fb->modopt)
3645 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3647 sig = fieldref_encode_signature (assembly, NULL, type);
3650 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3651 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3653 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3654 parent >>= MONO_TYPEDEFORREF_BITS;
3656 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3658 if (assembly->save) {
3659 alloc_table (table, table->rows + 1);
3660 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3661 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3662 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3663 values [MONO_MEMBERREF_SIGNATURE] = sig;
3666 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3668 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3674 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3681 if (!assembly->save)
3684 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3685 g_assert (helper->type == 2);
3687 if (helper->arguments)
3688 nargs = mono_array_length (helper->arguments);
3692 sigbuffer_init (&buf, 32);
3694 /* Encode calling convention */
3695 /* Change Any to Standard */
3696 if ((helper->call_conv & 0x03) == 0x03)
3697 helper->call_conv = 0x01;
3698 /* explicit_this implies has_this */
3699 if (helper->call_conv & 0x40)
3700 helper->call_conv &= 0x20;
3702 if (helper->call_conv == 0) { /* Unmanaged */
3703 idx = helper->unmanaged_call_conv - 1;
3706 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3707 if (helper->call_conv & 0x02) /* varargs */
3711 sigbuffer_add_byte (&buf, idx);
3712 sigbuffer_add_value (&buf, nargs);
3713 encode_reflection_type (assembly, helper->return_type, &buf, &error);
3714 if (!is_ok (&error))
3716 for (i = 0; i < nargs; ++i) {
3717 MonoArray *modreqs = NULL;
3718 MonoArray *modopts = NULL;
3719 MonoReflectionType *pt;
3721 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3722 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3723 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3724 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3726 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3727 if (!is_ok (&error))
3729 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3730 encode_reflection_type (assembly, pt, &buf, &error);
3731 if (!is_ok (&error))
3734 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3735 sigbuffer_free (&buf);
3739 sigbuffer_free (&buf);
3740 mono_error_raise_exception (&error); /* FIXME don't raise here */
3741 g_assert_not_reached ();
3745 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3748 MonoDynamicTable *table;
3751 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3752 idx = table->next_idx ++;
3754 alloc_table (table, table->rows);
3755 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3757 values [MONO_STAND_ALONE_SIGNATURE] =
3758 mono_reflection_encode_sighelper (assembly, helper);
3764 reflection_cc_to_file (int call_conv) {
3765 switch (call_conv & 0x3) {
3767 case 1: return MONO_CALL_DEFAULT;
3768 case 2: return MONO_CALL_VARARG;
3770 g_assert_not_reached ();
3774 #endif /* !DISABLE_REFLECTION_EMIT */
3778 MonoMethodSignature *sig;
3783 #ifndef DISABLE_REFLECTION_EMIT
3785 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3791 MonoMethodSignature *sig;
3795 name = mono_string_to_utf8 (m->name);
3796 nparams = mono_array_length (m->parameters);
3797 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3799 sig->sentinelpos = -1;
3800 sig->call_convention = reflection_cc_to_file (m->call_conv);
3801 sig->param_count = nparams;
3803 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3804 mono_error_raise_exception (&error); /* FIXME don't raise here */
3806 sig->ret = &mono_defaults.void_class->byval_arg;
3808 mtype = mono_reflection_type_get_handle (m->parent, &error);
3809 mono_error_raise_exception (&error); /* FIXME don't raise here */
3811 for (i = 0; i < nparams; ++i) {
3812 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3813 mono_error_raise_exception (&error); /* FIXME don't raise here */
3816 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3817 am = (ArrayMethod *)tmp->data;
3818 if (strcmp (name, am->name) == 0 &&
3819 mono_metadata_type_equal (am->parent, mtype) &&
3820 mono_metadata_signature_equal (am->sig, sig)) {
3823 m->table_idx = am->token & 0xffffff;
3827 am = g_new0 (ArrayMethod, 1);
3831 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3832 method_encode_signature (assembly, sig));
3833 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3834 m->table_idx = am->token & 0xffffff;
3839 * Insert into the metadata tables all the info about the TypeBuilder tb.
3840 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3843 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3845 MonoDynamicTable *table;
3847 int i, is_object = 0, is_system = 0;
3850 mono_error_init (error);
3852 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3853 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3854 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3855 n = mono_string_to_utf8 (tb->name);
3856 if (strcmp (n, "Object") == 0)
3858 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3860 n = mono_string_to_utf8 (tb->nspace);
3861 if (strcmp (n, "System") == 0)
3863 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3865 if (tb->parent && !(is_system && is_object) &&
3866 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3867 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3868 return_val_if_nok (error, FALSE);
3869 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3871 values [MONO_TYPEDEF_EXTENDS] = 0;
3873 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3874 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3877 * if we have explicitlayout or sequentiallayouts, output data in the
3878 * ClassLayout table.
3880 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3881 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3882 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3884 alloc_table (table, table->rows);
3885 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3886 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3887 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3888 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3891 /* handle interfaces */
3892 if (tb->interfaces) {
3893 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3895 table->rows += mono_array_length (tb->interfaces);
3896 alloc_table (table, table->rows);
3897 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3898 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3899 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3900 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3901 return_val_if_nok (error, FALSE);
3902 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3903 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3904 values += MONO_INTERFACEIMPL_SIZE;
3910 table = &assembly->tables [MONO_TABLE_FIELD];
3911 table->rows += tb->num_fields;
3912 alloc_table (table, table->rows);
3913 for (i = 0; i < tb->num_fields; ++i)
3914 mono_image_get_field_info (
3915 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3918 /* handle constructors */
3920 table = &assembly->tables [MONO_TABLE_METHOD];
3921 table->rows += mono_array_length (tb->ctors);
3922 alloc_table (table, table->rows);
3923 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3924 if (!mono_image_get_ctor_info (domain,
3925 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3931 /* handle methods */
3933 table = &assembly->tables [MONO_TABLE_METHOD];
3934 table->rows += tb->num_methods;
3935 alloc_table (table, table->rows);
3936 for (i = 0; i < tb->num_methods; ++i) {
3937 if (!mono_image_get_method_info (
3938 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3943 /* Do the same with properties etc.. */
3944 if (tb->events && mono_array_length (tb->events)) {
3945 table = &assembly->tables [MONO_TABLE_EVENT];
3946 table->rows += mono_array_length (tb->events);
3947 alloc_table (table, table->rows);
3948 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3950 alloc_table (table, table->rows);
3951 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3952 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3953 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3954 for (i = 0; i < mono_array_length (tb->events); ++i)
3955 mono_image_get_event_info (
3956 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3958 if (tb->properties && mono_array_length (tb->properties)) {
3959 table = &assembly->tables [MONO_TABLE_PROPERTY];
3960 table->rows += mono_array_length (tb->properties);
3961 alloc_table (table, table->rows);
3962 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3964 alloc_table (table, table->rows);
3965 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3966 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3967 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3968 for (i = 0; i < mono_array_length (tb->properties); ++i)
3969 mono_image_get_property_info (
3970 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3973 /* handle generic parameters */
3974 if (tb->generic_params) {
3975 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3976 table->rows += mono_array_length (tb->generic_params);
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3979 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3981 mono_image_get_generic_param_info (
3982 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3986 mono_image_add_decl_security (assembly,
3987 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3990 MonoDynamicTable *ntable;
3992 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3993 ntable->rows += mono_array_length (tb->subtypes);
3994 alloc_table (ntable, ntable->rows);
3995 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3997 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3998 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4000 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4001 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4002 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4003 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4004 mono_string_to_utf8 (tb->name), tb->table_idx,
4005 ntable->next_idx, ntable->rows);*/
4006 values += MONO_NESTED_CLASS_SIZE;
4016 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4020 mono_ptr_array_append (*types, type);
4022 if (!type->subtypes)
4025 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4026 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4027 collect_types (types, subtype);
4032 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4034 if ((*type1)->table_idx < (*type2)->table_idx)
4037 if ((*type1)->table_idx > (*type2)->table_idx)
4044 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4047 mono_error_init (error);
4050 for (i = 0; i < mono_array_length (pinfo); ++i) {
4051 MonoReflectionParamBuilder *pb;
4052 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4055 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4063 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4066 mono_error_init (error);
4068 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4071 for (i = 0; i < tb->num_fields; ++i) {
4072 MonoReflectionFieldBuilder* fb;
4073 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4074 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4079 for (i = 0; i < mono_array_length (tb->events); ++i) {
4080 MonoReflectionEventBuilder* eb;
4081 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4082 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4086 if (tb->properties) {
4087 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4088 MonoReflectionPropertyBuilder* pb;
4089 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4090 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4095 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4096 MonoReflectionCtorBuilder* cb;
4097 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4098 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4099 !params_add_cattrs (assembly, cb->pinfo, error))
4105 for (i = 0; i < tb->num_methods; ++i) {
4106 MonoReflectionMethodBuilder* mb;
4107 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4108 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4109 !params_add_cattrs (assembly, mb->pinfo, error))
4115 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4116 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4125 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4129 mono_error_init (error);
4131 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4134 if (moduleb->global_methods) {
4135 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4136 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4137 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4138 !params_add_cattrs (assembly, mb->pinfo, error))
4143 if (moduleb->global_fields) {
4144 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4145 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4146 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4151 if (moduleb->types) {
4152 for (i = 0; i < moduleb->num_types; ++i) {
4153 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4162 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4164 MonoDynamicTable *table;
4168 char *b = blob_size;
4171 table = &assembly->tables [MONO_TABLE_FILE];
4173 alloc_table (table, table->rows);
4174 values = table->values + table->next_idx * MONO_FILE_SIZE;
4175 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4176 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4177 if (image_is_dynamic (module->image)) {
4178 /* This depends on the fact that the main module is emitted last */
4179 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4180 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4183 path = g_strdup (module->image->name);
4185 mono_sha1_get_digest_from_file (path, hash);
4188 mono_metadata_encode_value (20, b, &b);
4189 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4190 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4195 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4197 MonoDynamicTable *table;
4200 table = &assembly->tables [MONO_TABLE_MODULE];
4201 mb->table_idx = table->next_idx ++;
4202 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4203 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4206 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4207 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4208 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4209 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4213 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4214 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4216 MonoDynamicTable *table;
4220 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4221 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4224 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4226 alloc_table (table, table->rows);
4227 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4229 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4230 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4231 if (klass->nested_in)
4232 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4234 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4235 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4236 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4238 res = table->next_idx;
4242 /* Emit nested types */
4243 if (klass->ext && klass->ext->nested_classes) {
4246 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4247 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4254 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4255 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4261 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4262 mono_error_raise_exception (&error); /* FIXME don't raise here */
4264 klass = mono_class_from_mono_type (t);
4266 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4268 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4269 parent_index, assembly);
4273 * We need to do this ourselves since klass->nested_classes is not set up.
4276 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4277 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4282 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4283 guint32 module_index, MonoDynamicImage *assembly)
4285 MonoImage *image = module->image;
4289 t = &image->tables [MONO_TABLE_TYPEDEF];
4291 for (i = 0; i < t->rows; ++i) {
4293 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4294 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4296 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4297 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4302 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4304 MonoDynamicTable *table;
4306 guint32 scope, scope_idx, impl, current_idx;
4307 gboolean forwarder = TRUE;
4308 gpointer iter = NULL;
4311 if (klass->nested_in) {
4312 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4315 scope = resolution_scope_from_image (assembly, klass->image);
4316 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4317 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4318 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4321 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4324 alloc_table (table, table->rows);
4325 current_idx = table->next_idx;
4326 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4328 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4329 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4330 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4331 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4332 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4336 while ((nested = mono_class_get_nested_types (klass, &iter)))
4337 add_exported_type (assemblyb, assembly, nested, current_idx);
4341 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4347 if (!assemblyb->type_forwarders)
4350 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4351 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4356 type = mono_reflection_type_get_handle (t, &error);
4357 mono_error_assert_ok (&error);
4360 klass = mono_class_from_mono_type (type);
4362 add_exported_type (assemblyb, assembly, klass, 0);
4366 #define align_pointer(base,p)\
4368 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4370 (p) += 4 - (__diff & 3);\
4374 compare_constants (const void *a, const void *b)
4376 const guint32 *a_values = (const guint32 *)a;
4377 const guint32 *b_values = (const guint32 *)b;
4378 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4382 compare_semantics (const void *a, const void *b)
4384 const guint32 *a_values = (const guint32 *)a;
4385 const guint32 *b_values = (const guint32 *)b;
4386 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4389 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4393 compare_custom_attrs (const void *a, const void *b)
4395 const guint32 *a_values = (const guint32 *)a;
4396 const guint32 *b_values = (const guint32 *)b;
4398 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4402 compare_field_marshal (const void *a, const void *b)
4404 const guint32 *a_values = (const guint32 *)a;
4405 const guint32 *b_values = (const guint32 *)b;
4407 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4411 compare_nested (const void *a, const void *b)
4413 const guint32 *a_values = (const guint32 *)a;
4414 const guint32 *b_values = (const guint32 *)b;
4416 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4420 compare_genericparam (const void *a, const void *b)
4423 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4424 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4426 if ((*b_entry)->owner == (*a_entry)->owner) {
4427 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4428 mono_error_assert_ok (&error);
4429 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4430 mono_error_assert_ok (&error);
4432 mono_type_get_generic_param_num (a_type) -
4433 mono_type_get_generic_param_num (b_type);
4435 return (*a_entry)->owner - (*b_entry)->owner;
4439 compare_declsecurity_attrs (const void *a, const void *b)
4441 const guint32 *a_values = (const guint32 *)a;
4442 const guint32 *b_values = (const guint32 *)b;
4444 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4448 compare_interface_impl (const void *a, const void *b)
4450 const guint32 *a_values = (const guint32 *)a;
4451 const guint32 *b_values = (const guint32 *)b;
4453 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4457 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4461 pad_heap (MonoDynamicStream *sh)
4463 if (sh->index & 3) {
4464 int sz = 4 - (sh->index & 3);
4465 memset (sh->data + sh->index, 0, sz);
4472 MonoDynamicStream *stream;
4476 * build_compressed_metadata() fills in the blob of data that represents the
4477 * raw metadata as it will be saved in the PE file. The five streams are output
4478 * and the metadata tables are comnpressed from the guint32 array representation,
4479 * to the compressed on-disk format.
4482 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4484 MonoDynamicTable *table;
4486 guint64 valid_mask = 0;
4487 guint64 sorted_mask;
4488 guint32 heapt_size = 0;
4489 guint32 meta_size = 256; /* allow for header and other stuff */
4490 guint32 table_offset;
4491 guint32 ntables = 0;
4497 struct StreamDesc stream_desc [5];
4499 mono_error_init (error);
4501 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4502 for (i = 0; i < assembly->gen_params->len; i++) {
4503 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4504 if (!write_generic_param_entry (assembly, entry, error))
4508 stream_desc [0].name = "#~";
4509 stream_desc [0].stream = &assembly->tstream;
4510 stream_desc [1].name = "#Strings";
4511 stream_desc [1].stream = &assembly->sheap;
4512 stream_desc [2].name = "#US";
4513 stream_desc [2].stream = &assembly->us;
4514 stream_desc [3].name = "#Blob";
4515 stream_desc [3].stream = &assembly->blob;
4516 stream_desc [4].name = "#GUID";
4517 stream_desc [4].stream = &assembly->guid;
4519 /* tables that are sorted */
4520 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4521 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4522 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4523 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4524 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4525 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4526 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4528 /* Compute table sizes */
4529 /* the MonoImage has already been created in mono_image_basic_init() */
4530 meta = &assembly->image;
4532 /* sizes should be multiple of 4 */
4533 pad_heap (&assembly->blob);
4534 pad_heap (&assembly->guid);
4535 pad_heap (&assembly->sheap);
4536 pad_heap (&assembly->us);
4538 /* Setup the info used by compute_sizes () */
4539 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4540 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4541 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4543 meta_size += assembly->blob.index;
4544 meta_size += assembly->guid.index;
4545 meta_size += assembly->sheap.index;
4546 meta_size += assembly->us.index;
4548 for (i=0; i < MONO_TABLE_NUM; ++i)
4549 meta->tables [i].rows = assembly->tables [i].rows;
4551 for (i = 0; i < MONO_TABLE_NUM; i++){
4552 if (meta->tables [i].rows == 0)
4554 valid_mask |= (guint64)1 << i;
4556 meta->tables [i].row_size = mono_metadata_compute_size (
4557 meta, i, &meta->tables [i].size_bitfield);
4558 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4560 heapt_size += 24; /* #~ header size */
4561 heapt_size += ntables * 4;
4562 /* make multiple of 4 */
4565 meta_size += heapt_size;
4566 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4567 p = (unsigned char*)meta->raw_metadata;
4568 /* the metadata signature */
4569 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4570 /* version numbers and 4 bytes reserved */
4571 int16val = (guint16*)p;
4572 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4573 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4575 /* version string */
4576 int32val = (guint32*)p;
4577 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4579 memcpy (p, meta->version, strlen (meta->version));
4580 p += GUINT32_FROM_LE (*int32val);
4581 align_pointer (meta->raw_metadata, p);
4582 int16val = (guint16*)p;
4583 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4584 *int16val = GUINT16_TO_LE (5); /* number of streams */
4588 * write the stream info.
4590 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4591 table_offset += 3; table_offset &= ~3;
4593 assembly->tstream.index = heapt_size;
4594 for (i = 0; i < 5; ++i) {
4595 int32val = (guint32*)p;
4596 stream_desc [i].stream->offset = table_offset;
4597 *int32val++ = GUINT32_TO_LE (table_offset);
4598 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4599 table_offset += GUINT32_FROM_LE (*int32val);
4600 table_offset += 3; table_offset &= ~3;
4602 strcpy ((char*)p, stream_desc [i].name);
4603 p += strlen (stream_desc [i].name) + 1;
4604 align_pointer (meta->raw_metadata, p);
4607 * now copy the data, the table stream header and contents goes first.
4609 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4610 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4611 int32val = (guint32*)p;
4612 *int32val = GUINT32_TO_LE (0); /* reserved */
4615 *p++ = 2; /* version */
4618 if (meta->idx_string_wide)
4620 if (meta->idx_guid_wide)
4622 if (meta->idx_blob_wide)
4625 *p++ = 1; /* reserved */
4626 int64val = (guint64*)p;
4627 *int64val++ = GUINT64_TO_LE (valid_mask);
4628 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4630 int32val = (guint32*)p;
4631 for (i = 0; i < MONO_TABLE_NUM; i++){
4632 if (meta->tables [i].rows == 0)
4634 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4636 p = (unsigned char*)int32val;
4638 /* sort the tables that still need sorting */
4639 table = &assembly->tables [MONO_TABLE_CONSTANT];
4641 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4642 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4644 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4645 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4647 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4648 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4650 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4651 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4653 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4654 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4655 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4657 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4658 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4660 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4662 /* compress the tables */
4663 for (i = 0; i < MONO_TABLE_NUM; i++){
4666 guint32 bitfield = meta->tables [i].size_bitfield;
4667 if (!meta->tables [i].rows)
4669 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4670 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4671 meta->tables [i].base = (char*)p;
4672 for (row = 1; row <= meta->tables [i].rows; ++row) {
4673 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4674 for (col = 0; col < assembly->tables [i].columns; ++col) {
4675 switch (mono_metadata_table_size (bitfield, col)) {
4677 *p++ = values [col];
4680 *p++ = values [col] & 0xff;
4681 *p++ = (values [col] >> 8) & 0xff;
4684 *p++ = values [col] & 0xff;
4685 *p++ = (values [col] >> 8) & 0xff;
4686 *p++ = (values [col] >> 16) & 0xff;
4687 *p++ = (values [col] >> 24) & 0xff;
4690 g_assert_not_reached ();
4694 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4697 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4698 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4699 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4700 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4701 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4703 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4709 * Some tables in metadata need to be sorted according to some criteria, but
4710 * when methods and fields are first created with reflection, they may be assigned a token
4711 * that doesn't correspond to the final token they will get assigned after the sorting.
4712 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4713 * with the reflection objects that represent them. Once all the tables are set up, the
4714 * reflection objects will contains the correct table index. fixup_method() will fixup the
4715 * tokens for the method with ILGenerator @ilgen.
4718 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4720 guint32 code_idx = GPOINTER_TO_UINT (value);
4721 MonoReflectionILTokenInfo *iltoken;
4722 MonoReflectionFieldBuilder *field;
4723 MonoReflectionCtorBuilder *ctor;
4724 MonoReflectionMethodBuilder *method;
4725 MonoReflectionTypeBuilder *tb;
4726 MonoReflectionArrayMethod *am;
4728 unsigned char *target;
4730 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4731 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4732 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4733 switch (target [3]) {
4734 case MONO_TABLE_FIELD:
4735 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4736 field = (MonoReflectionFieldBuilder *)iltoken->member;
4737 idx = field->table_idx;
4738 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4739 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4740 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4742 g_assert_not_reached ();
4745 case MONO_TABLE_METHOD:
4746 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4747 method = (MonoReflectionMethodBuilder *)iltoken->member;
4748 idx = method->table_idx;
4749 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4750 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4751 idx = ctor->table_idx;
4752 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4753 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4754 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4755 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4757 g_assert_not_reached ();
4760 case MONO_TABLE_TYPEDEF:
4761 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4762 g_assert_not_reached ();
4763 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4764 idx = tb->table_idx;
4766 case MONO_TABLE_MEMBERREF:
4767 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4768 am = (MonoReflectionArrayMethod*)iltoken->member;
4769 idx = am->table_idx;
4770 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4771 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4772 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4773 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4774 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4775 g_assert (m->klass->generic_class || m->klass->generic_container);
4777 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4779 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4780 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4781 g_assert (is_field_on_inst (f));
4783 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4784 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4786 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4788 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4790 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4793 g_assert_not_reached ();
4796 case MONO_TABLE_METHODSPEC:
4797 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4798 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4799 g_assert (mono_method_signature (m)->generic_param_count);
4801 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4803 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4806 g_assert_not_reached ();
4810 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4812 target [0] = idx & 0xff;
4813 target [1] = (idx >> 8) & 0xff;
4814 target [2] = (idx >> 16) & 0xff;
4821 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4822 * value is not known when the table is emitted.
4825 fixup_cattrs (MonoDynamicImage *assembly)
4827 MonoDynamicTable *table;
4829 guint32 type, i, idx, token;
4832 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4834 for (i = 0; i < table->rows; ++i) {
4835 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4837 type = values [MONO_CUSTOM_ATTR_TYPE];
4838 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4839 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4840 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4841 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4844 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4845 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4846 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4847 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4848 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4849 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4850 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4851 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4858 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4860 MonoDynamicTable *table;
4863 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4865 alloc_table (table, table->rows);
4866 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4867 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4868 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4869 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4870 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4875 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4877 MonoDynamicTable *table;
4881 char *b = blob_size;
4883 guint32 idx, offset;
4885 if (rsrc->filename) {
4886 name = mono_string_to_utf8 (rsrc->filename);
4887 sname = g_path_get_basename (name);
4889 table = &assembly->tables [MONO_TABLE_FILE];
4891 alloc_table (table, table->rows);
4892 values = table->values + table->next_idx * MONO_FILE_SIZE;
4893 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4894 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4897 mono_sha1_get_digest_from_file (name, hash);
4898 mono_metadata_encode_value (20, b, &b);
4899 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4900 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4902 idx = table->next_idx++;
4904 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4910 data = mono_array_addr (rsrc->data, char, 0);
4911 len = mono_array_length (rsrc->data);
4917 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4918 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4919 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4920 mono_image_add_stream_data (&assembly->resources, data, len);
4924 * The entry should be emitted into the MANIFESTRESOURCE table of
4925 * the main module, but that needs to reference the FILE table
4926 * which isn't emitted yet.
4933 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4937 set_version_from_string (MonoString *version, guint32 *values)
4939 gchar *ver, *p, *str;
4942 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4943 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4944 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4945 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4948 ver = str = mono_string_to_utf8 (version);
4949 for (i = 0; i < 4; ++i) {
4950 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4956 /* handle Revision and Build */
4966 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4970 char *b = blob_size;
4975 len = mono_array_length (pkey);
4976 mono_metadata_encode_value (len, b, &b);
4977 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4978 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4980 assembly->public_key = (guint8 *)g_malloc (len);
4981 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4982 assembly->public_key_len = len;
4984 /* Special case: check for ECMA key (16 bytes) */
4985 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4986 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4987 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4988 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4989 /* minimum key size (in 2.0) is 384 bits */
4990 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4992 /* FIXME - verifier */
4993 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4994 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4996 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5002 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5004 MonoDynamicTable *table;
5005 MonoDynamicImage *assembly;
5006 MonoReflectionAssemblyBuilder *assemblyb;
5010 guint32 module_index;
5012 assemblyb = moduleb->assemblyb;
5013 assembly = moduleb->dynamic_image;
5014 domain = mono_object_domain (assemblyb);
5016 /* Emit ASSEMBLY table */
5017 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5018 alloc_table (table, 1);
5019 values = table->values + MONO_ASSEMBLY_SIZE;
5020 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5021 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5022 if (assemblyb->culture) {
5023 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5025 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5027 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5028 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5029 set_version_from_string (assemblyb->version, values);
5031 /* Emit FILE + EXPORTED_TYPE table */
5033 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5035 MonoReflectionModuleBuilder *file_module =
5036 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5037 if (file_module != moduleb) {
5038 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5040 if (file_module->types) {
5041 for (j = 0; j < file_module->num_types; ++j) {
5042 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5043 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5048 if (assemblyb->loaded_modules) {
5049 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5050 MonoReflectionModule *file_module =
5051 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5052 mono_image_fill_file_table (domain, file_module, assembly);
5054 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5057 if (assemblyb->type_forwarders)
5058 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5060 /* Emit MANIFESTRESOURCE table */
5062 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5064 MonoReflectionModuleBuilder *file_module =
5065 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5066 /* The table for the main module is emitted later */
5067 if (file_module != moduleb) {
5069 if (file_module->resources) {
5070 int len = mono_array_length (file_module->resources);
5071 for (j = 0; j < len; ++j) {
5072 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5073 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5080 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5083 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5084 * for the modulebuilder @moduleb.
5085 * At the end of the process, method and field tokens are fixed up and the
5086 * on-disk compressed metadata representation is created.
5087 * Return TRUE on success, or FALSE on failure and sets @error
5090 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5092 MonoDynamicTable *table;
5093 MonoDynamicImage *assembly;
5094 MonoReflectionAssemblyBuilder *assemblyb;
5100 mono_error_init (error);
5102 assemblyb = moduleb->assemblyb;
5103 assembly = moduleb->dynamic_image;
5104 domain = mono_object_domain (assemblyb);
5106 if (assembly->text_rva)
5109 assembly->text_rva = START_TEXT_RVA;
5111 if (moduleb->is_main) {
5112 mono_image_emit_manifest (moduleb);
5115 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5116 table->rows = 1; /* .<Module> */
5118 alloc_table (table, table->rows);
5120 * Set the first entry.
5122 values = table->values + table->columns;
5123 values [MONO_TYPEDEF_FLAGS] = 0;
5124 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5125 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5126 values [MONO_TYPEDEF_EXTENDS] = 0;
5127 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5128 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5131 * handle global methods
5132 * FIXME: test what to do when global methods are defined in multiple modules.
5134 if (moduleb->global_methods) {
5135 table = &assembly->tables [MONO_TABLE_METHOD];
5136 table->rows += mono_array_length (moduleb->global_methods);
5137 alloc_table (table, table->rows);
5138 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5139 if (!mono_image_get_method_info (
5140 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5144 if (moduleb->global_fields) {
5145 table = &assembly->tables [MONO_TABLE_FIELD];
5146 table->rows += mono_array_length (moduleb->global_fields);
5147 alloc_table (table, table->rows);
5148 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5149 mono_image_get_field_info (
5150 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5153 table = &assembly->tables [MONO_TABLE_MODULE];
5154 alloc_table (table, 1);
5155 mono_image_fill_module_table (domain, moduleb, assembly);
5157 /* Collect all types into a list sorted by their table_idx */
5158 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5161 for (i = 0; i < moduleb->num_types; ++i) {
5162 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5163 collect_types (&types, type);
5166 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5167 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5168 table->rows += mono_ptr_array_size (types);
5169 alloc_table (table, table->rows);
5172 * Emit type names + namespaces at one place inside the string heap,
5173 * so load_class_names () needs to touch fewer pages.
5175 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5176 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5177 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5179 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5180 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5181 string_heap_insert_mstring (&assembly->sheap, tb->name);
5184 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5185 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5186 if (!mono_image_get_type_info (domain, type, assembly, error))
5191 * table->rows is already set above and in mono_image_fill_module_table.
5193 /* add all the custom attributes at the end, once all the indexes are stable */
5194 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5197 /* CAS assembly permissions */
5198 if (assemblyb->permissions_minimum)
5199 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5200 if (assemblyb->permissions_optional)
5201 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5202 if (assemblyb->permissions_refused)
5203 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5205 if (!module_add_cattrs (assembly, moduleb, error))
5209 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5211 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5212 * the final tokens and don't need another fixup pass. */
5214 if (moduleb->global_methods) {
5215 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5216 MonoReflectionMethodBuilder *mb = mono_array_get (
5217 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5218 if (!mono_image_add_methodimpl (assembly, mb, error))
5223 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5224 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5225 if (type->methods) {
5226 for (j = 0; j < type->num_methods; ++j) {
5227 MonoReflectionMethodBuilder *mb = mono_array_get (
5228 type->methods, MonoReflectionMethodBuilder*, j);
5230 if (!mono_image_add_methodimpl (assembly, mb, error))
5236 fixup_cattrs (assembly);
5239 mono_ptr_array_destroy (types);
5242 return mono_error_ok (error);
5245 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5248 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5250 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5253 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5257 guint32 import_lookup_table;
5261 guint32 import_address_table_rva;
5269 #ifndef DISABLE_REFLECTION_EMIT
5272 * mono_image_insert_string:
5273 * @module: module builder object
5276 * Insert @str into the user string stream of @module.
5279 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5281 MonoDynamicImage *assembly;
5286 if (!module->dynamic_image)
5287 mono_image_module_basic_init (module);
5289 assembly = module->dynamic_image;
5291 if (assembly->save) {
5292 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5293 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5294 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5296 char *swapped = g_malloc (2 * mono_string_length (str));
5297 const char *p = (const char*)mono_string_chars (str);
5299 swap_with_size (swapped, p, 2, mono_string_length (str));
5300 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5304 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5306 mono_image_add_stream_data (&assembly->us, "", 1);
5308 idx = assembly->us.index ++;
5311 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5313 return MONO_TOKEN_STRING | idx;
5317 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5321 MonoMethodSignature *sig;
5323 mono_error_init (error);
5325 klass = obj->vtable->klass;
5326 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5327 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5328 MonoMethodSignature *old;
5329 guint32 sig_token, parent;
5332 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5334 nargs = mono_array_length (opt_param_types);
5335 old = mono_method_signature (method);
5336 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5338 sig->hasthis = old->hasthis;
5339 sig->explicit_this = old->explicit_this;
5340 sig->call_convention = old->call_convention;
5341 sig->generic_param_count = old->generic_param_count;
5342 sig->param_count = old->param_count + nargs;
5343 sig->sentinelpos = old->param_count;
5344 sig->ret = old->ret;
5346 for (i = 0; i < old->param_count; i++)
5347 sig->params [i] = old->params [i];
5349 for (i = 0; i < nargs; i++) {
5350 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5351 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5352 if (!is_ok (error)) goto fail;
5355 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5356 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5357 parent >>= MONO_TYPEDEFORREF_BITS;
5359 parent <<= MONO_MEMBERREF_PARENT_BITS;
5360 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5362 sig_token = method_encode_signature (assembly, sig);
5363 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5364 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5365 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5366 ReflectionMethodBuilder rmb;
5367 guint32 parent, sig_token;
5368 int nopt_args, nparams, ngparams, i;
5370 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5373 rmb.opt_types = opt_param_types;
5374 nopt_args = mono_array_length (opt_param_types);
5376 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5377 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5378 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5380 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5381 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5382 sig->call_convention = rmb.call_conv;
5383 sig->generic_param_count = ngparams;
5384 sig->param_count = nparams + nopt_args;
5385 sig->sentinelpos = nparams;
5386 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5387 if (!is_ok (error)) goto fail;
5389 for (i = 0; i < nparams; i++) {
5390 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5391 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5392 if (!is_ok (error)) goto fail;
5395 for (i = 0; i < nopt_args; i++) {
5396 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5397 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5398 if (!is_ok (error)) goto fail;
5401 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5405 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5406 if (!mono_error_ok (error))
5408 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5410 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5411 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5413 char *name = mono_string_to_utf8 (rmb.name);
5414 token = mono_image_get_varargs_method_token (
5415 assembly, parent, name, sig_token);
5418 g_error ("requested method token for %s\n", klass->name);
5421 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5422 register_dyn_token (assembly, token, obj);
5425 g_assert (!mono_error_ok (error));
5430 * mono_image_create_token:
5431 * @assembly: a dynamic assembly
5433 * @register_token: Whenever to register the token in the assembly->tokens hash.
5435 * Get a token to insert in the IL code stream for the given MemberInfo.
5436 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5437 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5441 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5442 gboolean create_open_instance, gboolean register_token,
5448 mono_error_init (error);
5450 klass = obj->vtable->klass;
5452 /* Check for user defined reflection objects */
5453 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5454 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5455 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5459 if (strcmp (klass->name, "MethodBuilder") == 0) {
5460 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5461 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5463 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5464 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5466 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5467 if (!mono_error_ok (error))
5470 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5471 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5472 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5473 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5475 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5476 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5478 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5479 if (!mono_error_ok (error))
5482 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5483 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5484 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5485 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5486 if (tb->generic_params) {
5487 token = mono_image_get_generic_field_token (assembly, fb);
5489 if (tb->module->dynamic_image == assembly) {
5490 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5492 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5495 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5496 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5497 if (create_open_instance && tb->generic_params) {
5499 init_type_builder_generics (obj);
5500 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5501 return_val_if_nok (error, 0);
5502 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5503 token = mono_metadata_token_from_dor (token);
5504 } else if (tb->module->dynamic_image == assembly) {
5505 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5508 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5509 return_val_if_nok (error, 0);
5510 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5512 } else if (strcmp (klass->name, "MonoType") == 0) {
5513 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5514 return_val_if_nok (error, 0);
5515 MonoClass *mc = mono_class_from_mono_type (type);
5516 token = mono_metadata_token_from_dor (
5517 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5518 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5519 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5520 return_val_if_nok (error, 0);
5521 token = mono_metadata_token_from_dor (
5522 mono_image_typedef_or_ref (assembly, type));
5523 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5524 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5525 return_val_if_nok (error, 0);
5526 token = mono_metadata_token_from_dor (
5527 mono_image_typedef_or_ref (assembly, type));
5528 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5529 strcmp (klass->name, "MonoMethod") == 0 ||
5530 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5531 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5532 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5533 if (m->method->is_inflated) {
5534 if (create_open_instance)
5535 token = mono_image_get_methodspec_token (assembly, m->method);
5537 token = mono_image_get_inflated_method_token (assembly, m->method);
5538 } else if ((m->method->klass->image == &assembly->image) &&
5539 !m->method->klass->generic_class) {
5540 static guint32 method_table_idx = 0xffffff;
5541 if (m->method->klass->wastypebuilder) {
5542 /* we use the same token as the one that was assigned
5543 * to the Methodbuilder.
5544 * FIXME: do the equivalent for Fields.
5546 token = m->method->token;
5549 * Each token should have a unique index, but the indexes are
5550 * assigned by managed code, so we don't know about them. An
5551 * easy solution is to count backwards...
5553 method_table_idx --;
5554 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5557 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5559 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5560 } else if (strcmp (klass->name, "MonoField") == 0) {
5561 MonoReflectionField *f = (MonoReflectionField *)obj;
5562 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5563 static guint32 field_table_idx = 0xffffff;
5565 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5567 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5569 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5570 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5571 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5572 token = mono_image_get_array_token (assembly, m);
5573 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5574 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5575 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5576 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5577 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5578 return_val_if_nok (error, 0);
5579 token = mono_metadata_token_from_dor (
5580 mono_image_typedef_or_ref (assembly, type));
5581 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5582 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5583 token = mono_image_get_field_on_inst_token (assembly, f);
5584 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5585 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5586 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5587 if (!mono_error_ok (error))
5589 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5590 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5591 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5592 if (!mono_error_ok (error))
5594 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5595 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5596 return_val_if_nok (error, 0);
5597 token = mono_metadata_token_from_dor (
5598 mono_image_typedef_or_ref (assembly, type));
5600 g_error ("requested token for %s\n", klass->name);
5604 mono_image_register_token (assembly, token, obj);
5610 * mono_image_register_token:
5612 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5613 * the Module.ResolveXXXToken () methods to work.
5616 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5620 dynamic_image_lock (assembly);
5621 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5623 /* There could be multiple MethodInfo objects with the same token */
5624 //g_assert (prev == obj);
5626 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5628 dynamic_image_unlock (assembly);
5631 static MonoDynamicImage*
5632 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5634 static const guchar entrycode [16] = {0xff, 0x25, 0};
5635 MonoDynamicImage *image;
5638 const char *version;
5640 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5641 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5643 version = mono_get_runtime_info ()->runtime_version;
5646 /* The MonoGHashTable's need GC tracking */
5647 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5649 image = g_new0 (MonoDynamicImage, 1);
5652 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5654 /*g_print ("created image %p\n", image);*/
5655 /* keep in sync with image.c */
5656 image->image.name = assembly_name;
5657 image->image.assembly_name = image->image.name; /* they may be different */
5658 image->image.module_name = module_name;
5659 image->image.version = g_strdup (version);
5660 image->image.md_version_major = 1;
5661 image->image.md_version_minor = 1;
5662 image->image.dynamic = TRUE;
5664 image->image.references = g_new0 (MonoAssembly*, 1);
5665 image->image.references [0] = NULL;
5667 mono_image_init (&image->image);
5669 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");
5670 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5671 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5672 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5673 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5674 image->handleref = g_hash_table_new (NULL, NULL);
5675 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");
5676 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5677 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");
5678 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");
5679 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5680 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5681 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5682 image->gen_params = g_ptr_array_new ();
5683 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5685 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5686 string_heap_init (&image->sheap);
5687 mono_image_add_stream_data (&image->us, "", 1);
5688 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5689 /* import tables... */
5690 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5691 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5692 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5693 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5694 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5695 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5696 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5697 stream_data_align (&image->code);
5699 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5701 for (i=0; i < MONO_TABLE_NUM; ++i) {
5702 image->tables [i].next_idx = 1;
5703 image->tables [i].columns = table_sizes [i];
5706 image->image.assembly = (MonoAssembly*)assembly;
5707 image->run = assembly->run;
5708 image->save = assembly->save;
5709 image->pe_kind = 0x1; /* ILOnly */
5710 image->machine = 0x14c; /* I386 */
5712 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5714 dynamic_images_lock ();
5716 if (!dynamic_images)
5717 dynamic_images = g_ptr_array_new ();
5719 g_ptr_array_add (dynamic_images, image);
5721 dynamic_images_unlock ();
5728 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5734 release_hashtable (MonoGHashTable **hash)
5737 mono_g_hash_table_destroy (*hash);
5743 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5745 release_hashtable (&image->token_fixups);
5746 release_hashtable (&image->handleref_managed);
5747 release_hashtable (&image->tokens);
5748 release_hashtable (&image->remapped_tokens);
5749 release_hashtable (&image->generic_def_objects);
5750 release_hashtable (&image->methodspec);
5753 // Free dynamic image pass one: Free resources but not image itself
5755 mono_dynamic_image_free (MonoDynamicImage *image)
5757 MonoDynamicImage *di = image;
5762 mono_g_hash_table_destroy (di->methodspec);
5764 g_hash_table_destroy (di->typespec);
5766 g_hash_table_destroy (di->typeref);
5768 g_hash_table_destroy (di->handleref);
5769 if (di->handleref_managed)
5770 mono_g_hash_table_destroy (di->handleref_managed);
5772 mono_g_hash_table_destroy (di->tokens);
5773 if (di->remapped_tokens)
5774 mono_g_hash_table_destroy (di->remapped_tokens);
5775 if (di->generic_def_objects)
5776 mono_g_hash_table_destroy (di->generic_def_objects);
5777 if (di->blob_cache) {
5778 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5779 g_hash_table_destroy (di->blob_cache);
5781 if (di->standalonesig_cache)
5782 g_hash_table_destroy (di->standalonesig_cache);
5783 for (list = di->array_methods; list; list = list->next) {
5784 ArrayMethod *am = (ArrayMethod *)list->data;
5789 g_list_free (di->array_methods);
5790 if (di->gen_params) {
5791 for (i = 0; i < di->gen_params->len; i++) {
5792 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5793 mono_gc_deregister_root ((char*) &entry->gparam);
5796 g_ptr_array_free (di->gen_params, TRUE);
5798 if (di->token_fixups)
5799 mono_g_hash_table_destroy (di->token_fixups);
5800 if (di->method_to_table_idx)
5801 g_hash_table_destroy (di->method_to_table_idx);
5802 if (di->field_to_table_idx)
5803 g_hash_table_destroy (di->field_to_table_idx);
5804 if (di->method_aux_hash)
5805 g_hash_table_destroy (di->method_aux_hash);
5806 if (di->vararg_aux_hash)
5807 g_hash_table_destroy (di->vararg_aux_hash);
5808 g_free (di->strong_name);
5809 g_free (di->win32_res);
5811 g_free (di->public_key);
5813 /*g_print ("string heap destroy for image %p\n", di);*/
5814 mono_dynamic_stream_reset (&di->sheap);
5815 mono_dynamic_stream_reset (&di->code);
5816 mono_dynamic_stream_reset (&di->resources);
5817 mono_dynamic_stream_reset (&di->us);
5818 mono_dynamic_stream_reset (&di->blob);
5819 mono_dynamic_stream_reset (&di->tstream);
5820 mono_dynamic_stream_reset (&di->guid);
5821 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5822 g_free (di->tables [i].values);
5825 dynamic_images_lock ();
5828 g_ptr_array_remove (dynamic_images, di);
5830 dynamic_images_unlock ();
5833 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5835 mono_dynamic_image_free_image (MonoDynamicImage *image)
5837 /* See create_dynamic_mono_image () */
5839 /* Allocated using GC_MALLOC */
5845 #ifndef DISABLE_REFLECTION_EMIT
5848 * mono_image_basic_init:
5849 * @assembly: an assembly builder object
5851 * Create the MonoImage that represents the assembly builder and setup some
5852 * of the helper hash table and the basic metadata streams.
5855 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5857 MonoDynamicAssembly *assembly;
5858 MonoDynamicImage *image;
5859 MonoDomain *domain = mono_object_domain (assemblyb);
5861 if (assemblyb->dynamic_assembly)
5865 /* assembly->assembly.image might be GC allocated */
5866 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5868 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5871 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5873 assembly->assembly.ref_count = 1;
5874 assembly->assembly.dynamic = TRUE;
5875 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5876 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5877 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5878 if (assemblyb->culture)
5879 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5881 assembly->assembly.aname.culture = g_strdup ("");
5883 if (assemblyb->version) {
5884 char *vstr = mono_string_to_utf8 (assemblyb->version);
5885 char **version = g_strsplit (vstr, ".", 4);
5886 char **parts = version;
5887 assembly->assembly.aname.major = atoi (*parts++);
5888 assembly->assembly.aname.minor = atoi (*parts++);
5889 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5890 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5892 g_strfreev (version);
5895 assembly->assembly.aname.major = 0;
5896 assembly->assembly.aname.minor = 0;
5897 assembly->assembly.aname.build = 0;
5898 assembly->assembly.aname.revision = 0;
5901 assembly->run = assemblyb->access != 2;
5902 assembly->save = assemblyb->access != 1;
5903 assembly->domain = domain;
5905 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5906 image->initial_image = TRUE;
5907 assembly->assembly.aname.name = image->image.name;
5908 assembly->assembly.image = &image->image;
5909 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5910 /* -1 to correct for the trailing NULL byte */
5911 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5912 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5914 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5917 mono_domain_assemblies_lock (domain);
5918 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5919 mono_domain_assemblies_unlock (domain);
5921 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5923 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5925 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5928 #endif /* !DISABLE_REFLECTION_EMIT */
5930 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5933 calc_section_size (MonoDynamicImage *assembly)
5937 /* alignment constraints */
5938 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5939 g_assert ((assembly->code.index % 4) == 0);
5940 assembly->meta_size += 3;
5941 assembly->meta_size &= ~3;
5942 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5943 g_assert ((assembly->resources.index % 4) == 0);
5945 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5946 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5949 if (assembly->win32_res) {
5950 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5952 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5953 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5957 assembly->sections [MONO_SECTION_RELOC].size = 12;
5958 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5968 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5972 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5974 ResTreeNode *t1 = (ResTreeNode*)a;
5975 ResTreeNode *t2 = (ResTreeNode*)b;
5977 return t1->id - t2->id;
5981 * resource_tree_create:
5983 * Organize the resources into a resource tree.
5985 static ResTreeNode *
5986 resource_tree_create (MonoArray *win32_resources)
5988 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5992 tree = g_new0 (ResTreeNode, 1);
5994 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5995 MonoReflectionWin32Resource *win32_res =
5996 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6000 /* FIXME: BUG: this stores managed references in unmanaged memory */
6001 lang_node = g_new0 (ResTreeNode, 1);
6002 lang_node->id = win32_res->lang_id;
6003 lang_node->win32_res = win32_res;
6005 /* Create type node if neccesary */
6007 for (l = tree->children; l; l = l->next)
6008 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6009 type_node = (ResTreeNode*)l->data;
6014 type_node = g_new0 (ResTreeNode, 1);
6015 type_node->id = win32_res->res_type;
6018 * The resource types have to be sorted otherwise
6019 * Windows Explorer can't display the version information.
6021 tree->children = g_slist_insert_sorted (tree->children,
6022 type_node, resource_tree_compare_by_id);
6025 /* Create res node if neccesary */
6027 for (l = type_node->children; l; l = l->next)
6028 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6029 res_node = (ResTreeNode*)l->data;
6034 res_node = g_new0 (ResTreeNode, 1);
6035 res_node->id = win32_res->res_id;
6036 type_node->children = g_slist_append (type_node->children, res_node);
6039 res_node->children = g_slist_append (res_node->children, lang_node);
6046 * resource_tree_encode:
6048 * Encode the resource tree into the format used in the PE file.
6051 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6054 MonoPEResourceDir dir;
6055 MonoPEResourceDirEntry dir_entry;
6056 MonoPEResourceDataEntry data_entry;
6058 guint32 res_id_entries;
6061 * For the format of the resource directory, see the article
6062 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6066 memset (&dir, 0, sizeof (dir));
6067 memset (&dir_entry, 0, sizeof (dir_entry));
6068 memset (&data_entry, 0, sizeof (data_entry));
6070 g_assert (sizeof (dir) == 16);
6071 g_assert (sizeof (dir_entry) == 8);
6072 g_assert (sizeof (data_entry) == 16);
6074 node->offset = p - begin;
6076 /* IMAGE_RESOURCE_DIRECTORY */
6077 res_id_entries = g_slist_length (node->children);
6078 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6080 memcpy (p, &dir, sizeof (dir));
6083 /* Reserve space for entries */
6085 p += sizeof (dir_entry) * res_id_entries;
6087 /* Write children */
6088 for (l = node->children; l; l = l->next) {
6089 ResTreeNode *child = (ResTreeNode*)l->data;
6091 if (child->win32_res) {
6094 child->offset = p - begin;
6096 /* IMAGE_RESOURCE_DATA_ENTRY */
6097 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6098 size = mono_array_length (child->win32_res->res_data);
6099 data_entry.rde_size = GUINT32_TO_LE (size);
6101 memcpy (p, &data_entry, sizeof (data_entry));
6102 p += sizeof (data_entry);
6104 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6107 resource_tree_encode (child, begin, p, &p);
6111 /* IMAGE_RESOURCE_ENTRY */
6112 for (l = node->children; l; l = l->next) {
6113 ResTreeNode *child = (ResTreeNode*)l->data;
6115 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6116 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6118 memcpy (entries, &dir_entry, sizeof (dir_entry));
6119 entries += sizeof (dir_entry);
6126 resource_tree_free (ResTreeNode * node)
6129 for (list = node->children; list; list = list->next)
6130 resource_tree_free ((ResTreeNode*)list->data);
6131 g_slist_free(node->children);
6136 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6141 MonoReflectionWin32Resource *win32_res;
6144 if (!assemblyb->win32_resources)
6148 * Resources are stored in a three level tree inside the PE file.
6149 * - level one contains a node for each type of resource
6150 * - level two contains a node for each resource
6151 * - level three contains a node for each instance of a resource for a
6152 * specific language.
6155 tree = resource_tree_create (assemblyb->win32_resources);
6157 /* Estimate the size of the encoded tree */
6159 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6160 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6161 size += mono_array_length (win32_res->res_data);
6163 /* Directory structure */
6164 size += mono_array_length (assemblyb->win32_resources) * 256;
6165 p = buf = (char *)g_malloc (size);
6167 resource_tree_encode (tree, p, p, &p);
6169 g_assert (p - buf <= size);
6171 assembly->win32_res = (char *)g_malloc (p - buf);
6172 assembly->win32_res_size = p - buf;
6173 memcpy (assembly->win32_res, buf, p - buf);
6176 resource_tree_free (tree);
6180 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6182 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6185 p += sizeof (MonoPEResourceDir);
6186 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6187 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6188 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6189 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6190 fixup_resource_directory (res_section, child, rva);
6192 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6193 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6196 p += sizeof (MonoPEResourceDirEntry);
6201 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6204 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6205 g_error ("WriteFile returned %d\n", GetLastError ());
6209 * mono_image_create_pefile:
6210 * @mb: a module builder object
6212 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6213 * assembly->pefile where it can be easily retrieved later in chunks.
6216 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6218 MonoMSDOSHeader *msdos;
6219 MonoDotNetHeader *header;
6220 MonoSectionTable *section;
6221 MonoCLIHeader *cli_header;
6222 guint32 size, image_size, virtual_base, text_offset;
6223 guint32 header_start, section_start, file_offset, virtual_offset;
6224 MonoDynamicImage *assembly;
6225 MonoReflectionAssemblyBuilder *assemblyb;
6226 MonoDynamicStream pefile_stream = {0};
6227 MonoDynamicStream *pefile = &pefile_stream;
6229 guint32 *rva, value;
6231 static const unsigned char msheader[] = {
6232 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6233 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6236 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6237 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6238 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6239 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6242 mono_error_init (error);
6244 assemblyb = mb->assemblyb;
6246 mono_image_basic_init (assemblyb);
6247 assembly = mb->dynamic_image;
6249 assembly->pe_kind = assemblyb->pe_kind;
6250 assembly->machine = assemblyb->machine;
6251 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6252 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6254 if (!mono_image_build_metadata (mb, error))
6258 if (mb->is_main && assemblyb->resources) {
6259 int len = mono_array_length (assemblyb->resources);
6260 for (i = 0; i < len; ++i)
6261 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6264 if (mb->resources) {
6265 int len = mono_array_length (mb->resources);
6266 for (i = 0; i < len; ++i)
6267 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6270 if (!build_compressed_metadata (assembly, error))
6274 assembly_add_win32_resources (assembly, assemblyb);
6276 nsections = calc_section_size (assembly);
6278 /* The DOS header and stub */
6279 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6280 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6282 /* the dotnet header */
6283 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6285 /* the section tables */
6286 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6288 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6289 virtual_offset = VIRT_ALIGN;
6292 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6293 if (!assembly->sections [i].size)
6296 file_offset += FILE_ALIGN - 1;
6297 file_offset &= ~(FILE_ALIGN - 1);
6298 virtual_offset += VIRT_ALIGN - 1;
6299 virtual_offset &= ~(VIRT_ALIGN - 1);
6301 assembly->sections [i].offset = file_offset;
6302 assembly->sections [i].rva = virtual_offset;
6304 file_offset += assembly->sections [i].size;
6305 virtual_offset += assembly->sections [i].size;
6306 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6309 file_offset += FILE_ALIGN - 1;
6310 file_offset &= ~(FILE_ALIGN - 1);
6312 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6314 /* back-patch info */
6315 msdos = (MonoMSDOSHeader*)pefile->data;
6316 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6318 header = (MonoDotNetHeader*)(pefile->data + header_start);
6319 header->pesig [0] = 'P';
6320 header->pesig [1] = 'E';
6322 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6323 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6324 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6325 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6326 if (assemblyb->pekind == 1) {
6328 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6331 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6334 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6336 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6337 header->pe.pe_major = 6;
6338 header->pe.pe_minor = 0;
6339 size = assembly->sections [MONO_SECTION_TEXT].size;
6340 size += FILE_ALIGN - 1;
6341 size &= ~(FILE_ALIGN - 1);
6342 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6343 size = assembly->sections [MONO_SECTION_RSRC].size;
6344 size += FILE_ALIGN - 1;
6345 size &= ~(FILE_ALIGN - 1);
6346 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6347 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6348 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6349 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6350 /* pe_rva_entry_point always at the beginning of the text section */
6351 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6353 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6354 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6355 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6356 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6357 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6358 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6359 size = section_start;
6360 size += FILE_ALIGN - 1;
6361 size &= ~(FILE_ALIGN - 1);
6362 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6364 size += VIRT_ALIGN - 1;
6365 size &= ~(VIRT_ALIGN - 1);
6366 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6369 // Translate the PEFileKind value to the value expected by the Windows loader
6375 // PEFileKinds.Dll == 1
6376 // PEFileKinds.ConsoleApplication == 2
6377 // PEFileKinds.WindowApplication == 3
6380 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6381 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6383 if (assemblyb->pekind == 3)
6388 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6390 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6391 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6392 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6393 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6394 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6395 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6397 /* fill data directory entries */
6399 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6400 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6402 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6403 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6405 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6406 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6407 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6408 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6409 /* patch entrypoint name */
6410 if (assemblyb->pekind == 1)
6411 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6413 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6414 /* patch imported function RVA name */
6415 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6416 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6418 /* the import table */
6419 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6420 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6421 /* patch imported dll RVA name and other entries in the dir */
6422 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6423 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6424 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6425 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6426 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6427 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6429 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6430 value = (assembly->text_rva + assembly->imp_names_offset);
6431 *p++ = (value) & 0xff;
6432 *p++ = (value >> 8) & (0xff);
6433 *p++ = (value >> 16) & (0xff);
6434 *p++ = (value >> 24) & (0xff);
6436 /* the CLI header info */
6437 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6438 cli_header->ch_size = GUINT32_FROM_LE (72);
6439 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6440 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6441 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6442 if (assemblyb->entry_point) {
6443 guint32 table_idx = 0;
6444 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6445 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6446 table_idx = methodb->table_idx;
6448 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6450 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6452 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6454 /* The embedded managed resources */
6455 text_offset = assembly->text_rva + assembly->code.index;
6456 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6457 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6458 text_offset += assembly->resources.index;
6459 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6460 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6461 text_offset += assembly->meta_size;
6462 if (assembly->strong_name_size) {
6463 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6464 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6465 text_offset += assembly->strong_name_size;
6468 /* write the section tables and section content */
6469 section = (MonoSectionTable*)(pefile->data + section_start);
6470 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6471 static const char section_names [][7] = {
6472 ".text", ".rsrc", ".reloc"
6474 if (!assembly->sections [i].size)
6476 strcpy (section->st_name, section_names [i]);
6477 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6478 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6479 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6480 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6481 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6482 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6483 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6487 checked_write_file (file, pefile->data, pefile->index);
6489 mono_dynamic_stream_reset (pefile);
6491 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6492 if (!assembly->sections [i].size)
6495 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6496 g_error ("SetFilePointer returned %d\n", GetLastError ());
6499 case MONO_SECTION_TEXT:
6500 /* patch entry point */
6501 p = (guchar*)(assembly->code.data + 2);
6502 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6503 *p++ = (value) & 0xff;
6504 *p++ = (value >> 8) & 0xff;
6505 *p++ = (value >> 16) & 0xff;
6506 *p++ = (value >> 24) & 0xff;
6508 checked_write_file (file, assembly->code.data, assembly->code.index);
6509 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6510 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6511 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6514 g_free (assembly->image.raw_metadata);
6516 case MONO_SECTION_RELOC: {
6520 guint16 type_and_offset;
6524 g_assert (sizeof (reloc) == 12);
6526 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6527 reloc.block_size = GUINT32_FROM_LE (12);
6530 * the entrypoint is always at the start of the text section
6531 * 3 is IMAGE_REL_BASED_HIGHLOW
6532 * 2 is patch_size_rva - text_rva
6534 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6537 checked_write_file (file, &reloc, sizeof (reloc));
6541 case MONO_SECTION_RSRC:
6542 if (assembly->win32_res) {
6544 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6545 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6546 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6550 g_assert_not_reached ();
6554 /* check that the file is properly padded */
6555 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6556 g_error ("SetFilePointer returned %d\n", GetLastError ());
6557 if (! SetEndOfFile (file))
6558 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6560 mono_dynamic_stream_reset (&assembly->code);
6561 mono_dynamic_stream_reset (&assembly->us);
6562 mono_dynamic_stream_reset (&assembly->blob);
6563 mono_dynamic_stream_reset (&assembly->guid);
6564 mono_dynamic_stream_reset (&assembly->sheap);
6566 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6567 g_hash_table_destroy (assembly->blob_cache);
6568 assembly->blob_cache = NULL;
6573 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6576 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6578 g_assert_not_reached ();
6581 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6583 #ifndef DISABLE_REFLECTION_EMIT
6585 MonoReflectionModule *
6586 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6589 MonoReflectionModule *result = NULL;
6592 MonoImageOpenStatus status;
6593 MonoDynamicAssembly *assembly;
6594 guint32 module_count;
6595 MonoImage **new_modules;
6596 gboolean *new_modules_loaded;
6598 name = mono_string_to_utf8 (fileName);
6600 image = mono_image_open (name, &status);
6603 if (status == MONO_IMAGE_ERROR_ERRNO)
6604 exc = mono_get_exception_file_not_found (fileName);
6606 exc = mono_get_exception_bad_image_format (name);
6608 mono_raise_exception (exc);
6613 assembly = ab->dynamic_assembly;
6614 image->assembly = (MonoAssembly*)assembly;
6616 module_count = image->assembly->image->module_count;
6617 new_modules = g_new0 (MonoImage *, module_count + 1);
6618 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6620 if (image->assembly->image->modules)
6621 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6622 if (image->assembly->image->modules_loaded)
6623 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6624 new_modules [module_count] = image;
6625 new_modules_loaded [module_count] = TRUE;
6626 mono_image_addref (image);
6628 g_free (image->assembly->image->modules);
6629 image->assembly->image->modules = new_modules;
6630 image->assembly->image->modules_loaded = new_modules_loaded;
6631 image->assembly->image->module_count ++;
6633 mono_assembly_load_references (image, &status);
6635 mono_image_close (image);
6636 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6639 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6640 mono_error_raise_exception (&error); /* FIXME don't raise here */
6644 #endif /* DISABLE_REFLECTION_EMIT */
6647 * We need to return always the same object for MethodInfo, FieldInfo etc..
6648 * but we need to consider the reflected type.
6649 * type uses a different hash, since it uses custom hash/equal functions.
6654 MonoClass *refclass;
6658 reflected_equal (gconstpointer a, gconstpointer b) {
6659 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6660 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6662 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6666 reflected_hash (gconstpointer a) {
6667 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6668 return mono_aligned_addr_hash (ea->item);
6671 #define CHECK_OBJECT(t,p,k) \
6677 mono_domain_lock (domain); \
6678 if (!domain->refobject_hash) \
6679 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"); \
6680 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6681 mono_domain_unlock (domain); \
6684 mono_domain_unlock (domain); \
6687 #ifdef HAVE_BOEHM_GC
6688 /* ReflectedEntry doesn't need to be GC tracked */
6689 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6690 #define FREE_REFENTRY(entry) g_free ((entry))
6691 #define REFENTRY_REQUIRES_CLEANUP
6693 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6695 #define FREE_REFENTRY(entry)
6698 #define CACHE_OBJECT(t,p,o,k) \
6701 ReflectedEntry pe; \
6703 pe.refclass = (k); \
6704 mono_domain_lock (domain); \
6705 if (!domain->refobject_hash) \
6706 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"); \
6707 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6709 ReflectedEntry *e = ALLOC_REFENTRY; \
6711 e->refclass = (k); \
6712 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6715 mono_domain_unlock (domain); \
6720 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6722 mono_domain_lock (domain);
6723 if (domain->refobject_hash) {
6725 gpointer orig_pe, orig_value;
6728 pe.refclass = klass;
6729 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6730 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6731 FREE_REFENTRY (orig_pe);
6734 mono_domain_unlock (domain);
6737 #ifdef REFENTRY_REQUIRES_CLEANUP
6739 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6741 FREE_REFENTRY (key);
6746 mono_reflection_cleanup_domain (MonoDomain *domain)
6748 if (domain->refobject_hash) {
6749 /*let's avoid scanning the whole hashtable if not needed*/
6750 #ifdef REFENTRY_REQUIRES_CLEANUP
6751 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6753 mono_g_hash_table_destroy (domain->refobject_hash);
6754 domain->refobject_hash = NULL;
6758 #ifndef DISABLE_REFLECTION_EMIT
6760 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6762 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6766 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6768 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6772 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6774 MonoDynamicImage *image = moduleb->dynamic_image;
6775 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6779 MonoImage **new_modules;
6781 char *name, *fqname;
6783 * FIXME: we already created an image in mono_image_basic_init (), but
6784 * we don't know which module it belongs to, since that is only
6785 * determined at assembly save time.
6787 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6788 name = mono_string_to_utf8 (ab->name);
6789 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6790 if (!mono_error_ok (&error)) {
6792 mono_error_raise_exception (&error);
6794 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6796 moduleb->module.image = &image->image;
6797 moduleb->dynamic_image = image;
6798 register_module (mono_object_domain (moduleb), moduleb, image);
6800 /* register the module with the assembly */
6801 ass = ab->dynamic_assembly->assembly.image;
6802 module_count = ass->module_count;
6803 new_modules = g_new0 (MonoImage *, module_count + 1);
6806 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6807 new_modules [module_count] = &image->image;
6808 mono_image_addref (&image->image);
6810 g_free (ass->modules);
6811 ass->modules = new_modules;
6812 ass->module_count ++;
6817 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6819 MonoDynamicImage *image = moduleb->dynamic_image;
6821 g_assert (type->type);
6822 image->wrappers_type = mono_class_from_mono_type (type->type);
6828 * mono_assembly_get_object:
6829 * @domain: an app domain
6830 * @assembly: an assembly
6832 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6834 MonoReflectionAssembly*
6835 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6838 MonoReflectionAssembly *result;
6839 result = mono_assembly_get_object_checked (domain, assembly, &error);
6840 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6844 * mono_assembly_get_object_checked:
6845 * @domain: an app domain
6846 * @assembly: an assembly
6848 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6850 MonoReflectionAssembly*
6851 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6853 MonoReflectionAssembly *res;
6855 mono_error_init (error);
6857 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6858 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6861 res->assembly = assembly;
6863 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6868 MonoReflectionModule*
6869 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6872 MonoReflectionModule *result;
6873 result = mono_module_get_object_checked (domain, image, &error);
6874 mono_error_raise_exception (&error);
6878 MonoReflectionModule*
6879 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6881 MonoReflectionModule *res;
6884 mono_error_init (error);
6885 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6886 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6891 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6894 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6896 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6897 basename = g_path_get_basename (image->name);
6898 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6899 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6903 if (image->assembly->image == image) {
6904 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6908 if (image->assembly->image->modules) {
6909 for (i = 0; i < image->assembly->image->module_count; i++) {
6910 if (image->assembly->image->modules [i] == image)
6911 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6913 g_assert (res->token);
6917 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6920 MonoReflectionModule*
6921 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6924 MonoReflectionModule *result;
6925 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6926 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6930 MonoReflectionModule*
6931 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6933 MonoReflectionModule *res;
6934 MonoTableInfo *table;
6935 guint32 cols [MONO_FILE_SIZE];
6937 guint32 i, name_idx;
6940 mono_error_init (error);
6942 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6946 table = &image->tables [MONO_TABLE_FILE];
6947 g_assert (table_index < table->rows);
6948 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6951 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6954 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6955 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6957 /* Check whenever the row has a corresponding row in the moduleref table */
6958 table = &image->tables [MONO_TABLE_MODULEREF];
6959 for (i = 0; i < table->rows; ++i) {
6960 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6961 val = mono_metadata_string_heap (image, name_idx);
6962 if (strcmp (val, name) == 0)
6963 res->image = image->modules [i];
6966 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6967 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6968 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6969 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6970 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6976 verify_safe_for_managed_space (MonoType *type)
6978 switch (type->type) {
6980 case MONO_TYPE_ARRAY:
6981 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6983 return verify_safe_for_managed_space (type->data.type);
6984 case MONO_TYPE_SZARRAY:
6985 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6986 case MONO_TYPE_GENERICINST: {
6987 MonoGenericInst *inst = type->data.generic_class->inst;
6991 for (i = 0; i < inst->type_argc; ++i)
6992 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6998 case MONO_TYPE_MVAR:
7006 mono_type_normalize (MonoType *type)
7009 MonoGenericClass *gclass;
7010 MonoGenericInst *ginst;
7012 MonoGenericContainer *gcontainer;
7013 MonoType **argv = NULL;
7014 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7016 if (type->type != MONO_TYPE_GENERICINST)
7019 gclass = type->data.generic_class;
7020 ginst = gclass->context.class_inst;
7021 if (!ginst->is_open)
7024 gtd = gclass->container_class;
7025 gcontainer = gtd->generic_container;
7026 argv = g_newa (MonoType*, ginst->type_argc);
7028 for (i = 0; i < ginst->type_argc; ++i) {
7029 MonoType *t = ginst->type_argv [i], *norm;
7030 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7031 is_denorm_gtd = FALSE;
7032 norm = mono_type_normalize (t);
7035 requires_rebind = TRUE;
7039 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
7041 if (requires_rebind) {
7042 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7043 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7049 * mono_type_get_object:
7050 * @domain: an app domain
7053 * Return an System.MonoType object representing the type @type.
7056 mono_type_get_object (MonoDomain *domain, MonoType *type)
7059 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7060 mono_error_raise_exception (&error);
7066 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7068 MonoType *norm_type;
7069 MonoReflectionType *res;
7072 mono_error_init (error);
7074 klass = mono_class_from_mono_type (type);
7076 /*we must avoid using @type as it might have come
7077 * from a mono_metadata_type_dup and the caller
7078 * expects that is can be freed.
7079 * Using the right type from
7081 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7083 /* void is very common */
7084 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7085 return (MonoReflectionType*)domain->typeof_void;
7088 * If the vtable of the given class was already created, we can use
7089 * the MonoType from there and avoid all locking and hash table lookups.
7091 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7092 * that the resulting object is different.
7094 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7095 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7096 if (vtable && vtable->type)
7097 return (MonoReflectionType *)vtable->type;
7100 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7101 mono_domain_lock (domain);
7102 if (!domain->type_hash)
7103 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7104 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7105 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7106 mono_domain_unlock (domain);
7107 mono_loader_unlock ();
7111 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7112 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7113 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7114 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7115 * artifact of how generics are encoded and should be transparent to managed code so we
7116 * need to weed out this diference when retrieving managed System.Type objects.
7118 norm_type = mono_type_normalize (type);
7119 if (norm_type != type) {
7120 res = mono_type_get_object_checked (domain, norm_type, error);
7121 if (!mono_error_ok (error))
7123 mono_g_hash_table_insert (domain->type_hash, type, res);
7124 mono_domain_unlock (domain);
7125 mono_loader_unlock ();
7129 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7130 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7133 if (!verify_safe_for_managed_space (type)) {
7134 mono_domain_unlock (domain);
7135 mono_loader_unlock ();
7136 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7140 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7141 gboolean is_type_done = TRUE;
7142 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7143 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7144 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7146 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7147 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7149 if (gparam->owner && gparam->owner->is_method) {
7150 MonoMethod *method = gparam->owner->owner.method;
7151 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7152 is_type_done = FALSE;
7153 } else if (gparam->owner && !gparam->owner->is_method) {
7154 MonoClass *klass = gparam->owner->owner.klass;
7155 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7156 is_type_done = FALSE;
7160 /* g_assert_not_reached (); */
7161 /* should this be considered an error condition? */
7162 if (is_type_done && !type->byref) {
7163 mono_domain_unlock (domain);
7164 mono_loader_unlock ();
7165 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7168 /* This is stored in vtables/JITted code so it has to be pinned */
7169 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7170 if (!mono_error_ok (error))
7174 mono_g_hash_table_insert (domain->type_hash, type, res);
7176 if (type->type == MONO_TYPE_VOID)
7177 domain->typeof_void = (MonoObject*)res;
7179 mono_domain_unlock (domain);
7180 mono_loader_unlock ();
7185 * mono_method_get_object:
7186 * @domain: an app domain
7188 * @refclass: the reflected type (can be NULL)
7190 * Return an System.Reflection.MonoMethod object representing the method @method.
7192 MonoReflectionMethod*
7193 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7196 MonoReflectionMethod *ret = NULL;
7197 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7198 mono_error_raise_exception (&error);
7203 * mono_method_get_object_checked:
7204 * @domain: an app domain
7206 * @refclass: the reflected type (can be NULL)
7207 * @error: set on error.
7209 * Return an System.Reflection.MonoMethod object representing the method @method.
7210 * Returns NULL and sets @error on error.
7212 MonoReflectionMethod*
7213 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7216 * We use the same C representation for methods and constructors, but the type
7217 * name in C# is different.
7219 MonoReflectionType *rt;
7221 MonoReflectionMethod *ret;
7223 mono_error_init (error);
7225 if (method->is_inflated) {
7226 MonoReflectionGenericMethod *gret;
7229 refclass = method->klass;
7230 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7231 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7232 klass = mono_class_get_mono_generic_cmethod_class ();
7234 klass = mono_class_get_mono_generic_method_class ();
7236 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7237 if (!mono_error_ok (error))
7239 gret->method.method = method;
7241 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7243 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7244 if (!mono_error_ok (error))
7247 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7249 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7253 refclass = method->klass;
7255 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7256 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7257 klass = mono_class_get_mono_cmethod_class ();
7260 klass = mono_class_get_mono_method_class ();
7262 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7263 if (!mono_error_ok (error))
7265 ret->method = method;
7267 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7268 if (!mono_error_ok (error))
7271 MONO_OBJECT_SETREF (ret, reftype, rt);
7273 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7276 g_assert (!mono_error_ok (error));
7281 * mono_method_clear_object:
7283 * Clear the cached reflection objects for the dynamic method METHOD.
7286 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7289 g_assert (method_is_dynamic (method));
7291 klass = method->klass;
7293 clear_cached_object (domain, method, klass);
7294 klass = klass->parent;
7296 /* Added by mono_param_get_objects () */
7297 clear_cached_object (domain, &(method->signature), NULL);
7298 klass = method->klass;
7300 clear_cached_object (domain, &(method->signature), klass);
7301 klass = klass->parent;
7306 * mono_field_get_object:
7307 * @domain: an app domain
7311 * Return an System.Reflection.MonoField object representing the field @field
7314 MonoReflectionField*
7315 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7318 MonoReflectionField *result;
7319 result = mono_field_get_object_checked (domain, klass, field, &error);
7320 mono_error_raise_exception (&error);
7325 * mono_field_get_object_checked:
7326 * @domain: an app domain
7329 * @error: set on error
7331 * Return an System.Reflection.MonoField object representing the field @field
7332 * in class @klass. On error, returns NULL and sets @error.
7334 MonoReflectionField*
7335 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7337 MonoReflectionType *rt;
7338 MonoReflectionField *res;
7340 mono_error_init (error);
7342 CHECK_OBJECT (MonoReflectionField *, field, klass);
7343 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7348 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7350 if (is_field_on_inst (field)) {
7351 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7353 rt = mono_type_get_object_checked (domain, field->type, error);
7354 if (!mono_error_ok (error))
7357 MONO_OBJECT_SETREF (res, type, rt);
7360 rt = mono_type_get_object_checked (domain, field->type, error);
7361 if (!mono_error_ok (error))
7364 MONO_OBJECT_SETREF (res, type, rt);
7366 res->attrs = mono_field_get_flags (field);
7368 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7372 * mono_property_get_object:
7373 * @domain: an app domain
7375 * @property: a property
7377 * Return an System.Reflection.MonoProperty object representing the property @property
7380 MonoReflectionProperty*
7381 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7384 MonoReflectionProperty *result;
7385 result = mono_property_get_object_checked (domain, klass, property, &error);
7386 mono_error_raise_exception (&error);
7391 * mono_property_get_object:
7392 * @domain: an app domain
7394 * @property: a property
7395 * @error: set on error
7397 * Return an System.Reflection.MonoProperty object representing the property @property
7398 * in class @klass. On error returns NULL and sets @error.
7400 MonoReflectionProperty*
7401 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7403 MonoReflectionProperty *res;
7405 mono_error_init (error);
7407 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7408 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7412 res->property = property;
7413 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7417 * mono_event_get_object:
7418 * @domain: an app domain
7422 * Return an System.Reflection.MonoEvent object representing the event @event
7425 MonoReflectionEvent*
7426 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7429 MonoReflectionEvent *result;
7430 result = mono_event_get_object_checked (domain, klass, event, &error);
7431 mono_error_raise_exception (&error);
7436 * mono_event_get_object_checked:
7437 * @domain: an app domain
7440 * @error: set on error
7442 * Return an System.Reflection.MonoEvent object representing the event @event
7443 * in class @klass. On failure sets @error and returns NULL
7445 MonoReflectionEvent*
7446 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7448 MonoReflectionEvent *res;
7449 MonoReflectionMonoEvent *mono_event;
7451 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7452 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7455 mono_event->klass = klass;
7456 mono_event->event = event;
7457 res = (MonoReflectionEvent*)mono_event;
7458 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7462 * mono_get_reflection_missing_object:
7463 * @domain: Domain where the object lives
7465 * Returns the System.Reflection.Missing.Value singleton object
7466 * (of type System.Reflection.Missing).
7468 * Used as the value for ParameterInfo.DefaultValue when Optional
7472 mono_get_reflection_missing_object (MonoDomain *domain)
7475 static MonoClassField *missing_value_field = NULL;
7477 if (!missing_value_field) {
7478 MonoClass *missing_klass;
7479 missing_klass = mono_class_get_missing_class ();
7480 mono_class_init (missing_klass);
7481 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7482 g_assert (missing_value_field);
7484 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7490 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7493 *dbnull = mono_get_dbnull_object (domain);
7498 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7500 if (!*reflection_missing)
7501 *reflection_missing = mono_get_reflection_missing_object (domain);
7502 return *reflection_missing;
7506 * mono_param_get_objects:
7507 * @domain: an app domain
7510 * Return an System.Reflection.ParameterInfo array object representing the parameters
7511 * in the method @method.
7514 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7516 static MonoClass *System_Reflection_ParameterInfo;
7517 static MonoClass *System_Reflection_ParameterInfo_array;
7519 MonoArray *res = NULL;
7520 MonoReflectionMethod *member = NULL;
7521 MonoReflectionParameter *param = NULL;
7522 char **names = NULL, **blobs = NULL;
7523 guint32 *types = NULL;
7524 MonoType *type = NULL;
7525 MonoObject *dbnull = NULL;
7526 MonoObject *missing = NULL;
7527 MonoMarshalSpec **mspecs = NULL;
7528 MonoMethodSignature *sig = NULL;
7529 MonoVTable *pinfo_vtable;
7530 MonoReflectionType *rt;
7533 mono_error_init (&error);
7535 if (!System_Reflection_ParameterInfo_array) {
7538 klass = mono_class_get_mono_parameter_info_class ();
7540 mono_memory_barrier ();
7541 System_Reflection_ParameterInfo = klass;
7544 klass = mono_array_class_get (klass, 1);
7545 mono_memory_barrier ();
7546 System_Reflection_ParameterInfo_array = klass;
7549 sig = mono_method_signature_checked (method, &error);
7550 if (!mono_error_ok (&error))
7553 if (!sig->param_count) {
7554 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7561 /* Note: the cache is based on the address of the signature into the method
7562 * since we already cache MethodInfos with the method as keys.
7564 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7566 member = mono_method_get_object_checked (domain, method, refclass, &error);
7569 names = g_new (char *, sig->param_count);
7570 mono_method_get_param_names (method, (const char **) names);
7572 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7573 mono_method_get_marshal_info (method, mspecs);
7575 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7579 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7580 for (i = 0; i < sig->param_count; ++i) {
7581 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7585 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7589 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7591 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7593 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7595 param->PositionImpl = i;
7596 param->AttrsImpl = sig->params [i]->attrs;
7598 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7599 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7600 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7602 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7606 blobs = g_new0 (char *, sig->param_count);
7607 types = g_new0 (guint32, sig->param_count);
7608 get_default_param_value_blobs (method, blobs, types);
7611 /* Build MonoType for the type from the Constant Table */
7613 type = g_new0 (MonoType, 1);
7614 type->type = (MonoTypeEnum)types [i];
7615 type->data.klass = NULL;
7616 if (types [i] == MONO_TYPE_CLASS)
7617 type->data.klass = mono_defaults.object_class;
7618 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7619 /* For enums, types [i] contains the base type */
7621 type->type = MONO_TYPE_VALUETYPE;
7622 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7624 type->data.klass = mono_class_from_mono_type (type);
7626 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7628 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7629 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7630 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7631 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7633 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7638 if (mspecs [i + 1]) {
7639 MonoReflectionMarshalAsAttribute* mobj;
7640 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7643 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7646 mono_array_setref (res, i, param);
7656 for (i = sig->param_count; i >= 0; i--) {
7658 mono_metadata_free_marshal_spec (mspecs [i]);
7663 mono_error_raise_exception (&error); /* FIXME don't raise here */
7665 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7669 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7671 return mono_param_get_objects_internal (domain, method, NULL);
7675 * mono_method_body_get_object:
7676 * @domain: an app domain
7679 * Return an System.Reflection.MethodBody object representing the method @method.
7681 MonoReflectionMethodBody*
7682 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7685 MonoReflectionMethodBody *ret;
7686 MonoMethodHeader *header;
7688 MonoReflectionType *rt;
7689 guint32 method_rva, local_var_sig_token;
7691 unsigned char format, flags;
7694 /* for compatibility with .net */
7695 if (method_is_dynamic (method))
7696 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7698 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7700 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7701 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7702 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7703 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7704 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7707 image = method->klass->image;
7708 header = mono_method_get_header_checked (method, &error);
7709 mono_error_raise_exception (&error); /* FIXME don't raise here */
7711 if (!image_is_dynamic (image)) {
7712 /* Obtain local vars signature token */
7713 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7714 ptr = mono_image_rva_map (image, method_rva);
7715 flags = *(const unsigned char *) ptr;
7716 format = flags & METHOD_HEADER_FORMAT_MASK;
7718 case METHOD_HEADER_TINY_FORMAT:
7719 local_var_sig_token = 0;
7721 case METHOD_HEADER_FAT_FORMAT:
7725 local_var_sig_token = read32 (ptr);
7728 g_assert_not_reached ();
7731 local_var_sig_token = 0; //FIXME
7733 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7734 mono_error_raise_exception (&error); /* FIXME don't raise here */
7736 ret->init_locals = header->init_locals;
7737 ret->max_stack = header->max_stack;
7738 ret->local_var_sig_token = local_var_sig_token;
7739 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7740 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7743 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7744 for (i = 0; i < header->num_locals; ++i) {
7745 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7746 mono_error_raise_exception (&error); /* FIXME don't raise here */
7748 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7749 mono_error_raise_exception (&error); /* FIXME don't raise here */
7751 MONO_OBJECT_SETREF (info, local_type, rt);
7753 info->is_pinned = header->locals [i]->pinned;
7754 info->local_index = i;
7755 mono_array_setref (ret->locals, i, info);
7759 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7760 for (i = 0; i < header->num_clauses; ++i) {
7761 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7762 mono_error_raise_exception (&error); /* FIXME don't raise here */
7763 MonoExceptionClause *clause = &header->clauses [i];
7765 info->flags = clause->flags;
7766 info->try_offset = clause->try_offset;
7767 info->try_length = clause->try_len;
7768 info->handler_offset = clause->handler_offset;
7769 info->handler_length = clause->handler_len;
7770 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7771 info->filter_offset = clause->data.filter_offset;
7772 else if (clause->data.catch_class) {
7773 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7774 mono_error_raise_exception (&error); /* FIXME don't raise here */
7776 MONO_OBJECT_SETREF (info, catch_type, rt);
7779 mono_array_setref (ret->clauses, i, info);
7782 mono_metadata_free_mh (header);
7783 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7788 * mono_get_dbnull_object:
7789 * @domain: Domain where the object lives
7791 * Returns the System.DBNull.Value singleton object
7793 * Used as the value for ParameterInfo.DefaultValue
7796 mono_get_dbnull_object (MonoDomain *domain)
7799 static MonoClassField *dbnull_value_field = NULL;
7801 if (!dbnull_value_field) {
7802 MonoClass *dbnull_klass;
7803 dbnull_klass = mono_class_get_dbnull_class ();
7804 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7805 g_assert (dbnull_value_field);
7807 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7813 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7815 guint32 param_index, i, lastp, crow = 0;
7816 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7819 MonoClass *klass = method->klass;
7820 MonoImage *image = klass->image;
7821 MonoMethodSignature *methodsig = mono_method_signature (method);
7823 MonoTableInfo *constt;
7824 MonoTableInfo *methodt;
7825 MonoTableInfo *paramt;
7827 if (!methodsig->param_count)
7830 mono_class_init (klass);
7832 if (image_is_dynamic (klass->image)) {
7833 MonoReflectionMethodAux *aux;
7834 if (method->is_inflated)
7835 method = ((MonoMethodInflated*)method)->declaring;
7836 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7837 if (aux && aux->param_defaults) {
7838 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7839 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7844 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7845 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7846 constt = &image->tables [MONO_TABLE_CONSTANT];
7848 idx = mono_method_get_index (method) - 1;
7849 g_assert (idx != -1);
7851 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7852 if (idx + 1 < methodt->rows)
7853 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7855 lastp = paramt->rows + 1;
7857 for (i = param_index; i < lastp; ++i) {
7860 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7861 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7863 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7866 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7871 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7872 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7873 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7880 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7886 MonoType *basetype = type;
7891 klass = mono_class_from_mono_type (type);
7892 if (klass->valuetype) {
7893 object = mono_object_new_checked (domain, klass, &error);
7894 mono_error_raise_exception (&error); /* FIXME don't raise here */
7895 retval = ((gchar *) object + sizeof (MonoObject));
7896 if (klass->enumtype)
7897 basetype = mono_class_enum_basetype (klass);
7902 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7909 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7912 gboolean quoted = FALSE;
7914 memset (assembly, 0, sizeof (MonoAssemblyName));
7915 assembly->culture = "";
7916 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7923 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7934 /* Remove trailing whitespace */
7936 while (*s && g_ascii_isspace (*s))
7939 while (g_ascii_isspace (*p))
7942 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7944 assembly->major = strtoul (p, &s, 10);
7945 if (s == p || *s != '.')
7948 assembly->minor = strtoul (p, &s, 10);
7949 if (s == p || *s != '.')
7952 assembly->build = strtoul (p, &s, 10);
7953 if (s == p || *s != '.')
7956 assembly->revision = strtoul (p, &s, 10);
7960 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7962 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7963 assembly->culture = "";
7966 assembly->culture = p;
7967 while (*p && *p != ',') {
7971 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7973 if (strncmp (p, "null", 4) == 0) {
7978 while (*p && *p != ',') {
7981 len = (p - start + 1);
7982 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7983 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7984 g_strlcpy ((char*)assembly->public_key_token, start, len);
7987 while (*p && *p != ',')
7991 while (g_ascii_isspace (*p) || *p == ',') {
8005 * mono_reflection_parse_type:
8008 * Parse a type name as accepted by the GetType () method and output the info
8009 * extracted in the info structure.
8010 * the name param will be mangled, so, make a copy before passing it to this function.
8011 * The fields in info will be valid until the memory pointed to by name is valid.
8013 * See also mono_type_get_name () below.
8015 * Returns: 0 on parse error.
8018 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8019 MonoTypeNameParse *info)
8021 char *start, *p, *w, *last_point, *startn;
8022 int in_modifiers = 0;
8023 int isbyref = 0, rank = 0, isptr = 0;
8025 start = p = w = name;
8027 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8028 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8029 info->name = info->name_space = NULL;
8030 info->nested = NULL;
8031 info->modifiers = NULL;
8032 info->type_arguments = NULL;
8034 /* last_point separates the namespace from the name */
8037 while (*p == ' ') p++, start++, w++, name++;
8042 *p = 0; /* NULL terminate the name */
8044 info->nested = g_list_append (info->nested, startn);
8045 /* we have parsed the nesting namespace + name */
8049 info->name_space = start;
8051 info->name = last_point + 1;
8053 info->name_space = (char *)"";
8081 info->name_space = start;
8083 info->name = last_point + 1;
8085 info->name_space = (char *)"";
8092 if (isbyref) /* only one level allowed by the spec */
8096 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8100 if (isbyref) /* pointer to ref not okay */
8102 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8107 if (isbyref) /* array of ref and generic ref are not okay */
8109 //Decide if it's an array of a generic argument list
8114 if (*p == ',' || *p == '*' || *p == ']') { //array
8122 else if (*p == '*') /* '*' means unknown lower bound */
8123 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8130 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8132 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8135 info->type_arguments = g_ptr_array_new ();
8137 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8138 gboolean fqname = FALSE;
8140 g_ptr_array_add (info->type_arguments, subinfo);
8142 while (*p == ' ') p++;
8148 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8151 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8152 if (fqname && (*p != ']')) {
8160 while (*p && (*p != ']'))
8168 if (g_ascii_isspace (*aname)) {
8175 !assembly_name_to_aname (&subinfo->assembly, aname))
8177 } else if (fqname && (*p == ']')) {
8199 if (g_ascii_isspace (*p)) {
8206 return 0; /* missing assembly name */
8207 if (!assembly_name_to_aname (&info->assembly, p))
8213 if (info->assembly.name)
8216 // *w = 0; /* terminate class name */
8218 if (!info->name || !*info->name)
8222 /* add other consistency checks */
8228 * mono_identifier_unescape_type_name_chars:
8229 * @identifier: the display name of a mono type
8232 * The name in internal form, that is without escaping backslashes.
8234 * The string is modified in place!
8237 mono_identifier_unescape_type_name_chars(char* identifier)
8242 for (w = r = identifier; *r != 0; r++)
8260 mono_identifier_unescape_info (MonoTypeNameParse* info);
8263 unescape_each_type_argument(void* data, void* user_data)
8265 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8266 mono_identifier_unescape_info (info);
8270 unescape_each_nested_name (void* data, void* user_data)
8272 char* nested_name = (char*) data;
8273 mono_identifier_unescape_type_name_chars(nested_name);
8277 * mono_identifier_unescape_info:
8279 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8283 * Destructively updates the info by unescaping the identifiers that
8284 * comprise the type namespace, name, nested types (if any) and
8285 * generic type arguments (if any).
8287 * The resulting info has the names in internal form.
8291 mono_identifier_unescape_info (MonoTypeNameParse *info)
8295 mono_identifier_unescape_type_name_chars(info->name_space);
8296 mono_identifier_unescape_type_name_chars(info->name);
8297 // but don't escape info->assembly
8298 if (info->type_arguments)
8299 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8301 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8305 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8307 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8309 mono_identifier_unescape_info (info);
8315 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8317 gboolean type_resolve = FALSE;
8319 MonoImage *rootimage = image;
8321 if (info->assembly.name) {
8322 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8323 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8325 * This could happen in the AOT compiler case when the search hook is not
8328 assembly = image->assembly;
8330 /* then we must load the assembly ourselve - see #60439 */
8331 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8335 image = assembly->image;
8336 } else if (!image) {
8337 image = mono_defaults.corlib;
8340 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8341 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8342 image = mono_defaults.corlib;
8343 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8350 * mono_reflection_get_type_internal:
8352 * Returns: may return NULL on success, sets error on failure.
8355 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8360 gboolean bounded = FALSE;
8362 mono_error_init (error);
8364 image = mono_defaults.corlib;
8367 rootimage = mono_defaults.corlib;
8370 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8372 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8377 for (mod = info->nested; mod; mod = mod->next) {
8378 gpointer iter = NULL;
8382 mono_class_init (parent);
8384 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8386 char *nested_name, *nested_nspace;
8387 gboolean match = TRUE;
8389 lastp = strrchr ((const char *)mod->data, '.');
8391 /* Nested classes can have namespaces */
8394 nested_name = g_strdup (lastp + 1);
8395 nspace_len = lastp - (char*)mod->data;
8396 nested_nspace = (char *)g_malloc (nspace_len + 1);
8397 memcpy (nested_nspace, mod->data, nspace_len);
8398 nested_nspace [nspace_len] = '\0';
8401 nested_name = (char *)mod->data;
8402 nested_nspace = NULL;
8405 if (nested_nspace) {
8407 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8410 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8416 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8419 if (strcmp (klass->name, nested_name) != 0)
8424 g_free (nested_name);
8425 g_free (nested_nspace);
8437 if (info->type_arguments) {
8438 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8439 MonoReflectionType *the_type;
8443 for (i = 0; i < info->type_arguments->len; i++) {
8444 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8446 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8447 if (!type_args [i]) {
8453 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8457 instance = mono_reflection_bind_generic_parameters (
8458 the_type, info->type_arguments->len, type_args);
8464 klass = mono_class_from_mono_type (instance);
8467 for (mod = info->modifiers; mod; mod = mod->next) {
8468 modval = GPOINTER_TO_UINT (mod->data);
8469 if (!modval) { /* byref: must be last modifier */
8470 return &klass->this_arg;
8471 } else if (modval == -1) {
8472 klass = mono_ptr_class_get (&klass->byval_arg);
8473 } else if (modval == -2) {
8475 } else { /* array rank */
8476 klass = mono_bounded_array_class_get (klass, modval, bounded);
8480 return &klass->byval_arg;
8484 * mono_reflection_get_type:
8485 * @image: a metadata context
8486 * @info: type description structure
8487 * @ignorecase: flag for case-insensitive string compares
8488 * @type_resolve: whenever type resolve was already tried
8490 * Build a MonoType from the type description in @info.
8495 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8496 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8500 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8502 MonoReflectionAssemblyBuilder *abuilder;
8506 mono_error_init (error);
8507 g_assert (assembly_is_dynamic (assembly));
8508 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8512 /* Enumerate all modules */
8515 if (abuilder->modules) {
8516 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8517 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8518 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8521 if (!mono_error_ok (error))
8526 if (!type && abuilder->loaded_modules) {
8527 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8528 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8529 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8532 if (!mono_error_ok (error))
8541 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8545 MonoReflectionAssembly *assembly;
8549 if (image && image_is_dynamic (image))
8550 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8552 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8554 if (!mono_error_ok (&error))
8555 mono_error_raise_exception (&error); /* FIXME don't raise here */
8559 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8566 *type_resolve = TRUE;
8569 /* Reconstruct the type name */
8570 fullName = g_string_new ("");
8571 if (info->name_space && (info->name_space [0] != '\0'))
8572 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8574 g_string_printf (fullName, "%s", info->name);
8575 for (mod = info->nested; mod; mod = mod->next)
8576 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8578 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8579 mono_error_raise_exception (&error); /* FIXME don't raise here */
8582 if (assembly_is_dynamic (assembly->assembly))
8583 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8584 info, ignorecase, &error);
8586 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8587 info, ignorecase, &error);
8589 g_string_free (fullName, TRUE);
8590 if (!mono_error_ok (&error))
8591 mono_error_raise_exception (&error); /* FIXME don't raise here */
8596 mono_reflection_free_type_info (MonoTypeNameParse *info)
8598 g_list_free (info->modifiers);
8599 g_list_free (info->nested);
8601 if (info->type_arguments) {
8604 for (i = 0; i < info->type_arguments->len; i++) {
8605 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8607 mono_reflection_free_type_info (subinfo);
8608 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8612 g_ptr_array_free (info->type_arguments, TRUE);
8617 * mono_reflection_type_from_name:
8619 * @image: a metadata context (can be NULL).
8621 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8622 * it defaults to get the type from @image or, if @image is NULL or loading
8623 * from it fails, uses corlib.
8627 mono_reflection_type_from_name (char *name, MonoImage *image)
8629 MonoType *type = NULL;
8630 MonoTypeNameParse info;
8633 /* Make a copy since parse_type modifies its argument */
8634 tmp = g_strdup (name);
8636 /*g_print ("requested type %s\n", str);*/
8637 if (mono_reflection_parse_type (tmp, &info)) {
8638 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8642 mono_reflection_free_type_info (&info);
8647 * mono_reflection_get_token:
8649 * Return the metadata token of OBJ which should be an object
8650 * representing a metadata element.
8653 mono_reflection_get_token (MonoObject *obj)
8659 klass = obj->vtable->klass;
8661 if (strcmp (klass->name, "MethodBuilder") == 0) {
8662 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8664 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8665 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8666 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8668 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8669 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8670 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8672 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8673 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8674 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8675 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8676 } else if (strcmp (klass->name, "MonoType") == 0) {
8677 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8678 mono_error_raise_exception (&error); /* FIXME don't raise here */
8679 MonoClass *mc = mono_class_from_mono_type (type);
8680 if (!mono_class_init (mc))
8681 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8683 token = mc->type_token;
8684 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8685 strcmp (klass->name, "MonoMethod") == 0 ||
8686 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8687 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8688 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8689 if (m->method->is_inflated) {
8690 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8691 return inflated->declaring->token;
8693 token = m->method->token;
8695 } else if (strcmp (klass->name, "MonoField") == 0) {
8696 MonoReflectionField *f = (MonoReflectionField*)obj;
8698 if (is_field_on_inst (f->field)) {
8699 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8701 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8702 int field_index = f->field - dgclass->fields;
8705 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8706 obj = dgclass->field_objects [field_index];
8707 return mono_reflection_get_token (obj);
8710 token = mono_class_get_field_token (f->field);
8711 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8712 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8714 token = mono_class_get_property_token (p->property);
8715 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8716 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8718 token = mono_class_get_event_token (p->event);
8719 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8720 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8721 MonoClass *member_class = mono_object_class (p->MemberImpl);
8722 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8724 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8725 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8726 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8729 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8730 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8732 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8733 MonoException *ex = mono_get_exception_not_implemented (msg);
8735 mono_raise_exception (ex);
8742 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8746 int slen = mono_metadata_decode_value (p, &p);
8748 mono_error_init (error);
8750 n = (char *)g_memdup (p, slen + 1);
8752 t = mono_reflection_type_from_name (n, image);
8754 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8755 /* We don't free n, it's consumed by mono_error */
8756 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8762 return mono_class_from_mono_type (t);
8766 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8768 int slen, type = t->type;
8769 MonoClass *tklass = t->data.klass;
8771 mono_error_init (error);
8777 case MONO_TYPE_BOOLEAN: {
8778 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8783 case MONO_TYPE_CHAR:
8785 case MONO_TYPE_I2: {
8786 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8791 #if SIZEOF_VOID_P == 4
8797 case MONO_TYPE_I4: {
8798 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8803 #if SIZEOF_VOID_P == 8
8804 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8808 case MONO_TYPE_I8: {
8809 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8814 case MONO_TYPE_R8: {
8815 double *val = (double *)g_malloc (sizeof (double));
8820 case MONO_TYPE_VALUETYPE:
8821 if (t->data.klass->enumtype) {
8822 type = mono_class_enum_basetype (t->data.klass)->type;
8825 MonoClass *k = t->data.klass;
8827 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8828 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8834 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8837 case MONO_TYPE_STRING:
8838 if (*p == (char)0xFF) {
8842 slen = mono_metadata_decode_value (p, &p);
8844 return mono_string_new_len (mono_domain_get (), p, slen);
8845 case MONO_TYPE_CLASS: {
8846 MonoReflectionType *rt;
8849 if (*p == (char)0xFF) {
8854 slen = mono_metadata_decode_value (p, &p);
8855 n = (char *)g_memdup (p, slen + 1);
8857 t = mono_reflection_type_from_name (n, image);
8859 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8860 /* We don't free n, it's consumed by mono_error */
8861 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8867 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8868 if (!mono_error_ok (error))
8873 case MONO_TYPE_OBJECT: {
8876 MonoClass *subc = NULL;
8881 } else if (subt == 0x0E) {
8882 type = MONO_TYPE_STRING;
8884 } else if (subt == 0x1D) {
8885 MonoType simple_type = {{0}};
8889 type = MONO_TYPE_SZARRAY;
8890 if (etype == 0x50) {
8891 tklass = mono_defaults.systemtype_class;
8892 } else if (etype == 0x55) {
8893 tklass = load_cattr_enum_type (image, p, &p, error);
8894 if (!mono_error_ok (error))
8898 /* See Partition II, Appendix B3 */
8899 etype = MONO_TYPE_OBJECT;
8900 simple_type.type = (MonoTypeEnum)etype;
8901 tklass = mono_class_from_mono_type (&simple_type);
8904 } else if (subt == 0x55) {
8907 slen = mono_metadata_decode_value (p, &p);
8908 n = (char *)g_memdup (p, slen + 1);
8910 t = mono_reflection_type_from_name (n, image);
8912 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8913 /* We don't free n, it's consumed by mono_error */
8914 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8919 subc = mono_class_from_mono_type (t);
8920 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8921 MonoType simple_type = {{0}};
8922 simple_type.type = (MonoTypeEnum)subt;
8923 subc = mono_class_from_mono_type (&simple_type);
8925 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8927 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8929 if (mono_error_ok (error)) {
8930 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8931 g_assert (!subc->has_references);
8932 if (mono_error_ok (error))
8933 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8939 case MONO_TYPE_SZARRAY: {
8941 guint32 i, alen, basetype;
8944 if (alen == 0xffffffff) {
8948 arr = mono_array_new (mono_domain_get(), tklass, alen);
8949 basetype = tklass->byval_arg.type;
8950 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8951 basetype = mono_class_enum_basetype (tklass)->type;
8956 case MONO_TYPE_BOOLEAN:
8957 for (i = 0; i < alen; i++) {
8958 MonoBoolean val = *p++;
8959 mono_array_set (arr, MonoBoolean, i, val);
8962 case MONO_TYPE_CHAR:
8965 for (i = 0; i < alen; i++) {
8966 guint16 val = read16 (p);
8967 mono_array_set (arr, guint16, i, val);
8974 for (i = 0; i < alen; i++) {
8975 guint32 val = read32 (p);
8976 mono_array_set (arr, guint32, i, val);
8981 for (i = 0; i < alen; i++) {
8984 mono_array_set (arr, double, i, val);
8990 for (i = 0; i < alen; i++) {
8991 guint64 val = read64 (p);
8992 mono_array_set (arr, guint64, i, val);
8996 case MONO_TYPE_CLASS:
8997 case MONO_TYPE_OBJECT:
8998 case MONO_TYPE_STRING:
8999 case MONO_TYPE_SZARRAY:
9000 for (i = 0; i < alen; i++) {
9001 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9002 if (!mono_error_ok (error))
9004 mono_array_setref (arr, i, item);
9008 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9014 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9020 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9022 static MonoMethod *ctor;
9024 void *params [2], *unboxed;
9026 mono_error_init (error);
9029 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9031 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9032 return_val_if_nok (error, NULL);
9035 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9036 return_val_if_nok (error, NULL);
9037 unboxed = mono_object_unbox (retval);
9039 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9040 return_val_if_nok (error, NULL);
9046 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9048 static MonoMethod *ctor;
9050 void *unboxed, *params [2];
9052 mono_error_init (error);
9055 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9058 params [1] = typedarg;
9059 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9060 return_val_if_nok (error, NULL);
9062 unboxed = mono_object_unbox (retval);
9064 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9065 return_val_if_nok (error, NULL);
9071 type_is_reference (MonoType *type)
9073 switch (type->type) {
9074 case MONO_TYPE_BOOLEAN:
9075 case MONO_TYPE_CHAR:
9088 case MONO_TYPE_VALUETYPE:
9096 free_param_data (MonoMethodSignature *sig, void **params) {
9098 for (i = 0; i < sig->param_count; ++i) {
9099 if (!type_is_reference (sig->params [i]))
9100 g_free (params [i]);
9105 * Find the field index in the metadata FieldDef table.
9108 find_field_index (MonoClass *klass, MonoClassField *field) {
9111 for (i = 0; i < klass->field.count; ++i) {
9112 if (field == &klass->fields [i])
9113 return klass->field.first + 1 + i;
9119 * Find the property index in the metadata Property table.
9122 find_property_index (MonoClass *klass, MonoProperty *property) {
9125 for (i = 0; i < klass->ext->property.count; ++i) {
9126 if (property == &klass->ext->properties [i])
9127 return klass->ext->property.first + 1 + i;
9133 * Find the event index in the metadata Event table.
9136 find_event_index (MonoClass *klass, MonoEvent *event) {
9139 for (i = 0; i < klass->ext->event.count; ++i) {
9140 if (event == &klass->ext->events [i])
9141 return klass->ext->event.first + 1 + i;
9147 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9149 const char *p = (const char*)data;
9151 guint32 i, j, num_named;
9153 void *params_buf [32];
9154 void **params = NULL;
9155 MonoMethodSignature *sig;
9156 MonoObject *exc = NULL;
9158 mono_error_init (error);
9160 mono_class_init (method->klass);
9162 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9163 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9168 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9169 if (!mono_error_ok (error)) return NULL;
9171 mono_runtime_invoke_checked (method, attr, NULL, error);
9172 if (!mono_error_ok (error))
9178 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9181 /*g_print ("got attr %s\n", method->klass->name);*/
9183 sig = mono_method_signature (method);
9184 if (sig->param_count < 32) {
9185 params = params_buf;
9186 memset (params, 0, sizeof (void*) * sig->param_count);
9188 /* Allocate using GC so it gets GC tracking */
9189 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9194 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9195 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9196 if (!mono_error_ok (error))
9201 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9202 if (!mono_error_ok (error)) goto fail;
9204 mono_runtime_try_invoke (method, attr, params, &exc, error);
9205 if (!mono_error_ok (error))
9210 num_named = read16 (named);
9212 for (j = 0; j < num_named; j++) {
9214 char *name, named_type, data_type;
9215 named_type = *named++;
9216 data_type = *named++; /* type of data */
9217 if (data_type == MONO_TYPE_SZARRAY)
9218 data_type = *named++;
9219 if (data_type == MONO_TYPE_ENUM) {
9222 type_len = mono_metadata_decode_blob_size (named, &named);
9223 type_name = (char *)g_malloc (type_len + 1);
9224 memcpy (type_name, named, type_len);
9225 type_name [type_len] = 0;
9227 /* FIXME: lookup the type and check type consistency */
9230 name_len = mono_metadata_decode_blob_size (named, &named);
9231 name = (char *)g_malloc (name_len + 1);
9232 memcpy (name, named, name_len);
9233 name [name_len] = 0;
9235 if (named_type == 0x53) {
9236 MonoClassField *field;
9239 /* how this fail is a blackbox */
9240 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9242 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9247 val = load_cattr_value (image, field->type, named, &named, error);
9248 if (!mono_error_ok (error)) {
9250 if (!type_is_reference (field->type))
9255 mono_field_set_value (attr, field, val);
9256 if (!type_is_reference (field->type))
9258 } else if (named_type == 0x54) {
9261 MonoType *prop_type;
9263 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9266 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9272 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9277 /* can we have more that 1 arg in a custom attr named property? */
9278 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9279 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9281 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9282 if (!mono_error_ok (error)) {
9284 if (!type_is_reference (prop_type))
9285 g_free (pparams [0]);
9290 mono_property_set_value (prop, attr, pparams, NULL);
9291 if (!type_is_reference (prop_type))
9292 g_free (pparams [0]);
9297 free_param_data (method->signature, params);
9298 if (params != params_buf)
9299 mono_gc_free_fixed (params);
9304 free_param_data (method->signature, params);
9305 if (params != params_buf)
9306 mono_gc_free_fixed (params);
9308 mono_raise_exception ((MonoException*)exc);
9313 * mono_reflection_create_custom_attr_data_args:
9315 * Create an array of typed and named arguments from the cattr blob given by DATA.
9316 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9317 * NAMED_ARG_INFO will contain information about the named arguments.
9320 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)
9322 MonoArray *typedargs, *namedargs;
9323 MonoClass *attrklass;
9325 const char *p = (const char*)data;
9327 guint32 i, j, num_named;
9328 CattrNamedArg *arginfo = NULL;
9332 *named_arg_info = NULL;
9334 mono_error_init (error);
9336 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9337 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9341 mono_class_init (method->klass);
9343 domain = mono_domain_get ();
9345 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9348 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9352 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9356 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9357 if (!mono_error_ok (error)) {
9358 if (!type_is_reference (mono_method_signature (method)->params [i]))
9363 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9364 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9365 mono_array_setref (typedargs, i, obj);
9367 if (!type_is_reference (mono_method_signature (method)->params [i]))
9372 num_named = read16 (named);
9373 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9375 attrklass = method->klass;
9377 arginfo = g_new0 (CattrNamedArg, num_named);
9378 *named_arg_info = arginfo;
9380 for (j = 0; j < num_named; j++) {
9382 char *name, named_type, data_type;
9383 named_type = *named++;
9384 data_type = *named++; /* type of data */
9385 if (data_type == MONO_TYPE_SZARRAY)
9386 data_type = *named++;
9387 if (data_type == MONO_TYPE_ENUM) {
9390 type_len = mono_metadata_decode_blob_size (named, &named);
9391 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9394 type_name = (char *)g_malloc (type_len + 1);
9395 memcpy (type_name, named, type_len);
9396 type_name [type_len] = 0;
9398 /* FIXME: lookup the type and check type consistency */
9401 name_len = mono_metadata_decode_blob_size (named, &named);
9402 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9404 name = (char *)g_malloc (name_len + 1);
9405 memcpy (name, named, name_len);
9406 name [name_len] = 0;
9408 if (named_type == 0x53) {
9410 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9418 arginfo [j].type = field->type;
9419 arginfo [j].field = field;
9421 val = load_cattr_value (image, field->type, named, &named, error);
9422 if (!mono_error_ok (error)) {
9423 if (!type_is_reference (field->type))
9429 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9430 mono_array_setref (namedargs, j, obj);
9431 if (!type_is_reference (field->type))
9433 } else if (named_type == 0x54) {
9435 MonoType *prop_type;
9436 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9439 if (!prop || !prop->set) {
9444 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9445 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9447 arginfo [j].type = prop_type;
9448 arginfo [j].prop = prop;
9450 val = load_cattr_value (image, prop_type, named, &named, error);
9451 if (!mono_error_ok (error)) {
9452 if (!type_is_reference (prop_type))
9458 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9459 mono_array_setref (namedargs, j, obj);
9460 if (!type_is_reference (prop_type))
9466 *typed_args = typedargs;
9467 *named_args = namedargs;
9470 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9472 *named_arg_info = NULL;
9476 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9479 MonoArray *typedargs, *namedargs;
9482 CattrNamedArg *arginfo = NULL;
9486 mono_error_init (&error);
9494 image = assembly->assembly->image;
9495 method = ref_method->method;
9496 domain = mono_object_domain (ref_method);
9498 if (!mono_class_init (method->klass))
9499 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9501 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9502 if (!mono_error_ok (&error))
9505 if (mono_loader_get_last_error ()) {
9506 mono_error_set_from_loader_error (&error);
9510 if (!typedargs || !namedargs)
9513 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9514 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9515 MonoObject *typedarg;
9517 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9518 if (!is_ok (&error))
9520 mono_array_setref (typedargs, i, typedarg);
9523 for (i = 0; i < mono_array_length (namedargs); ++i) {
9524 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9525 MonoObject *typedarg, *namedarg, *minfo;
9527 if (arginfo [i].prop) {
9528 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9532 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9533 if (!mono_error_ok (&error))
9537 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9538 if (!is_ok (&error))
9540 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9541 if (!is_ok (&error))
9544 mono_array_setref (namedargs, i, namedarg);
9547 *ctor_args = typedargs;
9548 *named_args = namedargs;
9551 mono_error_raise_exception (&error);
9556 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9558 static MonoMethod *ctor;
9564 mono_error_init (error);
9566 g_assert (image->assembly);
9569 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9571 domain = mono_domain_get ();
9572 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9573 return_val_if_nok (error, NULL);
9574 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9575 return_val_if_nok (error, NULL);
9576 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9577 return_val_if_nok (error, NULL);
9578 params [2] = (gpointer)&cattr->data;
9579 params [3] = &cattr->data_size;
9581 mono_runtime_invoke_checked (ctor, attr, params, error);
9582 return_val_if_nok (error, NULL);
9587 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9593 mono_error_init (error);
9596 for (i = 0; i < cinfo->num_attrs; ++i) {
9597 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9601 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9603 for (i = 0; i < cinfo->num_attrs; ++i) {
9604 if (!cinfo->attrs [i].ctor) {
9605 /* The cattr type is not finished yet */
9606 /* We should include the type name but cinfo doesn't contain it */
9607 mono_error_set_type_load_name (error, NULL, NULL, "");
9610 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9611 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9612 if (!mono_error_ok (error))
9614 mono_array_setref (result, n, attr);
9622 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9625 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9626 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9632 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9638 mono_error_init (error);
9639 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9640 for (i = 0; i < cinfo->num_attrs; ++i) {
9641 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9642 return_val_if_nok (error, NULL);
9643 mono_array_setref (result, i, attr);
9649 * mono_custom_attrs_from_index:
9651 * Returns: NULL if no attributes are found or if a loading error occurs.
9654 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9657 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9658 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9662 * mono_custom_attrs_from_index_checked:
9664 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9667 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9669 guint32 mtoken, i, len;
9670 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9672 MonoCustomAttrInfo *ainfo;
9673 GList *tmp, *list = NULL;
9675 MonoCustomAttrEntry* attr;
9677 mono_error_init (error);
9679 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9681 i = mono_metadata_custom_attrs_from_index (image, idx);
9685 while (i < ca->rows) {
9686 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9688 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9691 len = g_list_length (list);
9694 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9695 ainfo->num_attrs = len;
9696 ainfo->image = image;
9697 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9698 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9699 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9700 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9701 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9702 mtoken |= MONO_TOKEN_METHOD_DEF;
9704 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9705 mtoken |= MONO_TOKEN_MEMBER_REF;
9708 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9711 attr = &ainfo->attrs [i - 1];
9712 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9714 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9720 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9721 /*FIXME raising an exception here doesn't make any sense*/
9722 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9727 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9728 attr->data_size = mono_metadata_decode_value (data, &data);
9729 attr->data = (guchar*)data;
9737 mono_custom_attrs_from_method (MonoMethod *method)
9740 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9741 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9746 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9750 mono_error_init (error);
9753 * An instantiated method has the same cattrs as the generic method definition.
9755 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9756 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9758 if (method->is_inflated)
9759 method = ((MonoMethodInflated *) method)->declaring;
9761 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9762 return lookup_custom_attr (method->klass->image, method);
9765 /* Synthetic methods */
9768 idx = mono_method_get_index (method);
9769 idx <<= MONO_CUSTOM_ATTR_BITS;
9770 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9771 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9775 mono_custom_attrs_from_class (MonoClass *klass)
9778 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9779 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9784 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9788 mono_error_init (error);
9790 if (klass->generic_class)
9791 klass = klass->generic_class->container_class;
9793 if (image_is_dynamic (klass->image))
9794 return lookup_custom_attr (klass->image, klass);
9796 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9797 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9798 idx <<= MONO_CUSTOM_ATTR_BITS;
9799 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9801 idx = mono_metadata_token_index (klass->type_token);
9802 idx <<= MONO_CUSTOM_ATTR_BITS;
9803 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9805 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9809 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9812 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9813 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9818 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9822 mono_error_init (error);
9824 if (image_is_dynamic (assembly->image))
9825 return lookup_custom_attr (assembly->image, assembly);
9826 idx = 1; /* there is only one assembly */
9827 idx <<= MONO_CUSTOM_ATTR_BITS;
9828 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9829 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9832 static MonoCustomAttrInfo*
9833 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9837 if (image_is_dynamic (image))
9838 return lookup_custom_attr (image, image);
9839 idx = 1; /* there is only one module */
9840 idx <<= MONO_CUSTOM_ATTR_BITS;
9841 idx |= MONO_CUSTOM_ATTR_MODULE;
9842 return mono_custom_attrs_from_index_checked (image, idx, error);
9846 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9849 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9850 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9855 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9859 if (image_is_dynamic (klass->image)) {
9860 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9861 return lookup_custom_attr (klass->image, property);
9863 idx = find_property_index (klass, property);
9864 idx <<= MONO_CUSTOM_ATTR_BITS;
9865 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9866 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9870 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9873 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9874 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9879 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9883 if (image_is_dynamic (klass->image)) {
9884 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9885 return lookup_custom_attr (klass->image, event);
9887 idx = find_event_index (klass, event);
9888 idx <<= MONO_CUSTOM_ATTR_BITS;
9889 idx |= MONO_CUSTOM_ATTR_EVENT;
9890 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9894 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9897 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9898 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9903 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9906 mono_error_init (error);
9908 if (image_is_dynamic (klass->image)) {
9909 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9910 return lookup_custom_attr (klass->image, field);
9912 idx = find_field_index (klass, field);
9913 idx <<= MONO_CUSTOM_ATTR_BITS;
9914 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9915 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9919 * mono_custom_attrs_from_param:
9920 * @method: handle to the method that we want to retrieve custom parameter information from
9921 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9923 * The result must be released with mono_custom_attrs_free().
9925 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9928 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9931 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9932 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9937 * mono_custom_attrs_from_param_checked:
9938 * @method: handle to the method that we want to retrieve custom parameter information from
9939 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9940 * @error: set on error
9942 * The result must be released with mono_custom_attrs_free().
9944 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9947 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9950 guint32 i, idx, method_index;
9951 guint32 param_list, param_last, param_pos, found;
9953 MonoReflectionMethodAux *aux;
9955 mono_error_init (error);
9958 * An instantiated method has the same cattrs as the generic method definition.
9960 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9961 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9963 if (method->is_inflated)
9964 method = ((MonoMethodInflated *) method)->declaring;
9966 if (image_is_dynamic (method->klass->image)) {
9967 MonoCustomAttrInfo *res, *ainfo;
9970 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9971 if (!aux || !aux->param_cattr)
9974 /* Need to copy since it will be freed later */
9975 ainfo = aux->param_cattr [param];
9978 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9979 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9980 memcpy (res, ainfo, size);
9984 image = method->klass->image;
9985 method_index = mono_method_get_index (method);
9988 ca = &image->tables [MONO_TABLE_METHOD];
9990 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9991 if (method_index == ca->rows) {
9992 ca = &image->tables [MONO_TABLE_PARAM];
9993 param_last = ca->rows + 1;
9995 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9996 ca = &image->tables [MONO_TABLE_PARAM];
9999 for (i = param_list; i < param_last; ++i) {
10000 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10001 if (param_pos == param) {
10009 idx <<= MONO_CUSTOM_ATTR_BITS;
10010 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10011 return mono_custom_attrs_from_index_checked (image, idx, error);
10015 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10019 for (i = 0; i < ainfo->num_attrs; ++i) {
10020 klass = ainfo->attrs [i].ctor->klass;
10021 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10028 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10031 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10032 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10037 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10043 mono_error_init (error);
10046 for (i = 0; i < ainfo->num_attrs; ++i) {
10047 klass = ainfo->attrs [i].ctor->klass;
10048 if (mono_class_has_parent (klass, attr_klass)) {
10053 if (attr_index == -1)
10056 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10057 if (!mono_error_ok (error))
10059 return mono_array_get (attrs, MonoObject*, attr_index);
10063 * mono_reflection_get_custom_attrs_info:
10064 * @obj: a reflection object handle
10066 * Return the custom attribute info for attributes defined for the
10067 * reflection handle @obj. The objects.
10069 * FIXME this function leaks like a sieve for SRE objects.
10071 MonoCustomAttrInfo*
10072 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10075 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10076 mono_error_assert_ok (&error);
10081 * mono_reflection_get_custom_attrs_info_checked:
10082 * @obj: a reflection object handle
10083 * @error: set on error
10085 * Return the custom attribute info for attributes defined for the
10086 * reflection handle @obj. The objects.
10088 * On failure returns NULL and sets @error.
10090 * FIXME this function leaks like a sieve for SRE objects.
10092 MonoCustomAttrInfo*
10093 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10096 MonoCustomAttrInfo *cinfo = NULL;
10098 mono_error_init (error);
10100 klass = obj->vtable->klass;
10101 if (klass == mono_defaults.monotype_class) {
10102 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10103 return_val_if_nok (error, NULL);
10104 klass = mono_class_from_mono_type (type);
10105 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10106 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10107 return_val_if_nok (error, NULL);
10108 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10109 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10110 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10111 return_val_if_nok (error, NULL);
10112 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10113 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10114 cinfo = mono_custom_attrs_from_module (module->image, error);
10115 return_val_if_nok (error, NULL);
10116 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10117 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10118 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10119 return_val_if_nok (error, NULL);
10120 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10121 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10122 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10123 return_val_if_nok (error, NULL);
10124 } else if (strcmp ("MonoField", klass->name) == 0) {
10125 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10126 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10127 return_val_if_nok (error, NULL);
10128 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10129 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10130 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10131 return_val_if_nok (error, NULL);
10132 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10133 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10134 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10135 return_val_if_nok (error, NULL);
10136 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10137 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10138 MonoClass *member_class = mono_object_class (param->MemberImpl);
10139 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10140 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10141 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10142 return_val_if_nok (error, NULL);
10143 } else if (is_sr_mono_property (member_class)) {
10144 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10145 MonoMethod *method;
10146 if (!(method = prop->property->get))
10147 method = prop->property->set;
10150 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10151 return_val_if_nok (error, NULL);
10153 #ifndef DISABLE_REFLECTION_EMIT
10154 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10155 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10156 return_val_if_nok (error, NULL);
10157 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10158 return_val_if_nok (error, NULL);
10159 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10160 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10161 MonoMethod *method = NULL;
10162 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10163 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10164 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10165 method = ((MonoReflectionMethod *)c->cb)->method;
10167 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));
10169 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10170 return_val_if_nok (error, NULL);
10174 char *type_name = mono_type_get_full_name (member_class);
10175 mono_error_set_generic_error (error, "System", "NotSupportedException",
10176 "Custom attributes on a ParamInfo with member %s are not supported",
10178 g_free (type_name);
10181 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10182 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10183 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10184 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10185 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10186 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10187 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10188 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10189 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10190 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10191 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10192 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10193 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10194 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10195 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10196 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10197 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10198 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10199 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10200 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10201 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10202 return_val_if_nok (error, NULL);
10203 } else { /* handle other types here... */
10204 g_error ("get custom attrs not yet supported for %s", klass->name);
10211 * mono_reflection_get_custom_attrs_by_type:
10212 * @obj: a reflection object handle
10214 * Return an array with all the custom attributes defined of the
10215 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10216 * of that type are returned. The objects are fully build. Return NULL if a loading error
10220 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10223 MonoCustomAttrInfo *cinfo;
10225 mono_error_init (error);
10227 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10228 return_val_if_nok (error, NULL);
10230 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10233 if (!cinfo->cached)
10234 mono_custom_attrs_free (cinfo);
10236 mono_loader_assert_no_error ();
10237 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10244 * mono_reflection_get_custom_attrs:
10245 * @obj: a reflection object handle
10247 * Return an array with all the custom attributes defined of the
10248 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10252 mono_reflection_get_custom_attrs (MonoObject *obj)
10256 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10260 * mono_reflection_get_custom_attrs_data:
10261 * @obj: a reflection obj handle
10263 * Returns an array of System.Reflection.CustomAttributeData,
10264 * which include information about attributes reflected on
10265 * types loaded using the Reflection Only methods
10268 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10272 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10273 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10278 * mono_reflection_get_custom_attrs_data_checked:
10279 * @obj: a reflection obj handle
10280 * @error: set on error
10282 * Returns an array of System.Reflection.CustomAttributeData,
10283 * which include information about attributes reflected on
10284 * types loaded using the Reflection Only methods
10287 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10290 MonoCustomAttrInfo *cinfo;
10292 mono_error_init (error);
10294 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10295 return_val_if_nok (error, NULL);
10297 result = mono_custom_attrs_data_construct (cinfo, error);
10298 return_val_if_nok (error, NULL);
10299 if (!cinfo->cached)
10300 mono_custom_attrs_free (cinfo);
10302 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10304 if (mono_loader_get_last_error ())
10305 mono_error_set_from_loader_error (error);
10310 static MonoReflectionType*
10311 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10313 static MonoMethod *method_get_underlying_system_type = NULL;
10314 MonoReflectionType *rt;
10315 MonoMethod *usertype_method;
10317 mono_error_init (error);
10319 if (!method_get_underlying_system_type)
10320 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10322 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10324 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10331 is_corlib_type (MonoClass *klass)
10333 return klass->image == mono_defaults.corlib;
10336 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10337 static MonoClass *cached_class; \
10338 if (cached_class) \
10339 return cached_class == _class; \
10340 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10341 cached_class = _class; \
10348 #ifndef DISABLE_REFLECTION_EMIT
10350 is_sre_array (MonoClass *klass)
10352 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10356 is_sre_byref (MonoClass *klass)
10358 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10362 is_sre_pointer (MonoClass *klass)
10364 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10368 is_sre_generic_instance (MonoClass *klass)
10370 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10374 is_sre_type_builder (MonoClass *klass)
10376 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10380 is_sre_method_builder (MonoClass *klass)
10382 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10386 is_sre_ctor_builder (MonoClass *klass)
10388 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10392 is_sre_field_builder (MonoClass *klass)
10394 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10398 is_sre_method_on_tb_inst (MonoClass *klass)
10400 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10404 is_sre_ctor_on_tb_inst (MonoClass *klass)
10406 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10410 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10413 mono_error_init (error);
10420 if (is_usertype (ref)) {
10421 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10422 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10428 klass = mono_object_class (ref);
10430 if (is_sre_array (klass)) {
10432 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10433 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10434 return_val_if_nok (error, NULL);
10436 if (sre_array->rank == 0) //single dimentional array
10437 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10439 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10440 sre_array->type.type = res;
10442 } else if (is_sre_byref (klass)) {
10444 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10445 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10446 return_val_if_nok (error, NULL);
10448 res = &mono_class_from_mono_type (base)->this_arg;
10449 sre_byref->type.type = res;
10451 } else if (is_sre_pointer (klass)) {
10453 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10454 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10455 return_val_if_nok (error, NULL);
10457 res = &mono_ptr_class_get (base)->byval_arg;
10458 sre_pointer->type.type = res;
10460 } else if (is_sre_generic_instance (klass)) {
10461 MonoType *res, **types;
10462 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10465 count = mono_array_length (gclass->type_arguments);
10466 types = g_new0 (MonoType*, count);
10467 for (i = 0; i < count; ++i) {
10468 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10469 types [i] = mono_reflection_type_get_handle (t, error);
10470 if (!types[i] || !is_ok (error)) {
10476 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10479 gclass->type.type = res;
10483 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10488 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10491 mono_reflection_type_get_handle (type, &error);
10492 mono_error_set_pending_exception (&error);
10496 mono_reflection_register_with_runtime (MonoReflectionType *type)
10499 MonoType *res = mono_reflection_type_get_handle (type, &error);
10500 mono_error_raise_exception (&error); /* FIXME don't raise here */
10501 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10505 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10507 klass = mono_class_from_mono_type (res);
10509 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10510 mono_domain_lock (domain);
10512 if (!image_is_dynamic (klass->image)) {
10513 mono_class_setup_supertypes (klass);
10515 if (!domain->type_hash)
10516 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10517 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10518 mono_g_hash_table_insert (domain->type_hash, res, type);
10520 mono_domain_unlock (domain);
10521 mono_loader_unlock ();
10525 * LOCKING: Assumes the loader lock is held.
10527 static MonoMethodSignature*
10528 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10530 MonoMethodSignature *sig;
10533 count = parameters? mono_array_length (parameters): 0;
10535 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10536 sig->param_count = count;
10537 sig->sentinelpos = -1; /* FIXME */
10538 for (i = 0; i < count; ++i) {
10539 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10540 mono_error_raise_exception (&error); /* FIXME don't raise here */
10546 * LOCKING: Assumes the loader lock is held.
10548 static MonoMethodSignature*
10549 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10550 MonoMethodSignature *sig;
10552 sig = parameters_to_signature (image, ctor->parameters);
10553 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10554 sig->ret = &mono_defaults.void_class->byval_arg;
10559 * LOCKING: Assumes the loader lock is held.
10561 static MonoMethodSignature*
10562 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10564 MonoMethodSignature *sig;
10566 sig = parameters_to_signature (image, method->parameters);
10567 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10568 if (method->rtype) {
10569 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10570 mono_error_raise_exception (&error); /* FIXME don't raise here */
10572 sig->ret = &mono_defaults.void_class->byval_arg;
10574 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10578 static MonoMethodSignature*
10579 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10581 MonoMethodSignature *sig;
10583 sig = parameters_to_signature (NULL, method->parameters);
10584 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10585 if (method->rtype) {
10586 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10587 mono_error_raise_exception (&error); /* FIXME don't raise here */
10589 sig->ret = &mono_defaults.void_class->byval_arg;
10591 sig->generic_param_count = 0;
10596 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10599 MonoClass *klass = mono_object_class (prop);
10600 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10601 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10602 *name = mono_string_to_utf8 (pb->name);
10603 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10604 mono_error_raise_exception (&error); /* FIXME don't raise here */
10606 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10607 *name = g_strdup (p->property->name);
10608 if (p->property->get)
10609 *type = mono_method_signature (p->property->get)->ret;
10611 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10616 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10619 MonoClass *klass = mono_object_class (field);
10620 if (strcmp (klass->name, "FieldBuilder") == 0) {
10621 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10622 *name = mono_string_to_utf8 (fb->name);
10623 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10624 mono_error_raise_exception (&error); /* FIXME don't raise here */
10626 MonoReflectionField *f = (MonoReflectionField *)field;
10627 *name = g_strdup (mono_field_get_name (f->field));
10628 *type = f->field->type;
10632 #else /* DISABLE_REFLECTION_EMIT */
10635 mono_reflection_register_with_runtime (MonoReflectionType *type)
10637 /* This is empty */
10641 is_sre_type_builder (MonoClass *klass)
10647 is_sre_generic_instance (MonoClass *klass)
10653 init_type_builder_generics (MonoObject *type)
10657 #endif /* !DISABLE_REFLECTION_EMIT */
10661 is_sr_mono_field (MonoClass *klass)
10663 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10667 is_sr_mono_property (MonoClass *klass)
10669 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10673 is_sr_mono_method (MonoClass *klass)
10675 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10679 is_sr_mono_cmethod (MonoClass *klass)
10681 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10685 is_sr_mono_generic_method (MonoClass *klass)
10687 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10691 is_sr_mono_generic_cmethod (MonoClass *klass)
10693 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10697 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10699 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10703 is_usertype (MonoReflectionType *ref)
10705 MonoClass *klass = mono_object_class (ref);
10706 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10709 static MonoReflectionType*
10710 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10712 mono_error_init (error);
10713 if (!type || type->type)
10716 if (is_usertype (type)) {
10717 type = mono_reflection_type_get_underlying_system_type (type, error);
10718 return_val_if_nok (error, NULL);
10719 if (is_usertype (type)) {
10720 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10728 * Encode a value in a custom attribute stream of bytes.
10729 * The value to encode is either supplied as an object in argument val
10730 * (valuetypes are boxed), or as a pointer to the data in the
10732 * @type represents the type of the value
10733 * @buffer is the start of the buffer
10734 * @p the current position in the buffer
10735 * @buflen contains the size of the buffer and is used to return the new buffer size
10736 * if this needs to be realloced.
10737 * @retbuffer and @retp return the start and the position of the buffer
10740 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10743 MonoTypeEnum simple_type;
10745 if ((p-buffer) + 10 >= *buflen) {
10748 newbuf = (char *)g_realloc (buffer, *buflen);
10749 p = newbuf + (p-buffer);
10753 argval = ((char*)arg + sizeof (MonoObject));
10754 simple_type = type->type;
10756 switch (simple_type) {
10757 case MONO_TYPE_BOOLEAN:
10762 case MONO_TYPE_CHAR:
10765 swap_with_size (p, argval, 2, 1);
10771 swap_with_size (p, argval, 4, 1);
10775 swap_with_size (p, argval, 8, 1);
10780 swap_with_size (p, argval, 8, 1);
10783 case MONO_TYPE_VALUETYPE:
10784 if (type->data.klass->enumtype) {
10785 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10788 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10791 case MONO_TYPE_STRING: {
10798 str = mono_string_to_utf8 ((MonoString*)arg);
10799 slen = strlen (str);
10800 if ((p-buffer) + 10 + slen >= *buflen) {
10804 newbuf = (char *)g_realloc (buffer, *buflen);
10805 p = newbuf + (p-buffer);
10808 mono_metadata_encode_value (slen, p, &p);
10809 memcpy (p, str, slen);
10814 case MONO_TYPE_CLASS: {
10817 MonoType *arg_type;
10823 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10824 mono_error_raise_exception (&error); /* FIXME don't raise here */
10825 str = type_get_qualified_name (arg_type, NULL);
10826 slen = strlen (str);
10827 if ((p-buffer) + 10 + slen >= *buflen) {
10831 newbuf = (char *)g_realloc (buffer, *buflen);
10832 p = newbuf + (p-buffer);
10835 mono_metadata_encode_value (slen, p, &p);
10836 memcpy (p, str, slen);
10841 case MONO_TYPE_SZARRAY: {
10843 MonoClass *eclass, *arg_eclass;
10846 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10849 len = mono_array_length ((MonoArray*)arg);
10851 *p++ = (len >> 8) & 0xff;
10852 *p++ = (len >> 16) & 0xff;
10853 *p++ = (len >> 24) & 0xff;
10855 *retbuffer = buffer;
10856 eclass = type->data.klass;
10857 arg_eclass = mono_object_class (arg)->element_class;
10860 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10861 eclass = mono_defaults.object_class;
10863 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10864 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10865 int elsize = mono_class_array_element_size (arg_eclass);
10866 for (i = 0; i < len; ++i) {
10867 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10870 } else if (eclass->valuetype && arg_eclass->valuetype) {
10871 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10872 int elsize = mono_class_array_element_size (eclass);
10873 for (i = 0; i < len; ++i) {
10874 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10878 for (i = 0; i < len; ++i) {
10879 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10884 case MONO_TYPE_OBJECT: {
10890 * The parameter type is 'object' but the type of the actual
10891 * argument is not. So we have to add type information to the blob
10892 * too. This is completely undocumented in the spec.
10896 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10901 klass = mono_object_class (arg);
10903 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10906 } else if (klass->enumtype) {
10908 } else if (klass == mono_defaults.string_class) {
10909 simple_type = MONO_TYPE_STRING;
10912 } else if (klass->rank == 1) {
10914 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10915 /* See Partition II, Appendix B3 */
10918 *p++ = klass->element_class->byval_arg.type;
10919 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10921 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10922 *p++ = simple_type = klass->byval_arg.type;
10925 g_error ("unhandled type in custom attr");
10927 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10928 slen = strlen (str);
10929 if ((p-buffer) + 10 + slen >= *buflen) {
10933 newbuf = (char *)g_realloc (buffer, *buflen);
10934 p = newbuf + (p-buffer);
10937 mono_metadata_encode_value (slen, p, &p);
10938 memcpy (p, str, slen);
10941 simple_type = mono_class_enum_basetype (klass)->type;
10945 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10948 *retbuffer = buffer;
10952 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10954 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10955 char *str = type_get_qualified_name (type, NULL);
10956 int slen = strlen (str);
10960 * This seems to be optional...
10963 mono_metadata_encode_value (slen, p, &p);
10964 memcpy (p, str, slen);
10967 } else if (type->type == MONO_TYPE_OBJECT) {
10969 } else if (type->type == MONO_TYPE_CLASS) {
10970 /* it should be a type: encode_cattr_value () has the check */
10973 mono_metadata_encode_value (type->type, p, &p);
10974 if (type->type == MONO_TYPE_SZARRAY)
10975 /* See the examples in Partition VI, Annex B */
10976 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10982 #ifndef DISABLE_REFLECTION_EMIT
10984 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10987 /* Preallocate a large enough buffer */
10988 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10989 char *str = type_get_qualified_name (type, NULL);
10990 len = strlen (str);
10992 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10993 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10994 len = strlen (str);
10999 len += strlen (name);
11001 if ((p-buffer) + 20 + len >= *buflen) {
11005 newbuf = (char *)g_realloc (buffer, *buflen);
11006 p = newbuf + (p-buffer);
11010 encode_field_or_prop_type (type, p, &p);
11012 len = strlen (name);
11013 mono_metadata_encode_value (len, p, &p);
11014 memcpy (p, name, len);
11016 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11018 *retbuffer = buffer;
11022 * mono_reflection_get_custom_attrs_blob:
11023 * @ctor: custom attribute constructor
11024 * @ctorArgs: arguments o the constructor
11030 * Creates the blob of data that needs to be saved in the metadata and that represents
11031 * the custom attributed described by @ctor, @ctorArgs etc.
11032 * Returns: a Byte array representing the blob of data.
11035 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11038 MonoMethodSignature *sig;
11043 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11044 /* sig is freed later so allocate it in the heap */
11045 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11047 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11050 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11052 p = buffer = (char *)g_malloc (buflen);
11053 /* write the prolog */
11056 for (i = 0; i < sig->param_count; ++i) {
11057 arg = mono_array_get (ctorArgs, MonoObject*, i);
11058 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11062 i += mono_array_length (properties);
11064 i += mono_array_length (fields);
11066 *p++ = (i >> 8) & 0xff;
11069 for (i = 0; i < mono_array_length (properties); ++i) {
11073 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11074 get_prop_name_and_type (prop, &pname, &ptype);
11075 *p++ = 0x54; /* PROPERTY signature */
11076 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11083 for (i = 0; i < mono_array_length (fields); ++i) {
11087 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11088 get_field_name_and_type (field, &fname, &ftype);
11089 *p++ = 0x53; /* FIELD signature */
11090 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11095 g_assert (p - buffer <= buflen);
11096 buflen = p - buffer;
11097 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11098 p = mono_array_addr (result, char, 0);
11099 memcpy (p, buffer, buflen);
11101 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11107 * mono_reflection_setup_internal_class:
11108 * @tb: a TypeBuilder object
11110 * Creates a MonoClass that represents the TypeBuilder.
11111 * This is a trick that lets us simplify a lot of reflection code
11112 * (and will allow us to support Build and Run assemblies easier).
11115 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11118 MonoClass *klass, *parent;
11120 RESOLVE_TYPE (tb->parent, &error);
11121 mono_error_raise_exception (&error); /* FIXME don't raise here */
11123 mono_loader_lock ();
11126 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11127 if (!is_ok (&error)) {
11128 mono_loader_unlock ();
11129 mono_error_raise_exception (&error); /* FIXME don't raise here */
11131 /* check so we can compile corlib correctly */
11132 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11133 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11134 parent = parent_type->data.klass;
11136 parent = mono_class_from_mono_type (parent_type);
11142 /* the type has already being created: it means we just have to change the parent */
11143 if (tb->type.type) {
11144 klass = mono_class_from_mono_type (tb->type.type);
11145 klass->parent = NULL;
11146 /* fool mono_class_setup_parent */
11147 klass->supertypes = NULL;
11148 mono_class_setup_parent (klass, parent);
11149 mono_class_setup_mono_type (klass);
11150 mono_loader_unlock ();
11154 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11156 klass->image = &tb->module->dynamic_image->image;
11158 klass->inited = 1; /* we lie to the runtime */
11159 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11160 if (!mono_error_ok (&error))
11162 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11163 if (!mono_error_ok (&error))
11165 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11166 klass->flags = tb->attrs;
11168 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11170 klass->element_class = klass;
11172 if (mono_class_get_ref_info (klass) == NULL) {
11174 mono_class_set_ref_info (klass, tb);
11176 /* Put into cache so mono_class_get_checked () will find it.
11177 Skip nested types as those should not be available on the global scope. */
11178 if (!tb->nesting_type)
11179 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11182 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11183 by performing a mono_class_get which does the full resolution.
11185 Working around this semantics would require us to write a lot of code for no clear advantage.
11187 mono_image_append_class_to_reflection_info_set (klass);
11189 g_assert (mono_class_get_ref_info (klass) == tb);
11192 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11194 if (parent != NULL) {
11195 mono_class_setup_parent (klass, parent);
11196 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11197 const char *old_n = klass->name;
11198 /* trick to get relative numbering right when compiling corlib */
11199 klass->name = "BuildingObject";
11200 mono_class_setup_parent (klass, mono_defaults.object_class);
11201 klass->name = old_n;
11204 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11205 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11206 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11207 klass->instance_size = sizeof (MonoObject);
11208 klass->size_inited = 1;
11209 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11212 mono_class_setup_mono_type (klass);
11214 mono_class_setup_supertypes (klass);
11217 * FIXME: handle interfaces.
11220 tb->type.type = &klass->byval_arg;
11222 if (tb->nesting_type) {
11223 g_assert (tb->nesting_type->type);
11224 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11225 if (!is_ok (&error)) goto failure;
11226 klass->nested_in = mono_class_from_mono_type (nesting_type);
11229 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11231 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11233 mono_loader_unlock ();
11237 mono_loader_unlock ();
11238 mono_error_raise_exception (&error);
11242 * mono_reflection_setup_generic_class:
11243 * @tb: a TypeBuilder object
11245 * Setup the generic class before adding the first generic parameter.
11248 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11253 * mono_reflection_create_generic_class:
11254 * @tb: a TypeBuilder object
11256 * Creates the generic class after all generic parameters have been added.
11259 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11265 klass = mono_class_from_mono_type (tb->type.type);
11267 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11269 if (klass->generic_container || (count == 0))
11272 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11274 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11276 klass->generic_container->owner.klass = klass;
11277 klass->generic_container->type_argc = count;
11278 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11280 klass->is_generic = 1;
11282 for (i = 0; i < count; i++) {
11283 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11284 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11285 mono_error_raise_exception (&error); /* FIXME don't raise here */
11286 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11287 klass->generic_container->type_params [i] = *param;
11288 /*Make sure we are a diferent type instance */
11289 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11290 klass->generic_container->type_params [i].info.pklass = NULL;
11291 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11293 g_assert (klass->generic_container->type_params [i].param.owner);
11296 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11300 * mono_reflection_create_internal_class:
11301 * @tb: a TypeBuilder object
11303 * Actually create the MonoClass that is associated with the TypeBuilder.
11306 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11311 klass = mono_class_from_mono_type (tb->type.type);
11313 mono_loader_lock ();
11314 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11315 MonoReflectionFieldBuilder *fb;
11317 MonoType *enum_basetype;
11319 g_assert (tb->fields != NULL);
11320 g_assert (mono_array_length (tb->fields) >= 1);
11322 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11324 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11325 if (!is_ok (&error)) {
11326 mono_loader_unlock ();
11327 mono_error_raise_exception (&error); /* FIXME don't raise here */
11329 if (!mono_type_is_valid_enum_basetype (field_type)) {
11330 mono_loader_unlock ();
11334 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11335 if (!is_ok (&error)) {
11336 mono_loader_unlock ();
11337 mono_error_raise_exception (&error); /* FIXME don't raise here */
11339 klass->element_class = mono_class_from_mono_type (enum_basetype);
11340 if (!klass->element_class)
11341 klass->element_class = mono_class_from_mono_type (enum_basetype);
11344 * get the element_class from the current corlib.
11346 ec = default_class_from_mono_type (enum_basetype);
11347 klass->instance_size = ec->instance_size;
11348 klass->size_inited = 1;
11350 * this is almost safe to do with enums and it's needed to be able
11351 * to create objects of the enum type (for use in SetConstant).
11353 /* FIXME: Does this mean enums can't have method overrides ? */
11354 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11356 mono_loader_unlock ();
11359 static MonoMarshalSpec*
11360 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11361 MonoReflectionMarshal *minfo)
11364 MonoMarshalSpec *res;
11366 res = image_g_new0 (image, MonoMarshalSpec, 1);
11367 res->native = (MonoMarshalNative)minfo->type;
11369 switch (minfo->type) {
11370 case MONO_NATIVE_LPARRAY:
11371 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11372 if (minfo->has_size) {
11373 res->data.array_data.param_num = minfo->param_num;
11374 res->data.array_data.num_elem = minfo->count;
11375 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11378 res->data.array_data.param_num = -1;
11379 res->data.array_data.num_elem = -1;
11380 res->data.array_data.elem_mult = -1;
11384 case MONO_NATIVE_BYVALTSTR:
11385 case MONO_NATIVE_BYVALARRAY:
11386 res->data.array_data.num_elem = minfo->count;
11389 case MONO_NATIVE_CUSTOM:
11390 if (minfo->marshaltyperef) {
11391 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11392 mono_error_raise_exception (&error); /* FIXME don't raise here */
11393 res->data.custom_data.custom_name =
11394 type_get_fully_qualified_name (marshaltyperef);
11396 if (minfo->mcookie)
11397 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11406 #endif /* !DISABLE_REFLECTION_EMIT */
11408 MonoReflectionMarshalAsAttribute*
11409 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11410 MonoMarshalSpec *spec, MonoError *error)
11412 MonoReflectionType *rt;
11413 MonoReflectionMarshalAsAttribute *minfo;
11416 mono_error_init (error);
11418 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11421 minfo->utype = spec->native;
11423 switch (minfo->utype) {
11424 case MONO_NATIVE_LPARRAY:
11425 minfo->array_subtype = spec->data.array_data.elem_type;
11426 minfo->size_const = spec->data.array_data.num_elem;
11427 if (spec->data.array_data.param_num != -1)
11428 minfo->size_param_index = spec->data.array_data.param_num;
11431 case MONO_NATIVE_BYVALTSTR:
11432 case MONO_NATIVE_BYVALARRAY:
11433 minfo->size_const = spec->data.array_data.num_elem;
11436 case MONO_NATIVE_CUSTOM:
11437 if (spec->data.custom_data.custom_name) {
11438 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11440 rt = mono_type_get_object_checked (domain, mtype, error);
11444 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11447 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11449 if (spec->data.custom_data.cookie)
11450 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11460 #ifndef DISABLE_REFLECTION_EMIT
11462 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11463 ReflectionMethodBuilder *rmb,
11464 MonoMethodSignature *sig)
11468 MonoMethodWrapper *wrapperm;
11469 MonoMarshalSpec **specs;
11470 MonoReflectionMethodAux *method_aux;
11475 mono_error_init (&error);
11477 * Methods created using a MethodBuilder should have their memory allocated
11478 * inside the image mempool, while dynamic methods should have their memory
11481 dynamic = rmb->refs != NULL;
11482 image = dynamic ? NULL : klass->image;
11485 g_assert (!klass->generic_class);
11487 mono_loader_lock ();
11489 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11490 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11491 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11493 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11495 wrapperm = (MonoMethodWrapper*)m;
11497 m->dynamic = dynamic;
11499 m->flags = rmb->attrs;
11500 m->iflags = rmb->iattrs;
11501 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11503 m->signature = sig;
11504 m->sre_method = TRUE;
11505 m->skip_visibility = rmb->skip_visibility;
11506 if (rmb->table_idx)
11507 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11509 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11510 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11511 m->string_ctor = 1;
11513 m->signature->pinvoke = 1;
11514 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11515 m->signature->pinvoke = 1;
11517 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11519 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11520 g_assert (mono_error_ok (&error));
11521 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11522 g_assert (mono_error_ok (&error));
11524 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11526 if (image_is_dynamic (klass->image))
11527 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11529 mono_loader_unlock ();
11532 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11533 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11534 MonoMethodHeader *header;
11536 gint32 max_stack, i;
11537 gint32 num_locals = 0;
11538 gint32 num_clauses = 0;
11542 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11543 code_size = rmb->ilgen->code_len;
11544 max_stack = rmb->ilgen->max_stack;
11545 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11546 if (rmb->ilgen->ex_handlers)
11547 num_clauses = method_count_clauses (rmb->ilgen);
11550 code = mono_array_addr (rmb->code, guint8, 0);
11551 code_size = mono_array_length (rmb->code);
11552 /* we probably need to run a verifier on the code... */
11562 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11563 header->code_size = code_size;
11564 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11565 memcpy ((char*)header->code, code, code_size);
11566 header->max_stack = max_stack;
11567 header->init_locals = rmb->init_locals;
11568 header->num_locals = num_locals;
11570 for (i = 0; i < num_locals; ++i) {
11571 MonoReflectionLocalBuilder *lb =
11572 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11574 header->locals [i] = image_g_new0 (image, MonoType, 1);
11575 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11576 mono_error_assert_ok (&error);
11577 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11580 header->num_clauses = num_clauses;
11582 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11583 rmb->ilgen, num_clauses);
11586 wrapperm->header = header;
11589 if (rmb->generic_params) {
11590 int count = mono_array_length (rmb->generic_params);
11591 MonoGenericContainer *container = rmb->generic_container;
11593 g_assert (container);
11595 container->type_argc = count;
11596 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11597 container->owner.method = m;
11598 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11600 m->is_generic = TRUE;
11601 mono_method_set_generic_container (m, container);
11603 for (i = 0; i < count; i++) {
11604 MonoReflectionGenericParam *gp =
11605 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11606 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11607 mono_error_assert_ok (&error);
11608 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11609 container->type_params [i] = *param;
11613 * The method signature might have pointers to generic parameters that belong to other methods.
11614 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11615 * generic parameters.
11617 for (i = 0; i < m->signature->param_count; ++i) {
11618 MonoType *t = m->signature->params [i];
11619 if (t->type == MONO_TYPE_MVAR) {
11620 MonoGenericParam *gparam = t->data.generic_param;
11621 if (gparam->num < count) {
11622 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11623 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11629 if (klass->generic_container) {
11630 container->parent = klass->generic_container;
11631 container->context.class_inst = klass->generic_container->context.class_inst;
11633 container->context.method_inst = mono_get_shared_generic_inst (container);
11637 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11641 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11643 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11644 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11645 for (i = 0; i < rmb->nrefs; ++i)
11646 data [i + 1] = rmb->refs [i];
11651 /* Parameter info */
11654 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11655 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11656 for (i = 0; i <= m->signature->param_count; ++i) {
11657 MonoReflectionParamBuilder *pb;
11658 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11659 if ((i > 0) && (pb->attrs)) {
11660 /* Make a copy since it might point to a shared type structure */
11661 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11662 m->signature->params [i - 1]->attrs = pb->attrs;
11665 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11666 MonoDynamicImage *assembly;
11668 MonoTypeEnum def_type;
11672 if (!method_aux->param_defaults) {
11673 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11674 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11676 assembly = (MonoDynamicImage*)klass->image;
11677 idx = encode_constant (assembly, pb->def_value, &def_type);
11678 /* Copy the data from the blob since it might get realloc-ed */
11679 p = assembly->blob.data + idx;
11680 len = mono_metadata_decode_blob_size (p, &p2);
11682 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11683 method_aux->param_default_types [i] = def_type;
11684 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11688 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11689 g_assert (mono_error_ok (&error));
11692 if (!method_aux->param_cattr)
11693 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11694 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11700 /* Parameter marshalling */
11703 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11704 MonoReflectionParamBuilder *pb;
11705 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11706 if (pb->marshal_info) {
11708 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11709 specs [pb->position] =
11710 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11714 if (specs != NULL) {
11716 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11717 method_aux->param_marshall = specs;
11720 if (image_is_dynamic (klass->image) && method_aux)
11721 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11723 mono_loader_unlock ();
11729 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11731 ReflectionMethodBuilder rmb;
11732 MonoMethodSignature *sig;
11734 mono_loader_lock ();
11735 sig = ctor_builder_to_signature (klass->image, mb);
11736 mono_loader_unlock ();
11738 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11741 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11742 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11744 /* If we are in a generic class, we might be called multiple times from inflate_method */
11745 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11746 /* ilgen is no longer needed */
11750 return mb->mhandle;
11754 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11756 ReflectionMethodBuilder rmb;
11757 MonoMethodSignature *sig;
11759 mono_error_init (error);
11761 mono_loader_lock ();
11762 sig = method_builder_to_signature (klass->image, mb);
11763 mono_loader_unlock ();
11765 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11768 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11769 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11771 /* If we are in a generic class, we might be called multiple times from inflate_method */
11772 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11773 /* ilgen is no longer needed */
11776 return mb->mhandle;
11779 static MonoClassField*
11780 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11782 MonoClassField *field;
11786 field = g_new0 (MonoClassField, 1);
11788 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11789 g_assert (mono_error_ok (&error));
11790 if (fb->attrs || fb->modreq || fb->modopt) {
11791 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11792 if (!is_ok (&error)) {
11794 mono_error_raise_exception (&error); /* FIXME don't raise here */
11796 field->type = mono_metadata_type_dup (NULL, type);
11797 field->type->attrs = fb->attrs;
11799 g_assert (image_is_dynamic (klass->image));
11800 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11801 g_free (field->type);
11802 field->type = mono_metadata_type_dup (klass->image, custom);
11805 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11806 if (!is_ok (&error)) {
11808 mono_error_raise_exception (&error); /* FIXME don't raise here */
11811 if (fb->offset != -1)
11812 field->offset = fb->offset;
11813 field->parent = klass;
11814 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11816 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11823 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11827 MonoReflectionTypeBuilder *tb = NULL;
11828 gboolean is_dynamic = FALSE;
11829 MonoClass *geninst;
11831 mono_loader_lock ();
11833 if (is_sre_type_builder (mono_object_class (type))) {
11834 tb = (MonoReflectionTypeBuilder *) type;
11837 } else if (is_sre_generic_instance (mono_object_class (type))) {
11838 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11839 MonoReflectionType *gtd = rgi->generic_type;
11841 if (is_sre_type_builder (mono_object_class (gtd))) {
11842 tb = (MonoReflectionTypeBuilder *)gtd;
11847 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11848 if (tb && tb->generic_container)
11849 mono_reflection_create_generic_class (tb);
11851 MonoType *t = mono_reflection_type_get_handle (type, &error);
11852 mono_error_raise_exception (&error); /* FIXME don't raise here */
11854 klass = mono_class_from_mono_type (t);
11855 if (!klass->generic_container) {
11856 mono_loader_unlock ();
11860 if (klass->wastypebuilder) {
11861 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11866 mono_loader_unlock ();
11868 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11870 return &geninst->byval_arg;
11874 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11876 MonoGenericClass *gclass;
11877 MonoGenericInst *inst;
11879 g_assert (klass->generic_container);
11881 inst = mono_metadata_get_generic_inst (type_argc, types);
11882 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11884 return mono_generic_class_get_class (gclass);
11887 MonoReflectionMethod*
11888 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11892 MonoMethod *method, *inflated;
11893 MonoMethodInflated *imethod;
11894 MonoGenericContext tmp_context;
11895 MonoGenericInst *ginst;
11896 MonoType **type_argv;
11899 /*FIXME but this no longer should happen*/
11900 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11901 #ifndef DISABLE_REFLECTION_EMIT
11902 MonoReflectionMethodBuilder *mb = NULL;
11906 mb = (MonoReflectionMethodBuilder *) rmethod;
11907 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11908 mono_error_raise_exception (&error); /* FIXME don't raise here */
11909 klass = mono_class_from_mono_type (tb);
11911 method = methodbuilder_to_mono_method (klass, mb, &error);
11913 mono_error_raise_exception (&error); /* FIXME don't raise here */
11915 g_assert_not_reached ();
11919 method = rmethod->method;
11922 klass = method->klass;
11924 if (method->is_inflated)
11925 method = ((MonoMethodInflated *) method)->declaring;
11927 count = mono_method_signature (method)->generic_param_count;
11928 if (count != mono_array_length (types))
11931 type_argv = g_new0 (MonoType *, count);
11932 for (i = 0; i < count; i++) {
11933 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11934 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11935 if (!is_ok (&error)) {
11936 g_free (type_argv);
11937 mono_error_raise_exception (&error); /* FIXME don't raise here */
11940 ginst = mono_metadata_get_generic_inst (count, type_argv);
11941 g_free (type_argv);
11943 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11944 tmp_context.method_inst = ginst;
11946 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11947 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11948 imethod = (MonoMethodInflated *) inflated;
11950 /*FIXME but I think this is no longer necessary*/
11951 if (image_is_dynamic (method->klass->image)) {
11952 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11954 * This table maps metadata structures representing inflated methods/fields
11955 * to the reflection objects representing their generic definitions.
11957 mono_image_lock ((MonoImage*)image);
11958 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11959 mono_image_unlock ((MonoImage*)image);
11962 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11963 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11965 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11966 mono_error_raise_exception (&error); /* FIXME don't raise here */
11970 #ifndef DISABLE_REFLECTION_EMIT
11972 static MonoMethod *
11973 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11975 MonoMethodInflated *imethod;
11976 MonoGenericContext *context;
11980 * With generic code sharing the klass might not be inflated.
11981 * This can happen because classes inflated with their own
11982 * type arguments are "normalized" to the uninflated class.
11984 if (!klass->generic_class)
11987 context = mono_class_get_context (klass);
11989 if (klass->method.count && klass->methods) {
11990 /* Find the already created inflated method */
11991 for (i = 0; i < klass->method.count; ++i) {
11992 g_assert (klass->methods [i]->is_inflated);
11993 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11996 g_assert (i < klass->method.count);
11997 imethod = (MonoMethodInflated*)klass->methods [i];
12000 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12001 mono_error_assert_ok (&error);
12004 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12005 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12007 mono_image_lock ((MonoImage*)image);
12008 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12009 mono_image_unlock ((MonoImage*)image);
12011 return (MonoMethod *) imethod;
12014 static MonoMethod *
12015 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12017 MonoMethod *method;
12020 mono_error_init (error);
12022 MonoClass *type_class = mono_object_class (type);
12024 if (is_sre_generic_instance (type_class)) {
12025 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12026 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12027 return_val_if_nok (error, NULL);
12028 gklass = mono_class_from_mono_type (generic_type);
12029 } else if (is_sre_type_builder (type_class)) {
12030 MonoType *t = mono_reflection_type_get_handle (type, error);
12031 return_val_if_nok (error, NULL);
12032 gklass = mono_class_from_mono_type (t);
12033 } else if (type->type) {
12034 gklass = mono_class_from_mono_type (type->type);
12035 gklass = mono_class_get_generic_type_definition (gklass);
12037 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12040 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12041 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12042 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12044 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12048 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12049 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12052 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12053 method = ((MonoReflectionMethod *) obj)->method;
12055 method = NULL; /* prevent compiler warning */
12056 g_error ("can't handle type %s", obj->vtable->klass->name);
12059 MonoType *t = mono_reflection_type_get_handle (type, error);
12060 return_val_if_nok (error, NULL);
12061 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12064 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12066 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12069 MonoGenericClass *gclass;
12070 MonoDynamicGenericClass *dgclass;
12071 MonoClass *klass, *gklass;
12075 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12076 mono_error_raise_exception (&error); /* FIXME don't raise here */
12077 klass = mono_class_from_mono_type (gtype);
12078 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12079 gclass = gtype->data.generic_class;
12081 if (!gclass->is_dynamic)
12084 dgclass = (MonoDynamicGenericClass *) gclass;
12086 if (dgclass->initialized)
12089 gklass = gclass->container_class;
12090 mono_class_init (gklass);
12092 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12094 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12095 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12096 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12098 for (i = 0; i < dgclass->count_fields; i++) {
12100 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12101 MonoClassField *field, *inflated_field = NULL;
12103 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12104 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12105 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12106 field = ((MonoReflectionField *) obj)->field;
12108 field = NULL; /* prevent compiler warning */
12109 g_assert_not_reached ();
12112 dgclass->fields [i] = *field;
12113 dgclass->fields [i].parent = klass;
12114 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12115 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12116 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12117 dgclass->field_generic_types [i] = field->type;
12118 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12119 dgclass->field_objects [i] = obj;
12121 if (inflated_field) {
12122 g_free (inflated_field);
12124 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12128 dgclass->initialized = TRUE;
12132 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12134 MonoDynamicGenericClass *dgclass;
12137 g_assert (gclass->is_dynamic);
12139 dgclass = (MonoDynamicGenericClass *)gclass;
12141 for (i = 0; i < dgclass->count_fields; ++i) {
12142 MonoClassField *field = dgclass->fields + i;
12143 mono_metadata_free_type (field->type);
12144 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12149 fix_partial_generic_class (MonoClass *klass)
12151 MonoClass *gklass = klass->generic_class->container_class;
12152 MonoDynamicGenericClass *dgclass;
12155 if (klass->wastypebuilder)
12158 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12159 if (klass->parent != gklass->parent) {
12161 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12162 if (mono_error_ok (&error)) {
12163 MonoClass *parent = mono_class_from_mono_type (parent_type);
12164 mono_metadata_free_type (parent_type);
12165 if (parent != klass->parent) {
12166 /*fool mono_class_setup_parent*/
12167 klass->supertypes = NULL;
12168 mono_class_setup_parent (klass, parent);
12171 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12172 mono_error_cleanup (&error);
12173 if (gklass->wastypebuilder)
12174 klass->wastypebuilder = TRUE;
12179 if (!dgclass->initialized)
12182 if (klass->method.count != gklass->method.count) {
12183 klass->method.count = gklass->method.count;
12184 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12186 for (i = 0; i < klass->method.count; i++) {
12188 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12189 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12190 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12194 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12195 klass->interface_count = gklass->interface_count;
12196 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12197 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12199 for (i = 0; i < gklass->interface_count; ++i) {
12201 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12202 mono_error_raise_exception (&error); /* FIXME don't raise here */
12204 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12205 mono_metadata_free_type (iface_type);
12207 ensure_runtime_vtable (klass->interfaces [i], &error);
12208 mono_error_raise_exception (&error); /* FIXME don't raise here */
12210 klass->interfaces_inited = 1;
12213 if (klass->field.count != gklass->field.count) {
12214 klass->field.count = gklass->field.count;
12215 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12217 for (i = 0; i < klass->field.count; i++) {
12219 klass->fields [i] = gklass->fields [i];
12220 klass->fields [i].parent = klass;
12221 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12222 mono_error_raise_exception (&error); /* FIXME don't raise here */
12226 /*We can only finish with this klass once it's parent has as well*/
12227 if (gklass->wastypebuilder)
12228 klass->wastypebuilder = TRUE;
12233 * ensure_generic_class_runtime_vtable:
12234 * @klass a generic class
12235 * @error set on error
12237 * Ensures that the generic container of @klass has a vtable and
12238 * returns TRUE on success. On error returns FALSE and sets @error.
12241 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12243 MonoClass *gklass = klass->generic_class->container_class;
12245 mono_error_init (error);
12247 if (!ensure_runtime_vtable (gklass, error))
12250 fix_partial_generic_class (klass);
12256 * ensure_runtime_vtable:
12258 * @error set on error
12260 * Ensures that @klass has a vtable and returns TRUE on success. On
12261 * error returns FALSE and sets @error.
12264 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12266 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12269 mono_error_init (error);
12271 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12274 if (!ensure_runtime_vtable (klass->parent, error))
12278 num = tb->ctors? mono_array_length (tb->ctors): 0;
12279 num += tb->num_methods;
12280 klass->method.count = num;
12281 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12282 num = tb->ctors? mono_array_length (tb->ctors): 0;
12283 for (i = 0; i < num; ++i) {
12284 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12287 klass->methods [i] = ctor;
12289 num = tb->num_methods;
12291 for (i = 0; i < num; ++i) {
12292 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12295 klass->methods [j++] = meth;
12298 if (tb->interfaces) {
12299 klass->interface_count = mono_array_length (tb->interfaces);
12300 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12301 for (i = 0; i < klass->interface_count; ++i) {
12302 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12303 return_val_if_nok (error, FALSE);
12304 klass->interfaces [i] = mono_class_from_mono_type (iface);
12305 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12308 klass->interfaces_inited = 1;
12310 } else if (klass->generic_class){
12311 if (!ensure_generic_class_runtime_vtable (klass, error))
12315 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12317 for (i = 0; i < klass->method.count; ++i) {
12318 MonoMethod *im = klass->methods [i];
12319 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12320 im->slot = slot_num++;
12323 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12324 mono_class_setup_interface_offsets (klass);
12325 mono_class_setup_interface_id (klass);
12329 * The generic vtable is needed even if image->run is not set since some
12330 * runtime code like ves_icall_Type_GetMethodsByName depends on
12331 * method->slot being defined.
12335 * tb->methods could not be freed since it is used for determining
12336 * overrides during dynamic vtable construction.
12343 mono_reflection_method_get_handle (MonoObject *method)
12346 MonoClass *klass = mono_object_class (method);
12347 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12348 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12349 return sr_method->method;
12351 if (is_sre_method_builder (klass)) {
12352 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12353 return mb->mhandle;
12355 if (is_sre_method_on_tb_inst (klass)) {
12356 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12357 MonoMethod *result;
12358 /*FIXME move this to a proper method and unify with resolve_object*/
12359 if (m->method_args) {
12360 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12361 mono_error_raise_exception (&error); /* FIXME don't raise here */
12363 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12364 mono_error_raise_exception (&error); /* FIXME don't raise here */
12365 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12366 MonoMethod *mono_method;
12368 if (is_sre_method_builder (mono_object_class (m->mb)))
12369 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12370 else if (is_sr_mono_method (mono_object_class (m->mb)))
12371 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12373 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)));
12375 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12380 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12385 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12387 MonoReflectionTypeBuilder *tb;
12389 MonoReflectionMethod *m;
12392 *num_overrides = 0;
12394 g_assert (image_is_dynamic (klass->image));
12396 if (!mono_class_get_ref_info (klass))
12399 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12401 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12405 for (i = 0; i < tb->num_methods; ++i) {
12406 MonoReflectionMethodBuilder *mb =
12407 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12408 if (mb->override_methods)
12409 onum += mono_array_length (mb->override_methods);
12414 *overrides = g_new0 (MonoMethod*, onum * 2);
12417 for (i = 0; i < tb->num_methods; ++i) {
12418 MonoReflectionMethodBuilder *mb =
12419 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12420 if (mb->override_methods) {
12421 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12422 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12424 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12425 (*overrides) [onum * 2 + 1] = mb->mhandle;
12427 g_assert (mb->mhandle);
12435 *num_overrides = onum;
12439 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12441 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12442 MonoReflectionFieldBuilder *fb;
12443 MonoClassField *field;
12444 MonoImage *image = klass->image;
12445 const char *p, *p2;
12447 guint32 len, idx, real_size = 0;
12449 klass->field.count = tb->num_fields;
12450 klass->field.first = 0;
12452 mono_error_init (error);
12454 if (tb->class_size) {
12455 if ((tb->packing_size & 0xffffff00) != 0) {
12456 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12457 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12460 klass->packing_size = tb->packing_size;
12461 real_size = klass->instance_size + tb->class_size;
12464 if (!klass->field.count) {
12465 klass->instance_size = MAX (klass->instance_size, real_size);
12469 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12470 mono_class_alloc_ext (klass);
12471 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12473 This is, guess what, a hack.
12474 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12475 On the static path no field class is resolved, only types are built. This is the right thing to do
12477 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12479 klass->size_inited = 1;
12481 for (i = 0; i < klass->field.count; ++i) {
12482 MonoArray *rva_data;
12483 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12484 field = &klass->fields [i];
12485 field->name = mono_string_to_utf8_image (image, fb->name, error);
12486 if (!mono_error_ok (error))
12489 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12490 return_if_nok (error);
12491 field->type = mono_metadata_type_dup (klass->image, type);
12492 field->type->attrs = fb->attrs;
12494 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12495 return_if_nok (error);
12498 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12499 char *base = mono_array_addr (rva_data, char, 0);
12500 size_t size = mono_array_length (rva_data);
12501 char *data = (char *)mono_image_alloc (klass->image, size);
12502 memcpy (data, base, size);
12503 klass->ext->field_def_values [i].data = data;
12505 if (fb->offset != -1)
12506 field->offset = fb->offset;
12507 field->parent = klass;
12508 fb->handle = field;
12509 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12511 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12512 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12514 if (fb->def_value) {
12515 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12516 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12517 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12518 /* Copy the data from the blob since it might get realloc-ed */
12519 p = assembly->blob.data + idx;
12520 len = mono_metadata_decode_blob_size (p, &p2);
12522 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12523 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12527 klass->instance_size = MAX (klass->instance_size, real_size);
12528 mono_class_layout_fields (klass);
12532 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12534 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12535 MonoReflectionPropertyBuilder *pb;
12536 MonoImage *image = klass->image;
12537 MonoProperty *properties;
12540 mono_error_init (error);
12543 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12545 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12546 klass->ext->property.first = 0;
12548 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12549 klass->ext->properties = properties;
12550 for (i = 0; i < klass->ext->property.count; ++i) {
12551 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12552 properties [i].parent = klass;
12553 properties [i].attrs = pb->attrs;
12554 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12555 if (!mono_error_ok (error))
12557 if (pb->get_method)
12558 properties [i].get = pb->get_method->mhandle;
12559 if (pb->set_method)
12560 properties [i].set = pb->set_method->mhandle;
12562 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12563 if (pb->def_value) {
12565 const char *p, *p2;
12566 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12567 if (!klass->ext->prop_def_values)
12568 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12569 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12570 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12571 /* Copy the data from the blob since it might get realloc-ed */
12572 p = assembly->blob.data + idx;
12573 len = mono_metadata_decode_blob_size (p, &p2);
12575 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12576 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12581 MonoReflectionEvent *
12582 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12585 MonoEvent *event = g_new0 (MonoEvent, 1);
12588 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12589 mono_error_raise_exception (&error); /* FIXME don't raise here */
12590 klass = mono_class_from_mono_type (type);
12592 event->parent = klass;
12593 event->attrs = eb->attrs;
12594 event->name = mono_string_to_utf8 (eb->name);
12595 if (eb->add_method)
12596 event->add = eb->add_method->mhandle;
12597 if (eb->remove_method)
12598 event->remove = eb->remove_method->mhandle;
12599 if (eb->raise_method)
12600 event->raise = eb->raise_method->mhandle;
12602 #ifndef MONO_SMALL_CONFIG
12603 if (eb->other_methods) {
12605 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12606 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12607 MonoReflectionMethodBuilder *mb =
12608 mono_array_get (eb->other_methods,
12609 MonoReflectionMethodBuilder*, j);
12610 event->other [j] = mb->mhandle;
12615 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12616 mono_error_raise_exception (&error); /* FIXME don't raise here */
12621 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12623 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12624 MonoReflectionEventBuilder *eb;
12625 MonoImage *image = klass->image;
12629 mono_error_init (error);
12632 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12634 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12635 klass->ext->event.first = 0;
12637 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12638 klass->ext->events = events;
12639 for (i = 0; i < klass->ext->event.count; ++i) {
12640 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12641 events [i].parent = klass;
12642 events [i].attrs = eb->attrs;
12643 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12644 if (!mono_error_ok (error))
12646 if (eb->add_method)
12647 events [i].add = eb->add_method->mhandle;
12648 if (eb->remove_method)
12649 events [i].remove = eb->remove_method->mhandle;
12650 if (eb->raise_method)
12651 events [i].raise = eb->raise_method->mhandle;
12653 #ifndef MONO_SMALL_CONFIG
12654 if (eb->other_methods) {
12656 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12657 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12658 MonoReflectionMethodBuilder *mb =
12659 mono_array_get (eb->other_methods,
12660 MonoReflectionMethodBuilder*, j);
12661 events [i].other [j] = mb->mhandle;
12665 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12670 remove_instantiations_of_and_ensure_contents (gpointer key,
12672 gpointer user_data)
12674 MonoType *type = (MonoType*)key;
12675 MonoClass *klass = (MonoClass*)user_data;
12677 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12678 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12685 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12687 mono_error_init (error);
12693 for (i = 0; i < mono_array_length (arr); ++i) {
12694 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12695 if (!mono_error_ok (error))
12700 MonoReflectionType*
12701 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12705 MonoDomain* domain;
12706 MonoReflectionType* res;
12709 domain = mono_object_domain (tb);
12710 klass = mono_class_from_mono_type (tb->type.type);
12713 * Check for user defined Type subclasses.
12715 RESOLVE_TYPE (tb->parent, &error);
12716 mono_error_raise_exception (&error); /* FIXME don't raise here */
12717 check_array_for_usertypes (tb->interfaces, &error);
12718 mono_error_raise_exception (&error); /*FIXME don't raise here */
12720 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12721 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12723 RESOLVE_TYPE (fb->type, &error);
12724 mono_error_raise_exception (&error); /* FIXME don't raise here */
12725 check_array_for_usertypes (fb->modreq, &error);
12726 mono_error_raise_exception (&error); /*FIXME don't raise here */
12727 check_array_for_usertypes (fb->modopt, &error);
12728 mono_error_raise_exception (&error); /*FIXME don't raise here */
12729 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12730 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12731 mono_error_raise_exception (&error); /* FIXME don't raise here */
12737 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12738 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12740 RESOLVE_TYPE (mb->rtype, &error);
12741 mono_error_raise_exception (&error); /* FIXME don't raise here */
12742 check_array_for_usertypes (mb->return_modreq, &error);
12743 mono_error_raise_exception (&error); /*FIXME don't raise here */
12744 check_array_for_usertypes (mb->return_modopt, &error);
12745 mono_error_raise_exception (&error); /*FIXME don't raise here */
12746 check_array_for_usertypes (mb->parameters, &error);
12747 mono_error_raise_exception (&error); /*FIXME don't raise here */
12748 if (mb->param_modreq)
12749 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12750 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12751 mono_error_raise_exception (&error); /*FIXME don't raise here */
12753 if (mb->param_modopt)
12754 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12755 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12756 mono_error_raise_exception (&error); /*FIXME don't raise here */
12762 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12763 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12765 check_array_for_usertypes (mb->parameters, &error);
12766 mono_error_raise_exception (&error); /*FIXME don't raise here */
12767 if (mb->param_modreq)
12768 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12769 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12770 mono_error_raise_exception (&error); /*FIXME don't raise here */
12772 if (mb->param_modopt)
12773 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12774 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12775 mono_error_raise_exception (&error); /*FIXME don't raise here */
12781 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12784 * we need to lock the domain because the lock will be taken inside
12785 * So, we need to keep the locking order correct.
12787 mono_loader_lock ();
12788 mono_domain_lock (domain);
12789 if (klass->wastypebuilder) {
12790 mono_domain_unlock (domain);
12791 mono_loader_unlock ();
12793 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12794 mono_error_raise_exception (&error); /* FIXME don't raise here */
12799 * Fields to set in klass:
12800 * the various flags: delegate/unicode/contextbound etc.
12802 klass->flags = tb->attrs;
12803 klass->has_cctor = 1;
12804 klass->has_finalize = 1;
12805 klass->has_finalize_inited = 1;
12807 mono_class_setup_parent (klass, klass->parent);
12808 /* fool mono_class_setup_supertypes */
12809 klass->supertypes = NULL;
12810 mono_class_setup_supertypes (klass);
12811 mono_class_setup_mono_type (klass);
12814 if (!((MonoDynamicImage*)klass->image)->run) {
12815 if (klass->generic_container) {
12816 /* FIXME: The code below can't handle generic classes */
12817 klass->wastypebuilder = TRUE;
12818 mono_loader_unlock ();
12819 mono_domain_unlock (domain);
12821 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12822 mono_error_raise_exception (&error); /* FIXME don't raise here */
12829 /* enums are done right away */
12830 if (!klass->enumtype)
12831 if (!ensure_runtime_vtable (klass, &error))
12834 if (tb->subtypes) {
12835 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12836 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12837 mono_class_alloc_ext (klass);
12838 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12839 if (!is_ok (&error)) goto failure;
12840 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12844 klass->nested_classes_inited = TRUE;
12846 /* fields and object layout */
12847 if (klass->parent) {
12848 if (!klass->parent->size_inited)
12849 mono_class_init (klass->parent);
12850 klass->instance_size = klass->parent->instance_size;
12851 klass->sizes.class_size = 0;
12852 klass->min_align = klass->parent->min_align;
12853 /* if the type has no fields we won't call the field_setup
12854 * routine which sets up klass->has_references.
12856 klass->has_references |= klass->parent->has_references;
12858 klass->instance_size = sizeof (MonoObject);
12859 klass->min_align = 1;
12862 /* FIXME: handle packing_size and instance_size */
12863 typebuilder_setup_fields (klass, &error);
12864 if (!mono_error_ok (&error))
12866 typebuilder_setup_properties (klass, &error);
12867 if (!mono_error_ok (&error))
12870 typebuilder_setup_events (klass, &error);
12871 if (!mono_error_ok (&error))
12874 klass->wastypebuilder = TRUE;
12877 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12878 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12879 * we want to return normal System.MonoType objects, so clear these out from the cache.
12881 * Together with this we must ensure the contents of all instances to match the created type.
12883 if (domain->type_hash && klass->generic_container)
12884 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12886 mono_domain_unlock (domain);
12887 mono_loader_unlock ();
12889 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12890 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12891 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12894 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12895 mono_error_raise_exception (&error); /* FIXME don't raise here */
12897 g_assert (res != (MonoReflectionType*)tb);
12902 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12903 klass->wastypebuilder = TRUE;
12904 mono_domain_unlock (domain);
12905 mono_loader_unlock ();
12906 mono_error_raise_exception (&error);
12911 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12913 MonoGenericParamFull *param;
12918 image = &gparam->tbuilder->module->dynamic_image->image;
12920 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12922 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12923 g_assert (mono_error_ok (&error));
12924 param->param.num = gparam->index;
12926 if (gparam->mbuilder) {
12927 if (!gparam->mbuilder->generic_container) {
12928 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12929 mono_error_raise_exception (&error); /* FIXME don't raise here */
12931 MonoClass *klass = mono_class_from_mono_type (tb);
12932 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12933 gparam->mbuilder->generic_container->is_method = TRUE;
12935 * Cannot set owner.method, since the MonoMethod is not created yet.
12936 * Set the image field instead, so type_in_image () works.
12938 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12939 gparam->mbuilder->generic_container->owner.image = klass->image;
12941 param->param.owner = gparam->mbuilder->generic_container;
12942 } else if (gparam->tbuilder) {
12943 if (!gparam->tbuilder->generic_container) {
12944 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12945 mono_error_raise_exception (&error); /* FIXME don't raise here */
12946 MonoClass *klass = mono_class_from_mono_type (tb);
12947 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12948 gparam->tbuilder->generic_container->owner.klass = klass;
12950 param->param.owner = gparam->tbuilder->generic_container;
12953 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12955 gparam->type.type = &pklass->byval_arg;
12957 mono_class_set_ref_info (pklass, gparam);
12958 mono_image_append_class_to_reflection_info_set (pklass);
12962 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12965 MonoReflectionModuleBuilder *module = sig->module;
12966 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12967 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12972 check_array_for_usertypes (sig->arguments, &error);
12973 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12975 sigbuffer_init (&buf, 32);
12977 sigbuffer_add_value (&buf, 0x07);
12978 sigbuffer_add_value (&buf, na);
12979 if (assembly != NULL){
12980 for (i = 0; i < na; ++i) {
12981 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12982 encode_reflection_type (assembly, type, &buf, &error);
12983 if (!is_ok (&error)) goto fail;
12987 buflen = buf.p - buf.buf;
12988 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12989 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12990 sigbuffer_free (&buf);
12993 sigbuffer_free (&buf);
12994 mono_error_raise_exception (&error); /* FIXME don't raise here */
12999 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13002 MonoDynamicImage *assembly = sig->module->dynamic_image;
13003 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13008 check_array_for_usertypes (sig->arguments, &error);
13009 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13011 sigbuffer_init (&buf, 32);
13013 sigbuffer_add_value (&buf, 0x06);
13014 for (i = 0; i < na; ++i) {
13015 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13016 encode_reflection_type (assembly, type, &buf, &error);
13017 if (!is_ok (&error))
13021 buflen = buf.p - buf.buf;
13022 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13023 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13024 sigbuffer_free (&buf);
13028 sigbuffer_free (&buf);
13029 mono_error_raise_exception (&error); /* FIXME don't raise here */
13034 MonoMethod *handle;
13035 MonoDomain *domain;
13036 } DynamicMethodReleaseData;
13039 * The runtime automatically clean up those after finalization.
13041 static MonoReferenceQueue *dynamic_method_queue;
13044 free_dynamic_method (void *dynamic_method)
13046 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13047 MonoDomain *domain = data->domain;
13048 MonoMethod *method = data->handle;
13051 mono_domain_lock (domain);
13052 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13053 g_hash_table_remove (domain->method_to_dyn_method, method);
13054 mono_domain_unlock (domain);
13055 g_assert (dis_link);
13056 mono_gchandle_free (dis_link);
13058 mono_runtime_free_method (domain, method);
13063 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13066 MonoReferenceQueue *queue;
13067 MonoMethod *handle;
13068 DynamicMethodReleaseData *release_data;
13069 ReflectionMethodBuilder rmb;
13070 MonoMethodSignature *sig;
13072 MonoDomain *domain;
13076 if (mono_runtime_is_shutting_down ())
13077 mono_raise_exception (mono_get_exception_invalid_operation (""));
13079 if (!(queue = dynamic_method_queue)) {
13080 mono_loader_lock ();
13081 if (!(queue = dynamic_method_queue))
13082 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13083 mono_loader_unlock ();
13086 sig = dynamic_method_to_signature (mb);
13088 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13091 * Resolve references.
13094 * Every second entry in the refs array is reserved for storing handle_class,
13095 * which is needed by the ldtoken implementation in the JIT.
13097 rmb.nrefs = mb->nrefs;
13098 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13099 for (i = 0; i < mb->nrefs; i += 2) {
13100 MonoClass *handle_class;
13102 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13104 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13105 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13107 * The referenced DynamicMethod should already be created by the managed
13108 * code, except in the case of circular references. In that case, we store
13109 * method in the refs array, and fix it up later when the referenced
13110 * DynamicMethod is created.
13112 if (method->mhandle) {
13113 ref = method->mhandle;
13115 /* FIXME: GC object stored in unmanaged memory */
13118 /* FIXME: GC object stored in unmanaged memory */
13119 method->referenced_by = g_slist_append (method->referenced_by, mb);
13121 handle_class = mono_defaults.methodhandle_class;
13123 MonoException *ex = NULL;
13124 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13126 ex = mono_get_exception_type_load (NULL, NULL);
13127 else if (mono_security_core_clr_enabled ())
13128 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13132 mono_raise_exception (ex);
13137 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13138 rmb.refs [i + 1] = handle_class;
13142 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13143 if (!is_ok (&error)) {
13145 mono_error_raise_exception (&error); /* FIXME don't raise here */
13147 klass = mono_class_from_mono_type (owner_type);
13149 klass = mono_defaults.object_class;
13152 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13153 release_data = g_new (DynamicMethodReleaseData, 1);
13154 release_data->handle = handle;
13155 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13156 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13157 g_free (release_data);
13159 /* Fix up refs entries pointing at us */
13160 for (l = mb->referenced_by; l; l = l->next) {
13161 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13162 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13165 g_assert (method->mhandle);
13167 data = (gpointer*)wrapper->method_data;
13168 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13169 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13170 data [i + 1] = mb->mhandle;
13173 g_slist_free (mb->referenced_by);
13177 /* ilgen is no longer needed */
13180 domain = mono_domain_get ();
13181 mono_domain_lock (domain);
13182 if (!domain->method_to_dyn_method)
13183 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13184 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13185 mono_domain_unlock (domain);
13188 #endif /* DISABLE_REFLECTION_EMIT */
13192 * mono_reflection_is_valid_dynamic_token:
13194 * Returns TRUE if token is valid.
13198 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13200 return lookup_dyn_token (image, token) != NULL;
13203 MonoMethodSignature *
13204 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13206 MonoMethodSignature *sig;
13207 g_assert (image_is_dynamic (image));
13209 mono_error_init (error);
13211 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13215 return mono_method_signature_checked (method, error);
13218 #ifndef DISABLE_REFLECTION_EMIT
13221 * mono_reflection_lookup_dynamic_token:
13223 * Finish the Builder object pointed to by TOKEN and return the corresponding
13224 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13225 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13228 * LOCKING: Take the loader lock
13231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13233 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13237 obj = lookup_dyn_token (assembly, token);
13240 g_error ("Could not find required dynamic token 0x%08x", token);
13246 handle_class = &klass;
13247 return resolve_object (image, obj, handle_class, context);
13251 * ensure_complete_type:
13253 * Ensure that KLASS is completed if it is a dynamic type, or references
13257 ensure_complete_type (MonoClass *klass)
13261 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13262 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13264 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13265 mono_error_raise_exception (&error); /* FIXME don't raise here */
13267 // Asserting here could break a lot of code
13268 //g_assert (klass->wastypebuilder);
13271 if (klass->generic_class) {
13272 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13275 for (i = 0; i < inst->type_argc; ++i) {
13276 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13282 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13285 gpointer result = NULL;
13287 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13288 result = mono_string_intern_checked ((MonoString*)obj, &error);
13289 mono_error_raise_exception (&error); /* FIXME don't raise here */
13290 *handle_class = mono_defaults.string_class;
13292 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13293 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13294 mono_error_raise_exception (&error); /* FIXME don't raise here */
13295 MonoClass *mc = mono_class_from_mono_type (type);
13296 if (!mono_class_init (mc))
13297 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13300 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13301 mono_error_raise_exception (&error); /* FIXME don't raise here */
13303 result = mono_class_from_mono_type (inflated);
13304 mono_metadata_free_type (inflated);
13306 result = mono_class_from_mono_type (type);
13308 *handle_class = mono_defaults.typehandle_class;
13310 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13311 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13312 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13313 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13314 result = ((MonoReflectionMethod*)obj)->method;
13317 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13318 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13320 *handle_class = mono_defaults.methodhandle_class;
13322 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13323 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13324 result = mb->mhandle;
13326 /* Type is not yet created */
13327 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13329 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13330 mono_error_raise_exception (&error); /* FIXME don't raise here */
13333 * Hopefully this has been filled in by calling CreateType() on the
13337 * TODO: This won't work if the application finishes another
13338 * TypeBuilder instance instead of this one.
13340 result = mb->mhandle;
13344 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13345 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13347 *handle_class = mono_defaults.methodhandle_class;
13348 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13349 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13351 result = cb->mhandle;
13353 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13355 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13356 mono_error_raise_exception (&error); /* FIXME don't raise here */
13357 result = cb->mhandle;
13361 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13362 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13364 *handle_class = mono_defaults.methodhandle_class;
13365 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13366 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13368 ensure_complete_type (field->parent);
13370 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13371 mono_error_raise_exception (&error); /* FIXME don't raise here */
13373 MonoClass *klass = mono_class_from_mono_type (inflated);
13374 MonoClassField *inflated_field;
13375 gpointer iter = NULL;
13376 mono_metadata_free_type (inflated);
13377 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13378 if (!strcmp (field->name, inflated_field->name))
13381 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13382 result = inflated_field;
13386 *handle_class = mono_defaults.fieldhandle_class;
13388 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13389 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13390 result = fb->handle;
13393 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13395 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13396 mono_error_raise_exception (&error); /* FIXME don't raise here */
13397 result = fb->handle;
13400 if (fb->handle && fb->handle->parent->generic_container) {
13401 MonoClass *klass = fb->handle->parent;
13402 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13403 mono_error_raise_exception (&error); /* FIXME don't raise here */
13405 MonoClass *inflated = mono_class_from_mono_type (type);
13407 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13409 mono_metadata_free_type (type);
13411 *handle_class = mono_defaults.fieldhandle_class;
13412 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13414 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13415 mono_error_raise_exception (&error); /* FIXME don't raise here */
13418 klass = type->data.klass;
13419 if (klass->wastypebuilder) {
13420 /* Already created */
13424 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13425 mono_error_raise_exception (&error); /* FIXME don't raise here */
13426 result = type->data.klass;
13429 *handle_class = mono_defaults.typehandle_class;
13430 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13431 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13432 MonoMethodSignature *sig;
13435 if (helper->arguments)
13436 nargs = mono_array_length (helper->arguments);
13440 sig = mono_metadata_signature_alloc (image, nargs);
13441 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13442 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13444 if (helper->unmanaged_call_conv) { /* unmanaged */
13445 sig->call_convention = helper->unmanaged_call_conv - 1;
13446 sig->pinvoke = TRUE;
13447 } else if (helper->call_conv & 0x02) {
13448 sig->call_convention = MONO_CALL_VARARG;
13450 sig->call_convention = MONO_CALL_DEFAULT;
13453 sig->param_count = nargs;
13454 /* TODO: Copy type ? */
13455 sig->ret = helper->return_type->type;
13456 for (i = 0; i < nargs; ++i) {
13457 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13458 mono_error_raise_exception (&error); /* FIXME don't raise here */
13462 *handle_class = NULL;
13463 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13464 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13465 /* Already created by the managed code */
13466 g_assert (method->mhandle);
13467 result = method->mhandle;
13468 *handle_class = mono_defaults.methodhandle_class;
13469 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13470 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13471 mono_error_raise_exception (&error); /* FIXME don't raise here */
13472 type = mono_class_inflate_generic_type_checked (type, context, &error);
13473 mono_error_raise_exception (&error); /* FIXME don't raise here */
13475 result = mono_class_from_mono_type (type);
13476 *handle_class = mono_defaults.typehandle_class;
13478 mono_metadata_free_type (type);
13479 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13480 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13481 mono_error_raise_exception (&error); /* FIXME don't raise here */
13482 type = mono_class_inflate_generic_type_checked (type, context, &error);
13483 mono_error_raise_exception (&error); /* FIXME don't raise here */
13485 result = mono_class_from_mono_type (type);
13486 *handle_class = mono_defaults.typehandle_class;
13488 mono_metadata_free_type (type);
13489 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13490 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13491 MonoClass *inflated;
13493 MonoClassField *field;
13495 if (is_sre_field_builder (mono_object_class (f->fb)))
13496 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13497 else if (is_sr_mono_field (mono_object_class (f->fb)))
13498 field = ((MonoReflectionField*)f->fb)->field;
13500 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)));
13502 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13503 mono_error_raise_exception (&error); /* FIXME don't raise here */
13504 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13505 mono_error_raise_exception (&error); /* FIXME don't raise here */
13507 inflated = mono_class_from_mono_type (type);
13509 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13510 ensure_complete_type (field->parent);
13512 mono_metadata_free_type (type);
13513 *handle_class = mono_defaults.fieldhandle_class;
13514 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13515 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13516 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13517 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13519 mono_error_raise_exception (&error); /* FIXME don't raise here */
13521 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13522 MonoMethod *method;
13524 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13525 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13526 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13527 method = ((MonoReflectionMethod *)c->cb)->method;
13529 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)));
13531 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13532 *handle_class = mono_defaults.methodhandle_class;
13533 mono_metadata_free_type (type);
13534 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13535 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13536 if (m->method_args) {
13537 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13538 mono_error_raise_exception (&error); /* FIXME don't raise here */
13540 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13541 mono_error_assert_ok (&error);
13544 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13545 mono_error_raise_exception (&error); /* FIXME don't raise here */
13546 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13547 mono_error_raise_exception (&error); /* FIXME don't raise here */
13549 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13550 MonoMethod *method;
13552 if (is_sre_method_builder (mono_object_class (m->mb)))
13553 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13554 else if (is_sr_mono_method (mono_object_class (m->mb)))
13555 method = ((MonoReflectionMethod *)m->mb)->method;
13557 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)));
13559 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13560 mono_metadata_free_type (type);
13562 *handle_class = mono_defaults.methodhandle_class;
13563 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13564 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13567 MonoMethod *method;
13571 mtype = mono_reflection_type_get_handle (m->parent, &error);
13572 mono_error_raise_exception (&error); /* FIXME don't raise here */
13573 klass = mono_class_from_mono_type (mtype);
13575 /* Find the method */
13577 name = mono_string_to_utf8 (m->name);
13579 while ((method = mono_class_get_methods (klass, &iter))) {
13580 if (!strcmp (method->name, name))
13587 // FIXME: Check parameters/return value etc. match
13590 *handle_class = mono_defaults.methodhandle_class;
13591 } else if (is_sre_array (mono_object_get_class(obj)) ||
13592 is_sre_byref (mono_object_get_class(obj)) ||
13593 is_sre_pointer (mono_object_get_class(obj))) {
13594 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13595 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13596 mono_error_raise_exception (&error); /* FIXME don't raise here */
13599 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13600 mono_error_raise_exception (&error); /* FIXME don't raise here */
13602 result = mono_class_from_mono_type (inflated);
13603 mono_metadata_free_type (inflated);
13605 result = mono_class_from_mono_type (type);
13607 *handle_class = mono_defaults.typehandle_class;
13609 g_print ("%s\n", obj->vtable->klass->name);
13610 g_assert_not_reached ();
13615 #else /* DISABLE_REFLECTION_EMIT */
13618 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13620 g_assert_not_reached ();
13625 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13627 g_assert_not_reached ();
13631 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13633 g_assert_not_reached ();
13637 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13639 g_assert_not_reached ();
13643 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13645 g_assert_not_reached ();
13649 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13651 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13655 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13657 g_assert_not_reached ();
13661 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13663 g_assert_not_reached ();
13666 MonoReflectionModule *
13667 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13669 g_assert_not_reached ();
13674 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13676 g_assert_not_reached ();
13681 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13683 g_assert_not_reached ();
13688 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13689 gboolean create_open_instance, gboolean register_token, MonoError *error)
13691 g_assert_not_reached ();
13696 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13701 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13703 g_assert_not_reached ();
13707 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13710 *num_overrides = 0;
13713 MonoReflectionEvent *
13714 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13716 g_assert_not_reached ();
13720 MonoReflectionType*
13721 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13723 g_assert_not_reached ();
13728 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13730 g_assert_not_reached ();
13734 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13736 g_assert_not_reached ();
13741 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13743 g_assert_not_reached ();
13748 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13753 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13759 mono_reflection_type_get_handle (MonoReflectionType* ref)
13767 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13769 g_assert_not_reached ();
13772 #endif /* DISABLE_REFLECTION_EMIT */
13774 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13775 const static guint32 declsec_flags_map[] = {
13776 0x00000000, /* empty */
13777 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13778 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13779 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13780 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13781 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13782 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13783 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13784 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13785 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13786 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13787 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13788 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13789 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13790 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13791 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13792 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13793 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13794 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13798 * Returns flags that includes all available security action associated to the handle.
13799 * @token: metadata token (either for a class or a method)
13800 * @image: image where resides the metadata.
13803 mono_declsec_get_flags (MonoImage *image, guint32 token)
13805 int index = mono_metadata_declsec_from_index (image, token);
13806 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13807 guint32 result = 0;
13811 /* HasSecurity can be present for other, not specially encoded, attributes,
13812 e.g. SuppressUnmanagedCodeSecurityAttribute */
13816 for (i = index; i < t->rows; i++) {
13817 guint32 cols [MONO_DECL_SECURITY_SIZE];
13819 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13820 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13823 action = cols [MONO_DECL_SECURITY_ACTION];
13824 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13825 result |= declsec_flags_map [action];
13827 g_assert_not_reached ();
13834 * Get the security actions (in the form of flags) associated with the specified method.
13836 * @method: The method for which we want the declarative security flags.
13837 * Return the declarative security flags for the method (only).
13839 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13840 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13843 mono_declsec_flags_from_method (MonoMethod *method)
13845 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13846 /* FIXME: No cache (for the moment) */
13847 guint32 idx = mono_method_get_index (method);
13848 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13849 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13850 return mono_declsec_get_flags (method->klass->image, idx);
13856 * Get the security actions (in the form of flags) associated with the specified class.
13858 * @klass: The class for which we want the declarative security flags.
13859 * Return the declarative security flags for the class.
13861 * Note: We cache the flags inside the MonoClass structure as this will get
13862 * called very often (at least for each method).
13865 mono_declsec_flags_from_class (MonoClass *klass)
13867 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13868 if (!klass->ext || !klass->ext->declsec_flags) {
13871 idx = mono_metadata_token_index (klass->type_token);
13872 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13873 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13874 mono_loader_lock ();
13875 mono_class_alloc_ext (klass);
13876 mono_loader_unlock ();
13877 /* we cache the flags on classes */
13878 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13880 return klass->ext->declsec_flags;
13886 * Get the security actions (in the form of flags) associated with the specified assembly.
13888 * @assembly: The assembly for which we want the declarative security flags.
13889 * Return the declarative security flags for the assembly.
13892 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13894 guint32 idx = 1; /* there is only one assembly */
13895 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13896 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13897 return mono_declsec_get_flags (assembly->image, idx);
13902 * Fill actions for the specific index (which may either be an encoded class token or
13903 * an encoded method token) from the metadata image.
13904 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13907 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13908 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13910 MonoBoolean result = FALSE;
13912 guint32 cols [MONO_DECL_SECURITY_SIZE];
13913 int index = mono_metadata_declsec_from_index (image, token);
13916 t = &image->tables [MONO_TABLE_DECLSECURITY];
13917 for (i = index; i < t->rows; i++) {
13918 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13920 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13923 /* if present only replace (class) permissions with method permissions */
13924 /* if empty accept either class or method permissions */
13925 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13926 if (!actions->demand.blob) {
13927 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13928 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13929 actions->demand.blob = (char*) (blob + 2);
13930 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13933 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13934 if (!actions->noncasdemand.blob) {
13935 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13936 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13937 actions->noncasdemand.blob = (char*) (blob + 2);
13938 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13941 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13942 if (!actions->demandchoice.blob) {
13943 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13944 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13945 actions->demandchoice.blob = (char*) (blob + 2);
13946 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13956 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13957 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13959 guint32 idx = mono_metadata_token_index (klass->type_token);
13960 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13961 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13962 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13966 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13967 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13969 guint32 idx = mono_method_get_index (method);
13970 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13971 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13972 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13976 * Collect all actions (that requires to generate code in mini) assigned for
13977 * the specified method.
13978 * Note: Don't use the content of actions if the function return FALSE.
13981 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13983 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13984 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13985 MonoBoolean result = FALSE;
13988 /* quick exit if no declarative security is present in the metadata */
13989 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13992 /* we want the original as the wrapper is "free" of the security informations */
13993 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13994 method = mono_marshal_method_from_wrapper (method);
13999 /* First we look for method-level attributes */
14000 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14001 mono_class_init (method->klass);
14002 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14004 result = mono_declsec_get_method_demands_params (method, demands,
14005 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14008 /* Here we use (or create) the class declarative cache to look for demands */
14009 flags = mono_declsec_flags_from_class (method->klass);
14010 if (flags & mask) {
14012 mono_class_init (method->klass);
14013 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14015 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14016 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14019 /* The boolean return value is used as a shortcut in case nothing needs to
14020 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14026 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14028 * Note: Don't use the content of actions if the function return FALSE.
14031 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14033 MonoBoolean result = FALSE;
14036 /* quick exit if no declarative security is present in the metadata */
14037 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14040 /* we want the original as the wrapper is "free" of the security informations */
14041 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14042 method = mono_marshal_method_from_wrapper (method);
14047 /* results are independant - zeroize both */
14048 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14049 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14051 /* First we look for method-level attributes */
14052 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14053 mono_class_init (method->klass);
14055 result = mono_declsec_get_method_demands_params (method, cmethod,
14056 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14059 /* Here we use (or create) the class declarative cache to look for demands */
14060 flags = mono_declsec_flags_from_class (method->klass);
14061 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14062 mono_class_init (method->klass);
14064 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14065 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14072 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14074 * @klass The inherited class - this is the class that provides the security check (attributes)
14076 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14078 * Note: Don't use the content of actions if the function return FALSE.
14081 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14083 MonoBoolean result = FALSE;
14086 /* quick exit if no declarative security is present in the metadata */
14087 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14090 /* Here we use (or create) the class declarative cache to look for demands */
14091 flags = mono_declsec_flags_from_class (klass);
14092 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14093 mono_class_init (klass);
14094 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14096 result |= mono_declsec_get_class_demands_params (klass, demands,
14097 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14104 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14106 * Note: Don't use the content of actions if the function return FALSE.
14109 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14111 /* quick exit if no declarative security is present in the metadata */
14112 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14115 /* we want the original as the wrapper is "free" of the security informations */
14116 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14117 method = mono_marshal_method_from_wrapper (method);
14122 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14123 mono_class_init (method->klass);
14124 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14126 return mono_declsec_get_method_demands_params (method, demands,
14127 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14134 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14136 guint32 cols [MONO_DECL_SECURITY_SIZE];
14140 int index = mono_metadata_declsec_from_index (image, token);
14144 t = &image->tables [MONO_TABLE_DECLSECURITY];
14145 for (i = index; i < t->rows; i++) {
14146 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14148 /* shortcut - index are ordered */
14149 if (token != cols [MONO_DECL_SECURITY_PARENT])
14152 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14153 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14154 entry->blob = (char*) (metadata + 2);
14155 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14164 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14166 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14167 guint32 idx = mono_method_get_index (method);
14168 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14169 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14170 return get_declsec_action (method->klass->image, idx, action, entry);
14176 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14179 guint32 flags = mono_declsec_flags_from_class (klass);
14180 if (declsec_flags_map [action] & flags) {
14181 guint32 idx = mono_metadata_token_index (klass->type_token);
14182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14183 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14184 return get_declsec_action (klass->image, idx, action, entry);
14190 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14192 guint32 idx = 1; /* there is only one assembly */
14193 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14194 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14196 return get_declsec_action (assembly->image, idx, action, entry);
14200 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14203 MonoObject *res, *exc;
14205 static MonoMethod *method = NULL;
14207 if (method == NULL) {
14208 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14213 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14214 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14216 g_assert (mono_class_get_ref_info (klass));
14217 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14219 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14220 mono_error_raise_exception (&error); /* FIXME don't raise here */
14222 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14224 if (exc || !mono_error_ok (&error)) {
14225 mono_error_cleanup (&error);
14228 return *(MonoBoolean*)mono_object_unbox (res);
14232 * mono_reflection_type_get_type:
14233 * @reftype: the System.Type object
14235 * Returns the MonoType* associated with the C# System.Type object @reftype.
14238 mono_reflection_type_get_type (MonoReflectionType *reftype)
14240 g_assert (reftype);
14243 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14244 mono_error_assert_ok (&error);
14249 * mono_reflection_assembly_get_assembly:
14250 * @refassembly: the System.Reflection.Assembly object
14252 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14255 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14257 g_assert (refassembly);
14259 return refassembly->assembly;